diff options
Diffstat (limited to 'drivers')
222 files changed, 2701 insertions, 1789 deletions
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index c29c2c3ec0ad..b06f5f55ada9 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -170,6 +170,9 @@ static int acpi_processor_hotadd_init(struct acpi_processor *pr) acpi_status status; int ret; + if (pr->apic_id == -1) + return -ENODEV; + status = acpi_evaluate_integer(pr->handle, "_STA", NULL, &sta); if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT)) return -ENODEV; @@ -260,10 +263,8 @@ static int acpi_processor_get_info(struct acpi_device *device) } apic_id = acpi_get_apicid(pr->handle, device_declaration, pr->acpi_id); - if (apic_id < 0) { + if (apic_id < 0) acpi_handle_debug(pr->handle, "failed to get CPU APIC ID.\n"); - return -ENODEV; - } pr->apic_id = apic_id; cpu_index = acpi_map_cpuid(pr->apic_id, pr->acpi_id); diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index d7d32c28829b..ad11ba4a412d 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -206,13 +206,13 @@ unlock: spin_unlock_irqrestore(&ec->lock, flags); } -static int acpi_ec_sync_query(struct acpi_ec *ec); +static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data); static int ec_check_sci_sync(struct acpi_ec *ec, u8 state) { if (state & ACPI_EC_FLAG_SCI) { if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) - return acpi_ec_sync_query(ec); + return acpi_ec_sync_query(ec, NULL); } return 0; } @@ -443,10 +443,8 @@ acpi_handle ec_get_handle(void) EXPORT_SYMBOL(ec_get_handle); -static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 *data); - /* - * Clears stale _Q events that might have accumulated in the EC. + * Process _Q events that might have accumulated in the EC. * Run with locked ec mutex. */ static void acpi_ec_clear(struct acpi_ec *ec) @@ -455,7 +453,7 @@ static void acpi_ec_clear(struct acpi_ec *ec) u8 value = 0; for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) { - status = acpi_ec_query_unlocked(ec, &value); + status = acpi_ec_sync_query(ec, &value); if (status || !value) break; } @@ -582,13 +580,18 @@ static void acpi_ec_run(void *cxt) kfree(handler); } -static int acpi_ec_sync_query(struct acpi_ec *ec) +static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data) { u8 value = 0; int status; struct acpi_ec_query_handler *handler, *copy; - if ((status = acpi_ec_query_unlocked(ec, &value))) + + status = acpi_ec_query_unlocked(ec, &value); + if (data) + *data = value; + if (status) return status; + list_for_each_entry(handler, &ec->list, node) { if (value == handler->query_bit) { /* have custom handler for this bit */ @@ -612,7 +615,7 @@ static void acpi_ec_gpe_query(void *ec_cxt) if (!ec) return; mutex_lock(&ec->mutex); - acpi_ec_sync_query(ec); + acpi_ec_sync_query(ec, NULL); mutex_unlock(&ec->mutex); } diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 8986b9f22781..62ec61e8f84a 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -52,6 +52,7 @@ static DEFINE_MUTEX(deferred_probe_mutex); static LIST_HEAD(deferred_probe_pending_list); static LIST_HEAD(deferred_probe_active_list); static struct workqueue_struct *deferred_wq; +static atomic_t deferred_trigger_count = ATOMIC_INIT(0); /** * deferred_probe_work_func() - Retry probing devices in the active list. @@ -135,6 +136,17 @@ static bool driver_deferred_probe_enable = false; * This functions moves all devices from the pending list to the active * list and schedules the deferred probe workqueue to process them. It * should be called anytime a driver is successfully bound to a device. + * + * Note, there is a race condition in multi-threaded probe. In the case where + * more than one device is probing at the same time, it is possible for one + * probe to complete successfully while another is about to defer. If the second + * depends on the first, then it will get put on the pending list after the + * trigger event has already occured and will be stuck there. + * + * The atomic 'deferred_trigger_count' is used to determine if a successful + * trigger has occurred in the midst of probing a driver. If the trigger count + * changes in the midst of a probe, then deferred processing should be triggered + * again. */ static void driver_deferred_probe_trigger(void) { @@ -147,6 +159,7 @@ static void driver_deferred_probe_trigger(void) * into the active list so they can be retried by the workqueue */ mutex_lock(&deferred_probe_mutex); + atomic_inc(&deferred_trigger_count); list_splice_tail_init(&deferred_probe_pending_list, &deferred_probe_active_list); mutex_unlock(&deferred_probe_mutex); @@ -265,6 +278,7 @@ static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue); static int really_probe(struct device *dev, struct device_driver *drv) { int ret = 0; + int local_trigger_count = atomic_read(&deferred_trigger_count); atomic_inc(&probe_count); pr_debug("bus: '%s': %s: probing driver %s with device %s\n", @@ -310,6 +324,9 @@ probe_failed: /* Driver requested deferred probing */ dev_info(dev, "Driver %s requests probe deferral\n", drv->name); driver_deferred_probe_add(dev); + /* Did a trigger occur while probing? Need to re-trigger if yes */ + if (local_trigger_count != atomic_read(&deferred_trigger_count)) + driver_deferred_probe_trigger(); } else if (ret != -ENODEV && ret != -ENXIO) { /* driver matched but the probe failed */ printk(KERN_WARNING diff --git a/drivers/base/platform.c b/drivers/base/platform.c index e714709704e4..5b47210889e0 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -13,6 +13,7 @@ #include <linux/string.h> #include <linux/platform_device.h> #include <linux/of_device.h> +#include <linux/of_irq.h> #include <linux/module.h> #include <linux/init.h> #include <linux/dma-mapping.h> @@ -87,7 +88,11 @@ int platform_get_irq(struct platform_device *dev, unsigned int num) return -ENXIO; return dev->archdata.irqs[num]; #else - struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num); + struct resource *r; + if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) + return of_irq_get(dev->dev.of_node, num); + + r = platform_get_resource(dev, IORESOURCE_IRQ, num); return r ? r->start : -ENXIO; #endif diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 8f5565bf34cd..fa9bb742df6e 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3067,7 +3067,10 @@ static int raw_cmd_copyout(int cmd, void __user *param, int ret; while (ptr) { - ret = copy_to_user(param, ptr, sizeof(*ptr)); + struct floppy_raw_cmd cmd = *ptr; + cmd.next = NULL; + cmd.kernel_data = NULL; + ret = copy_to_user(param, &cmd, sizeof(cmd)); if (ret) return -EFAULT; param += sizeof(struct floppy_raw_cmd); @@ -3121,10 +3124,11 @@ loop: return -ENOMEM; *rcmd = ptr; ret = copy_from_user(ptr, param, sizeof(*ptr)); - if (ret) - return -EFAULT; ptr->next = NULL; ptr->buffer_length = 0; + ptr->kernel_data = NULL; + if (ret) + return -EFAULT; param += sizeof(struct floppy_raw_cmd); if (ptr->cmd_count > 33) /* the command may now also take up the space @@ -3140,7 +3144,6 @@ loop: for (i = 0; i < 16; i++) ptr->reply[i] = 0; ptr->resultcode = 0; - ptr->kernel_data = NULL; if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) { if (ptr->length <= 0) diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index be571fef185d..a83b57e57b63 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -82,6 +82,7 @@ static const struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x04CA, 0x3004) }, { USB_DEVICE(0x04CA, 0x3005) }, { USB_DEVICE(0x04CA, 0x3006) }, + { USB_DEVICE(0x04CA, 0x3007) }, { USB_DEVICE(0x04CA, 0x3008) }, { USB_DEVICE(0x04CA, 0x300b) }, { USB_DEVICE(0x0930, 0x0219) }, @@ -131,6 +132,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index f338b0c5a8de..a7dfbf9a3afb 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -152,6 +152,7 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, @@ -1485,10 +1486,8 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_BCM92035) hdev->setup = btusb_setup_bcm92035; - if (id->driver_info & BTUSB_INTEL) { - usb_enable_autosuspend(data->udev); + if (id->driver_info & BTUSB_INTEL) hdev->setup = btusb_setup_intel; - } /* Interface numbers are hardcoded in the specification */ data->isoc = usb_ifnum_to_if(data->udev, 1); diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index 293e2e0a0a87..00b73448b22e 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c @@ -56,6 +56,7 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/debugfs.h> +#include <linux/log2.h> /* * DDR target is the same on all platforms. @@ -222,12 +223,6 @@ static int mvebu_mbus_window_conflicts(struct mvebu_mbus_state *mbus, */ if ((u64)base < wend && end > wbase) return 0; - - /* - * Check if target/attribute conflicts - */ - if (target == wtarget && attr == wattr) - return 0; } return 1; @@ -266,6 +261,17 @@ static int mvebu_mbus_setup_window(struct mvebu_mbus_state *mbus, mbus->soc->win_cfg_offset(win); u32 ctrl, remap_addr; + if (!is_power_of_2(size)) { + WARN(true, "Invalid MBus window size: 0x%zx\n", size); + return -EINVAL; + } + + if ((base & (phys_addr_t)(size - 1)) != 0) { + WARN(true, "Invalid MBus base/size: %pa len 0x%zx\n", &base, + size); + return -EINVAL; + } + ctrl = ((size - 1) & WIN_CTRL_SIZE_MASK) | (attr << WIN_CTRL_ATTR_SHIFT) | (target << WIN_CTRL_TGT_SHIFT) | @@ -413,6 +419,10 @@ static int mvebu_devs_debug_show(struct seq_file *seq, void *v) win, (unsigned long long)wbase, (unsigned long long)(wbase + wsize), wtarget, wattr); + if (!is_power_of_2(wsize) || + ((wbase & (u64)(wsize - 1)) != 0)) + seq_puts(seq, " (Invalid base/size!!)"); + if (win < mbus->soc->num_remappable_wins) { seq_printf(seq, " (remap %016llx)\n", (unsigned long long)wremap); diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c index 8121b4c70ede..b29703324e94 100644 --- a/drivers/char/agp/frontend.c +++ b/drivers/char/agp/frontend.c @@ -730,6 +730,7 @@ static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg) agp_copy_info(agp_bridge, &kerninfo); + memset(&userinfo, 0, sizeof(userinfo)); userinfo.version.major = kerninfo.version.major; userinfo.version.minor = kerninfo.version.minor; userinfo.bridge_id = kerninfo.device->vendor | diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c index a535c7bf8574..422391242b39 100644 --- a/drivers/clk/versatile/clk-vexpress-osc.c +++ b/drivers/clk/versatile/clk-vexpress-osc.c @@ -100,6 +100,8 @@ void __init vexpress_osc_of_setup(struct device_node *node) struct clk *clk; u32 range[2]; + vexpress_sysreg_of_early_init(); + osc = kzalloc(sizeof(*osc), GFP_KERNEL); if (!osc) return; diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 57e823c44d2a..5163ec13429d 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -66,6 +66,7 @@ static int arch_timer_ppi[MAX_TIMER_PPI]; static struct clock_event_device __percpu *arch_timer_evt; static bool arch_timer_use_virtual = true; +static bool arch_timer_c3stop; static bool arch_timer_mem_use_virtual; /* @@ -263,7 +264,8 @@ static void __arch_timer_setup(unsigned type, clk->features = CLOCK_EVT_FEAT_ONESHOT; if (type == ARCH_CP15_TIMER) { - clk->features |= CLOCK_EVT_FEAT_C3STOP; + if (arch_timer_c3stop) + clk->features |= CLOCK_EVT_FEAT_C3STOP; clk->name = "arch_sys_timer"; clk->rating = 450; clk->cpumask = cpumask_of(smp_processor_id()); @@ -665,6 +667,8 @@ static void __init arch_timer_init(struct device_node *np) } } + arch_timer_c3stop = !of_property_read_bool(np, "always-on"); + arch_timer_register(); arch_timer_common_init(); } diff --git a/drivers/clocksource/zevio-timer.c b/drivers/clocksource/zevio-timer.c index ca81809d159d..7ce442148c3f 100644 --- a/drivers/clocksource/zevio-timer.c +++ b/drivers/clocksource/zevio-timer.c @@ -212,4 +212,9 @@ error_free: return ret; } -CLOCKSOURCE_OF_DECLARE(zevio_timer, "lsi,zevio-timer", zevio_timer_add); +static void __init zevio_timer_init(struct device_node *node) +{ + BUG_ON(zevio_timer_add(node)); +} + +CLOCKSOURCE_OF_DECLARE(zevio_timer, "lsi,zevio-timer", zevio_timer_init); diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c index 148d707a1d43..ccdd4c7e748b 100644 --- a/drivers/connector/cn_proc.c +++ b/drivers/connector/cn_proc.c @@ -369,7 +369,7 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg, return; /* Can only change if privileged. */ - if (!capable(CAP_NET_ADMIN)) { + if (!__netlink_ns_capable(nsp, &init_user_ns, CAP_NET_ADMIN)) { err = EPERM; goto out; } diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index d00e5d1abd25..5c4369b5d834 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c @@ -242,7 +242,7 @@ static void do_powersaver(int cx_address, unsigned int mults_index, * Sets a new clock ratio. */ -static void longhaul_setstate(struct cpufreq_policy *policy, +static int longhaul_setstate(struct cpufreq_policy *policy, unsigned int table_index) { unsigned int mults_index; @@ -258,10 +258,12 @@ static void longhaul_setstate(struct cpufreq_policy *policy, /* Safety precautions */ mult = mults[mults_index & 0x1f]; if (mult == -1) - return; + return -EINVAL; + speed = calc_speed(mult); if ((speed > highest_speed) || (speed < lowest_speed)) - return; + return -EINVAL; + /* Voltage transition before frequency transition? */ if (can_scale_voltage && longhaul_index < table_index) dir = 1; @@ -269,8 +271,6 @@ static void longhaul_setstate(struct cpufreq_policy *policy, freqs.old = calc_speed(longhaul_get_cpu_mult()); freqs.new = speed; - cpufreq_freq_transition_begin(policy, &freqs); - pr_debug("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n", fsb, mult/10, mult%10, print_speed(speed/1000)); retry_loop: @@ -385,12 +385,14 @@ retry_loop: goto retry_loop; } } - /* Report true CPU frequency */ - cpufreq_freq_transition_end(policy, &freqs, 0); - if (!bm_timeout) + if (!bm_timeout) { printk(KERN_INFO PFX "Warning: Timeout while waiting for " "idle PCI bus.\n"); + return -EBUSY; + } + + return 0; } /* @@ -631,9 +633,10 @@ static int longhaul_target(struct cpufreq_policy *policy, unsigned int i; unsigned int dir = 0; u8 vid, current_vid; + int retval = 0; if (!can_scale_voltage) - longhaul_setstate(policy, table_index); + retval = longhaul_setstate(policy, table_index); else { /* On test system voltage transitions exceeding single * step up or down were turning motherboard off. Both @@ -648,7 +651,7 @@ static int longhaul_target(struct cpufreq_policy *policy, while (i != table_index) { vid = (longhaul_table[i].driver_data >> 8) & 0x1f; if (vid != current_vid) { - longhaul_setstate(policy, i); + retval = longhaul_setstate(policy, i); current_vid = vid; msleep(200); } @@ -657,10 +660,11 @@ static int longhaul_target(struct cpufreq_policy *policy, else i--; } - longhaul_setstate(policy, table_index); + retval = longhaul_setstate(policy, table_index); } + longhaul_index = table_index; - return 0; + return retval; } @@ -968,7 +972,15 @@ static void __exit longhaul_exit(void) for (i = 0; i < numscales; i++) { if (mults[i] == maxmult) { + struct cpufreq_freqs freqs; + + freqs.old = policy->cur; + freqs.new = longhaul_table[i].frequency; + freqs.flags = 0; + + cpufreq_freq_transition_begin(policy, &freqs); longhaul_setstate(policy, i); + cpufreq_freq_transition_end(policy, &freqs, 0); break; } } diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c index 49f120e1bc7b..78904e6ca4a0 100644 --- a/drivers/cpufreq/powernow-k6.c +++ b/drivers/cpufreq/powernow-k6.c @@ -138,22 +138,14 @@ static void powernow_k6_set_cpu_multiplier(unsigned int best_i) static int powernow_k6_target(struct cpufreq_policy *policy, unsigned int best_i) { - struct cpufreq_freqs freqs; if (clock_ratio[best_i].driver_data > max_multiplier) { printk(KERN_ERR PFX "invalid target frequency\n"); return -EINVAL; } - freqs.old = busfreq * powernow_k6_get_cpu_multiplier(); - freqs.new = busfreq * clock_ratio[best_i].driver_data; - - cpufreq_freq_transition_begin(policy, &freqs); - powernow_k6_set_cpu_multiplier(best_i); - cpufreq_freq_transition_end(policy, &freqs, 0); - return 0; } @@ -227,9 +219,20 @@ have_busfreq: static int powernow_k6_cpu_exit(struct cpufreq_policy *policy) { unsigned int i; - for (i = 0; i < 8; i++) { - if (i == max_multiplier) + + for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) { + if (clock_ratio[i].driver_data == max_multiplier) { + struct cpufreq_freqs freqs; + + freqs.old = policy->cur; + freqs.new = clock_ratio[i].frequency; + freqs.flags = 0; + + cpufreq_freq_transition_begin(policy, &freqs); powernow_k6_target(policy, i); + cpufreq_freq_transition_end(policy, &freqs, 0); + break; + } } return 0; } diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c index f911645c3f6d..e61e224475ad 100644 --- a/drivers/cpufreq/powernow-k7.c +++ b/drivers/cpufreq/powernow-k7.c @@ -269,8 +269,6 @@ static int powernow_target(struct cpufreq_policy *policy, unsigned int index) freqs.new = powernow_table[index].frequency; - cpufreq_freq_transition_begin(policy, &freqs); - /* Now do the magic poking into the MSRs. */ if (have_a0 == 1) /* A0 errata 5 */ @@ -290,8 +288,6 @@ static int powernow_target(struct cpufreq_policy *policy, unsigned int index) if (have_a0 == 1) local_irq_enable(); - cpufreq_freq_transition_end(policy, &freqs, 0); - return 0; } diff --git a/drivers/cpufreq/ppc-corenet-cpufreq.c b/drivers/cpufreq/ppc-corenet-cpufreq.c index a1ca3dd04a8e..0af618abebaf 100644 --- a/drivers/cpufreq/ppc-corenet-cpufreq.c +++ b/drivers/cpufreq/ppc-corenet-cpufreq.c @@ -138,6 +138,7 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy) struct cpufreq_frequency_table *table; struct cpu_data *data; unsigned int cpu = policy->cpu; + u64 transition_latency_hz; np = of_get_cpu_node(cpu, NULL); if (!np) @@ -205,8 +206,10 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy) for_each_cpu(i, per_cpu(cpu_mask, cpu)) per_cpu(cpu_data, i) = data; + transition_latency_hz = 12ULL * NSEC_PER_SEC; policy->cpuinfo.transition_latency = - (12ULL * NSEC_PER_SEC) / fsl_get_sys_freq(); + do_div(transition_latency_hz, fsl_get_sys_freq()); + of_node_put(np); return 0; diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index e930d4fe29c7..1ef5ab9c9d51 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -145,6 +145,7 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, plane->crtc = crtc; plane->fb = crtc->primary->fb; + drm_framebuffer_reference(plane->fb); return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c index c786cd4f457b..2a3ad24276f8 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c @@ -263,7 +263,7 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, buffer->sgt = sgt; exynos_gem_obj->base.import_attach = attach; - DRM_DEBUG_PRIME("dma_addr = 0x%x, size = 0x%lx\n", buffer->dma_addr, + DRM_DEBUG_PRIME("dma_addr = %pad, size = 0x%lx\n", &buffer->dma_addr, buffer->size); return &exynos_gem_obj->base; diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index eb73e3bf2a0c..4ac438187568 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1426,9 +1426,9 @@ static int exynos_dsi_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); dsi->reg_base = devm_ioremap_resource(&pdev->dev, res); - if (!dsi->reg_base) { + if (IS_ERR(dsi->reg_base)) { dev_err(&pdev->dev, "failed to remap io region\n"); - return -EADDRNOTAVAIL; + return PTR_ERR(dsi->reg_base); } dsi->phy = devm_phy_get(&pdev->dev, "dsim"); diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 7afead9c3f30..852f2dadaebd 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -220,7 +220,7 @@ static void vidi_win_commit(struct exynos_drm_manager *mgr, int zpos) win_data->enabled = true; - DRM_DEBUG_KMS("dma_addr = 0x%x\n", win_data->dma_addr); + DRM_DEBUG_KMS("dma_addr = %pad\n", &win_data->dma_addr); if (ctx->vblank_on) schedule_work(&ctx->work); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ec82f6bff122..108e1ec2fa4b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1954,6 +1954,9 @@ struct drm_i915_cmd_table { #define IS_ULT(dev) (IS_HSW_ULT(dev) || IS_BDW_ULT(dev)) #define IS_HSW_GT3(dev) (IS_HASWELL(dev) && \ ((dev)->pdev->device & 0x00F0) == 0x0020) +/* ULX machines are also considered ULT. */ +#define IS_HSW_ULX(dev) ((dev)->pdev->device == 0x0A0E || \ + (dev)->pdev->device == 0x0A1E) #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary) /* diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index ab5e93c30aa2..154b0f8bb88d 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -34,25 +34,35 @@ static void gen8_setup_private_ppat(struct drm_i915_private *dev_priv); bool intel_enable_ppgtt(struct drm_device *dev, bool full) { - if (i915.enable_ppgtt == 0 || !HAS_ALIASING_PPGTT(dev)) + if (i915.enable_ppgtt == 0) return false; if (i915.enable_ppgtt == 1 && full) return false; + return true; +} + +static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt) +{ + if (enable_ppgtt == 0 || !HAS_ALIASING_PPGTT(dev)) + return 0; + + if (enable_ppgtt == 1) + return 1; + + if (enable_ppgtt == 2 && HAS_PPGTT(dev)) + return 2; + #ifdef CONFIG_INTEL_IOMMU /* Disable ppgtt on SNB if VT-d is on. */ if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped) { DRM_INFO("Disabling PPGTT because VT-d is on\n"); - return false; + return 0; } #endif - /* Full ppgtt disabled by default for now due to issues. */ - if (full) - return false; /* HAS_PPGTT(dev) */ - else - return HAS_ALIASING_PPGTT(dev); + return HAS_ALIASING_PPGTT(dev) ? 1 : 0; } #define GEN6_PPGTT_PD_ENTRIES 512 @@ -2031,6 +2041,14 @@ int i915_gem_gtt_init(struct drm_device *dev) gtt->base.total >> 20); DRM_DEBUG_DRIVER("GMADR size = %ldM\n", gtt->mappable_end >> 20); DRM_DEBUG_DRIVER("GTT stolen size = %zdM\n", gtt->stolen_size >> 20); + /* + * i915.enable_ppgtt is read-only, so do an early pass to validate the + * user's requested state against the hardware/driver capabilities. We + * do this now so that we can print out any log messages once rather + * than every time we check intel_enable_ppgtt(). + */ + i915.enable_ppgtt = sanitize_enable_ppgtt(dev, i915.enable_ppgtt); + DRM_DEBUG_DRIVER("ppgtt mode: %i\n", i915.enable_ppgtt); return 0; } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 7753249b3a95..f98ba4e6e70b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1362,10 +1362,20 @@ static inline void intel_hpd_irq_handler(struct drm_device *dev, spin_lock(&dev_priv->irq_lock); for (i = 1; i < HPD_NUM_PINS; i++) { - WARN_ONCE(hpd[i] & hotplug_trigger && - dev_priv->hpd_stats[i].hpd_mark == HPD_DISABLED, - "Received HPD interrupt (0x%08x) on pin %d (0x%08x) although disabled\n", - hotplug_trigger, i, hpd[i]); + if (hpd[i] & hotplug_trigger && + dev_priv->hpd_stats[i].hpd_mark == HPD_DISABLED) { + /* + * On GMCH platforms the interrupt mask bits only + * prevent irq generation, not the setting of the + * hotplug bits itself. So only WARN about unexpected + * interrupts on saner platforms. + */ + WARN_ONCE(INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev), + "Received HPD interrupt (0x%08x) on pin %d (0x%08x) although disabled\n", + hotplug_trigger, i, hpd[i]); + + continue; + } if (!(hpd[i] & hotplug_trigger) || dev_priv->hpd_stats[i].hpd_mark != HPD_ENABLED) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9f5b18d9d885..c77af69c2d8f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -827,6 +827,7 @@ enum punit_power_well { # define MI_FLUSH_ENABLE (1 << 12) # define ASYNC_FLIP_PERF_DISABLE (1 << 14) # define MODE_IDLE (1 << 9) +# define STOP_RING (1 << 8) #define GEN6_GT_MODE 0x20d0 #define GEN7_GT_MODE 0x7008 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index dae976f51d83..48aa516a1ac0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9654,11 +9654,22 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_I(pipe_src_w); PIPE_CONF_CHECK_I(pipe_src_h); - PIPE_CONF_CHECK_I(gmch_pfit.control); - /* pfit ratios are autocomputed by the hw on gen4+ */ - if (INTEL_INFO(dev)->gen < 4) - PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios); - PIPE_CONF_CHECK_I(gmch_pfit.lvds_border_bits); + /* + * FIXME: BIOS likes to set up a cloned config with lvds+external + * screen. Since we don't yet re-compute the pipe config when moving + * just the lvds port away to another pipe the sw tracking won't match. + * + * Proper atomic modesets with recomputed global state will fix this. + * Until then just don't check gmch state for inherited modes. + */ + if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_INHERITED_MODE)) { + PIPE_CONF_CHECK_I(gmch_pfit.control); + /* pfit ratios are autocomputed by the hw on gen4+ */ + if (INTEL_INFO(dev)->gen < 4) + PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios); + PIPE_CONF_CHECK_I(gmch_pfit.lvds_border_bits); + } + PIPE_CONF_CHECK_I(pch_pfit.enabled); if (current_config->pch_pfit.enabled) { PIPE_CONF_CHECK_I(pch_pfit.pos); @@ -11384,15 +11395,6 @@ void intel_modeset_init(struct drm_device *dev) } } -static void -intel_connector_break_all_links(struct intel_connector *connector) -{ - connector->base.dpms = DRM_MODE_DPMS_OFF; - connector->base.encoder = NULL; - connector->encoder->connectors_active = false; - connector->encoder->base.crtc = NULL; -} - static void intel_enable_pipe_a(struct drm_device *dev) { struct intel_connector *connector; @@ -11474,8 +11476,17 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) if (connector->encoder->base.crtc != &crtc->base) continue; - intel_connector_break_all_links(connector); + connector->base.dpms = DRM_MODE_DPMS_OFF; + connector->base.encoder = NULL; } + /* multiple connectors may have the same encoder: + * handle them and break crtc link separately */ + list_for_each_entry(connector, &dev->mode_config.connector_list, + base.head) + if (connector->encoder->base.crtc == &crtc->base) { + connector->encoder->base.crtc = NULL; + connector->encoder->connectors_active = false; + } WARN_ON(crtc->active); crtc->base.enabled = false; @@ -11557,6 +11568,8 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder) drm_get_encoder_name(&encoder->base)); encoder->disable(encoder); } + encoder->base.crtc = NULL; + encoder->connectors_active = false; /* Inconsistent output/port/pipe state happens presumably due to * a bug in one of the get_hw_state functions. Or someplace else @@ -11567,8 +11580,8 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder) base.head) { if (connector->encoder != encoder) continue; - - intel_connector_break_all_links(connector); + connector->base.dpms = DRM_MODE_DPMS_OFF; + connector->base.encoder = NULL; } } /* Enabled encoders without active connectors will be fixed in @@ -11616,6 +11629,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) base.head) { memset(&crtc->config, 0, sizeof(crtc->config)); + crtc->config.quirks |= PIPE_CONFIG_QUIRK_INHERITED_MODE; + crtc->active = dev_priv->display.get_pipe_config(crtc, &crtc->config); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index d2a55884ad52..5ca68aa9f237 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -105,7 +105,8 @@ intel_dp_max_link_bw(struct intel_dp *intel_dp) case DP_LINK_BW_2_7: break; case DP_LINK_BW_5_4: /* 1.2 capable displays may advertise higher bw */ - if ((IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) && + if (((IS_HASWELL(dev) && !IS_HSW_ULX(dev)) || + INTEL_INFO(dev)->gen >= 8) && intel_dp->dpcd[DP_DPCD_REV] >= 0x12) max_link_bw = DP_LINK_BW_5_4; else @@ -3619,7 +3620,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, { struct drm_connector *connector = &intel_connector->base; struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = intel_dig_port->base.base.dev; + struct intel_encoder *intel_encoder = &intel_dig_port->base; + struct drm_device *dev = intel_encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_display_mode *fixed_mode = NULL; bool has_dpcd; @@ -3629,6 +3631,14 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, if (!is_edp(intel_dp)) return true; + /* The VDD bit needs a power domain reference, so if the bit is already + * enabled when we boot, grab this reference. */ + if (edp_have_panel_vdd(intel_dp)) { + enum intel_display_power_domain power_domain; + power_domain = intel_display_port_power_domain(intel_encoder); + intel_display_power_get(dev_priv, power_domain); + } + /* Cache DPCD and EDID for edp. */ intel_edp_panel_vdd_on(intel_dp); has_dpcd = intel_dp_get_dpcd(intel_dp); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 0542de982260..328b1a70264b 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -236,7 +236,8 @@ struct intel_crtc_config { * tracked with quirk flags so that fastboot and state checker can act * accordingly. */ -#define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS (1<<0) /* unreliable sync mode.flags */ +#define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS (1<<0) /* unreliable sync mode.flags */ +#define PIPE_CONFIG_QUIRK_INHERITED_MODE (1<<1) /* mode inherited from firmware */ unsigned long quirks; /* User requested mode, only valid as a starting point to diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index b4d44e62f0c7..fce4a0d93c0b 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -132,6 +132,16 @@ static int intelfb_create(struct drm_fb_helper *helper, mutex_lock(&dev->struct_mutex); + if (intel_fb && + (sizes->fb_width > intel_fb->base.width || + sizes->fb_height > intel_fb->base.height)) { + DRM_DEBUG_KMS("BIOS fb too small (%dx%d), we require (%dx%d)," + " releasing it\n", + intel_fb->base.width, intel_fb->base.height, + sizes->fb_width, sizes->fb_height); + drm_framebuffer_unreference(&intel_fb->base); + intel_fb = ifbdev->fb = NULL; + } if (!intel_fb || WARN_ON(!intel_fb->obj)) { DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n"); ret = intelfb_alloc(helper, sizes); diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index b0413e190625..157267aa3561 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -821,11 +821,11 @@ static void intel_disable_hdmi(struct intel_encoder *encoder) } } -static int hdmi_portclock_limit(struct intel_hdmi *hdmi) +static int hdmi_portclock_limit(struct intel_hdmi *hdmi, bool respect_dvi_limit) { struct drm_device *dev = intel_hdmi_to_dev(hdmi); - if (!hdmi->has_hdmi_sink || IS_G4X(dev)) + if ((respect_dvi_limit && !hdmi->has_hdmi_sink) || IS_G4X(dev)) return 165000; else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) return 300000; @@ -837,7 +837,8 @@ static enum drm_mode_status intel_hdmi_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { - if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector))) + if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector), + true)) return MODE_CLOCK_HIGH; if (mode->clock < 20000) return MODE_CLOCK_LOW; @@ -879,7 +880,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, struct drm_device *dev = encoder->base.dev; struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; int clock_12bpc = pipe_config->adjusted_mode.crtc_clock * 3 / 2; - int portclock_limit = hdmi_portclock_limit(intel_hdmi); + int portclock_limit = hdmi_portclock_limit(intel_hdmi, false); int desired_bpp; if (intel_hdmi->color_range_auto) { diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 6bc68bdcf433..79fb4cc2137c 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -437,32 +437,41 @@ static void ring_setup_phys_status_page(struct intel_ring_buffer *ring) I915_WRITE(HWS_PGA, addr); } -static int init_ring_common(struct intel_ring_buffer *ring) +static bool stop_ring(struct intel_ring_buffer *ring) { - struct drm_device *dev = ring->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj = ring->obj; - int ret = 0; - u32 head; + struct drm_i915_private *dev_priv = to_i915(ring->dev); - gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); + if (!IS_GEN2(ring->dev)) { + I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING)); + if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) { + DRM_ERROR("%s :timed out trying to stop ring\n", ring->name); + return false; + } + } - /* Stop the ring if it's running. */ I915_WRITE_CTL(ring, 0); I915_WRITE_HEAD(ring, 0); ring->write_tail(ring, 0); - if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) - DRM_ERROR("%s :timed out trying to stop ring\n", ring->name); - if (I915_NEED_GFX_HWS(dev)) - intel_ring_setup_status_page(ring); - else - ring_setup_phys_status_page(ring); + if (!IS_GEN2(ring->dev)) { + (void)I915_READ_CTL(ring); + I915_WRITE_MODE(ring, _MASKED_BIT_DISABLE(STOP_RING)); + } - head = I915_READ_HEAD(ring) & HEAD_ADDR; + return (I915_READ_HEAD(ring) & HEAD_ADDR) == 0; +} - /* G45 ring initialization fails to reset head to zero */ - if (head != 0) { +static int init_ring_common(struct intel_ring_buffer *ring) +{ + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj = ring->obj; + int ret = 0; + + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); + + if (!stop_ring(ring)) { + /* G45 ring initialization often fails to reset head to zero */ DRM_DEBUG_KMS("%s head not reset to zero " "ctl %08x head %08x tail %08x start %08x\n", ring->name, @@ -471,9 +480,7 @@ static int init_ring_common(struct intel_ring_buffer *ring) I915_READ_TAIL(ring), I915_READ_START(ring)); - I915_WRITE_HEAD(ring, 0); - - if (I915_READ_HEAD(ring) & HEAD_ADDR) { + if (!stop_ring(ring)) { DRM_ERROR("failed to set %s head to zero " "ctl %08x head %08x tail %08x start %08x\n", ring->name, @@ -481,9 +488,16 @@ static int init_ring_common(struct intel_ring_buffer *ring) I915_READ_HEAD(ring), I915_READ_TAIL(ring), I915_READ_START(ring)); + ret = -EIO; + goto out; } } + if (I915_NEED_GFX_HWS(dev)) + intel_ring_setup_status_page(ring); + else + ring_setup_phys_status_page(ring); + /* Initialize the ring. This must happen _after_ we've cleared the ring * registers with the above sequence (the readback of the HEAD registers * also enforces ordering), otherwise the hw might lose the new ring diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 270a6a973438..2b91c4b4d34b 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -34,6 +34,7 @@ struct intel_hw_status_page { #define I915_WRITE_IMR(ring, val) I915_WRITE(RING_IMR((ring)->mmio_base), val) #define I915_READ_MODE(ring) I915_READ(RING_MI_MODE((ring)->mmio_base)) +#define I915_WRITE_MODE(ring, val) I915_WRITE(RING_MI_MODE((ring)->mmio_base), val) enum intel_ring_hangcheck_action { HANGCHECK_IDLE = 0, diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index 3e6c0f3ed592..ef9957dbac94 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c @@ -510,9 +510,8 @@ static void update_cursor(struct drm_crtc *crtc) MDP4_DMA_CURSOR_BLEND_CONFIG_CURSOR_EN); } else { /* disable cursor: */ - mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_BASE(dma), 0); - mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_BLEND_CONFIG(dma), - MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT(CURSOR_ARGB)); + mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_BASE(dma), + mdp4_kms->blank_cursor_iova); } /* and drop the iova ref + obj rev when done scanning out: */ @@ -574,11 +573,9 @@ static int mdp4_crtc_cursor_set(struct drm_crtc *crtc, if (old_bo) { /* drop our previous reference: */ - msm_gem_put_iova(old_bo, mdp4_kms->id); - drm_gem_object_unreference_unlocked(old_bo); + drm_flip_work_queue(&mdp4_crtc->unref_cursor_work, old_bo); } - crtc_flush(crtc); request_pending(crtc, PENDING_CURSOR); return 0; diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c index c740ccd1cc67..8edd531cb621 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c @@ -70,12 +70,12 @@ irqreturn_t mdp4_irq(struct msm_kms *kms) VERB("status=%08x", status); + mdp_dispatch_irqs(mdp_kms, status); + for (id = 0; id < priv->num_crtcs; id++) if (status & mdp4_crtc_vblank(priv->crtcs[id])) drm_handle_vblank(dev, id); - mdp_dispatch_irqs(mdp_kms, status); - return IRQ_HANDLED; } diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c index 272e707c9487..0bb4faa17523 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c @@ -144,6 +144,10 @@ static void mdp4_preclose(struct msm_kms *kms, struct drm_file *file) static void mdp4_destroy(struct msm_kms *kms) { struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms)); + if (mdp4_kms->blank_cursor_iova) + msm_gem_put_iova(mdp4_kms->blank_cursor_bo, mdp4_kms->id); + if (mdp4_kms->blank_cursor_bo) + drm_gem_object_unreference(mdp4_kms->blank_cursor_bo); kfree(mdp4_kms); } @@ -372,6 +376,23 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev) goto fail; } + mutex_lock(&dev->struct_mutex); + mdp4_kms->blank_cursor_bo = msm_gem_new(dev, SZ_16K, MSM_BO_WC); + mutex_unlock(&dev->struct_mutex); + if (IS_ERR(mdp4_kms->blank_cursor_bo)) { + ret = PTR_ERR(mdp4_kms->blank_cursor_bo); + dev_err(dev->dev, "could not allocate blank-cursor bo: %d\n", ret); + mdp4_kms->blank_cursor_bo = NULL; + goto fail; + } + + ret = msm_gem_get_iova(mdp4_kms->blank_cursor_bo, mdp4_kms->id, + &mdp4_kms->blank_cursor_iova); + if (ret) { + dev_err(dev->dev, "could not pin blank-cursor bo: %d\n", ret); + goto fail; + } + return kms; fail: diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h index 66a4d31aec80..715520c54cde 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h @@ -44,6 +44,10 @@ struct mdp4_kms { struct clk *lut_clk; struct mdp_irq error_handler; + + /* empty/blank cursor bo to use when cursor is "disabled" */ + struct drm_gem_object *blank_cursor_bo; + uint32_t blank_cursor_iova; }; #define to_mdp4_kms(x) container_of(x, struct mdp4_kms, base) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c index 353d494a497f..f2b985bc2adf 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c @@ -71,11 +71,11 @@ static void mdp5_irq_mdp(struct mdp_kms *mdp_kms) VERB("status=%08x", status); + mdp_dispatch_irqs(mdp_kms, status); + for (id = 0; id < priv->num_crtcs; id++) if (status & mdp5_crtc_vblank(priv->crtcs[id])) drm_handle_vblank(dev, id); - - mdp_dispatch_irqs(mdp_kms, status); } irqreturn_t mdp5_irq(struct msm_kms *kms) diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c index 6c6d7d4c9b4e..a752ab83b810 100644 --- a/drivers/gpu/drm/msm/msm_fbdev.c +++ b/drivers/gpu/drm/msm/msm_fbdev.c @@ -62,11 +62,8 @@ static int msm_fbdev_create(struct drm_fb_helper *helper, dma_addr_t paddr; int ret, size; - /* only doing ARGB32 since this is what is needed to alpha-blend - * with video overlays: - */ sizes->surface_bpp = 32; - sizes->surface_depth = 32; + sizes->surface_depth = 24; DBG("create fbdev: %dx%d@%d (%dx%d)", sizes->surface_width, sizes->surface_height, sizes->surface_bpp, diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 3da8264d3039..bb8026daebc9 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -118,8 +118,10 @@ static void put_pages(struct drm_gem_object *obj) if (iommu_present(&platform_bus_type)) drm_gem_put_pages(obj, msm_obj->pages, true, false); - else + else { drm_mm_remove_node(msm_obj->vram_node); + drm_free_large(msm_obj->pages); + } msm_obj->pages = NULL; } diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c index 1dc37b1ddbfa..b0d0fb2f4d08 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c @@ -863,7 +863,7 @@ gm107_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info) { mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS); mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS); - mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW); + mmio_data(0x200000, 0x1000, NV_MEM_ACCESS_RW); mmio_list(0x40800c, 0x00000000, 8, 1); mmio_list(0x408010, 0x80000000, 0, 0); @@ -877,6 +877,8 @@ gm107_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info) mmio_list(0x418e24, 0x00000000, 8, 0); mmio_list(0x418e28, 0x80000030, 0, 0); + mmio_list(0x4064c8, 0x018002c0, 0, 0); + mmio_list(0x418810, 0x80000000, 12, 2); mmio_list(0x419848, 0x10000000, 12, 2); mmio_list(0x419c2c, 0x10000000, 12, 2); diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index fb0b6b2d1427..222e8ebb669d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c @@ -168,7 +168,8 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios) */ i = 16; do { - if ((nv_rd32(bios, 0x300000) & 0xffff) == 0xaa55) + u32 data = le32_to_cpu(nv_rd32(bios, 0x300000)) & 0xffff; + if (data == 0xaa55) break; } while (i--); @@ -176,14 +177,15 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios) goto out; /* read entire bios image to system memory */ - bios->size = ((nv_rd32(bios, 0x300000) >> 16) & 0xff) * 512; + bios->size = (le32_to_cpu(nv_rd32(bios, 0x300000)) >> 16) & 0xff; + bios->size = bios->size * 512; if (!bios->size) goto out; bios->data = kmalloc(bios->size, GFP_KERNEL); if (bios->data) { - for (i = 0; i < bios->size; i+=4) - nv_wo32(bios, i, nv_rd32(bios, 0x300000 + i)); + for (i = 0; i < bios->size; i += 4) + ((u32 *)bios->data)[i/4] = nv_rd32(bios, 0x300000 + i); } /* check the PCI record header */ diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 83face3f608f..279206997e5c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -389,9 +389,6 @@ bool nouveau_acpi_rom_supported(struct pci_dev *pdev) acpi_status status; acpi_handle dhandle, rom_handle; - if (!nouveau_dsm_priv.dsm_detected && !nouveau_dsm_priv.optimus_detected) - return false; - dhandle = ACPI_HANDLE(&pdev->dev); if (!dhandle) return false; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 3ff030dc1ee3..da764a4ed958 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -764,9 +764,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, } ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); - mutex_unlock(&chan->cli->mutex); if (ret) goto fail_unreserve; + mutex_unlock(&chan->cli->mutex); /* Update the crtc struct and cleanup */ crtc->primary->fb = fb; diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index fb187c78978f..c31c12b4e666 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1177,27 +1177,43 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, /* Set NUM_BANKS. */ if (rdev->family >= CHIP_TAHITI) { - unsigned tileb, index, num_banks, tile_split_bytes; + unsigned index, num_banks; - /* Calculate the macrotile mode index. */ - tile_split_bytes = 64 << tile_split; - tileb = 8 * 8 * target_fb->bits_per_pixel / 8; - tileb = min(tile_split_bytes, tileb); + if (rdev->family >= CHIP_BONAIRE) { + unsigned tileb, tile_split_bytes; - for (index = 0; tileb > 64; index++) { - tileb >>= 1; - } + /* Calculate the macrotile mode index. */ + tile_split_bytes = 64 << tile_split; + tileb = 8 * 8 * target_fb->bits_per_pixel / 8; + tileb = min(tile_split_bytes, tileb); - if (index >= 16) { - DRM_ERROR("Wrong screen bpp (%u) or tile split (%u)\n", - target_fb->bits_per_pixel, tile_split); - return -EINVAL; - } + for (index = 0; tileb > 64; index++) + tileb >>= 1; + + if (index >= 16) { + DRM_ERROR("Wrong screen bpp (%u) or tile split (%u)\n", + target_fb->bits_per_pixel, tile_split); + return -EINVAL; + } - if (rdev->family >= CHIP_BONAIRE) num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3; - else + } else { + switch (target_fb->bits_per_pixel) { + case 8: + index = 10; + break; + case 16: + index = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP; + break; + default: + case 32: + index = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP; + break; + } + num_banks = (rdev->config.si.tile_mode_array[index] >> 20) & 0x3; + } + fb_format |= EVERGREEN_GRPH_NUM_BANKS(num_banks); } else { /* NI and older. */ @@ -1720,8 +1736,9 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) } /* otherwise, pick one of the plls */ if ((rdev->family == CHIP_KAVERI) || - (rdev->family == CHIP_KABINI)) { - /* KB/KV has PPLL1 and PPLL2 */ + (rdev->family == CHIP_KABINI) || + (rdev->family == CHIP_MULLINS)) { + /* KB/KV/ML has PPLL1 and PPLL2 */ pll_in_use = radeon_get_pll_use_mask(crtc); if (!(pll_in_use & (1 << ATOM_PPLL2))) return ATOM_PPLL2; @@ -1885,6 +1902,9 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) is_tvcv = true; + if (!radeon_crtc->adjusted_clock) + return -EINVAL; + atombios_crtc_set_pll(crtc, adjusted_mode); if (ASIC_IS_DCE4(rdev)) diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index bc0119fb6c12..54e4f52549af 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -366,11 +366,11 @@ static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector) if (!(dig_connector->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) return; - if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_SINK_OUI, buf, 3)) + if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_SINK_OUI, buf, 3) == 3) DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n", buf[0], buf[1], buf[2]); - if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_BRANCH_OUI, buf, 3)) + if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_BRANCH_OUI, buf, 3) == 3) DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n", buf[0], buf[1], buf[2]); } @@ -419,21 +419,23 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder, if (dp_bridge != ENCODER_OBJECT_ID_NONE) { /* DP bridge chips */ - drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, - DP_EDP_CONFIGURATION_CAP, &tmp); - if (tmp & 1) - panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; - else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) || - (dp_bridge == ENCODER_OBJECT_ID_TRAVIS)) - panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; - else - panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; + if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, + DP_EDP_CONFIGURATION_CAP, &tmp) == 1) { + if (tmp & 1) + panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; + else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) || + (dp_bridge == ENCODER_OBJECT_ID_TRAVIS)) + panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; + else + panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; + } } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { /* eDP */ - drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, - DP_EDP_CONFIGURATION_CAP, &tmp); - if (tmp & 1) - panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; + if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, + DP_EDP_CONFIGURATION_CAP, &tmp) == 1) { + if (tmp & 1) + panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; + } } return panel_mode; @@ -809,11 +811,15 @@ void radeon_dp_link_train(struct drm_encoder *encoder, else dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; - drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, DP_MAX_LANE_COUNT, &tmp); - if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) - dp_info.tp3_supported = true; - else + if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, DP_MAX_LANE_COUNT, &tmp) + == 1) { + if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) + dp_info.tp3_supported = true; + else + dp_info.tp3_supported = false; + } else { dp_info.tp3_supported = false; + } memcpy(dp_info.dpcd, dig_connector->dpcd, DP_RECEIVER_CAP_SIZE); dp_info.rdev = rdev; diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 199eb194716f..d2fd98968085 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -63,6 +63,12 @@ MODULE_FIRMWARE("radeon/KABINI_ce.bin"); MODULE_FIRMWARE("radeon/KABINI_mec.bin"); MODULE_FIRMWARE("radeon/KABINI_rlc.bin"); MODULE_FIRMWARE("radeon/KABINI_sdma.bin"); +MODULE_FIRMWARE("radeon/MULLINS_pfp.bin"); +MODULE_FIRMWARE("radeon/MULLINS_me.bin"); +MODULE_FIRMWARE("radeon/MULLINS_ce.bin"); +MODULE_FIRMWARE("radeon/MULLINS_mec.bin"); +MODULE_FIRMWARE("radeon/MULLINS_rlc.bin"); +MODULE_FIRMWARE("radeon/MULLINS_sdma.bin"); extern int r600_ih_ring_alloc(struct radeon_device *rdev); extern void r600_ih_ring_fini(struct radeon_device *rdev); @@ -1473,6 +1479,43 @@ static const u32 hawaii_mgcg_cgcg_init[] = 0xd80c, 0xff000ff0, 0x00000100 }; +static const u32 godavari_golden_registers[] = +{ + 0x55e4, 0xff607fff, 0xfc000100, + 0x6ed8, 0x00010101, 0x00010000, + 0x9830, 0xffffffff, 0x00000000, + 0x98302, 0xf00fffff, 0x00000400, + 0x6130, 0xffffffff, 0x00010000, + 0x5bb0, 0x000000f0, 0x00000070, + 0x5bc0, 0xf0311fff, 0x80300000, + 0x98f8, 0x73773777, 0x12010001, + 0x98fc, 0xffffffff, 0x00000010, + 0x8030, 0x00001f0f, 0x0000100a, + 0x2f48, 0x73773777, 0x12010001, + 0x2408, 0x000fffff, 0x000c007f, + 0x8a14, 0xf000003f, 0x00000007, + 0x8b24, 0xffffffff, 0x00ff0fff, + 0x30a04, 0x0000ff0f, 0x00000000, + 0x28a4c, 0x07ffffff, 0x06000000, + 0x4d8, 0x00000fff, 0x00000100, + 0xd014, 0x00010000, 0x00810001, + 0xd814, 0x00010000, 0x00810001, + 0x3e78, 0x00000001, 0x00000002, + 0xc768, 0x00000008, 0x00000008, + 0xc770, 0x00000f00, 0x00000800, + 0xc774, 0x00000f00, 0x00000800, + 0xc798, 0x00ffffff, 0x00ff7fbf, + 0xc79c, 0x00ffffff, 0x00ff7faf, + 0x8c00, 0x000000ff, 0x00000001, + 0x214f8, 0x01ff01ff, 0x00000002, + 0x21498, 0x007ff800, 0x00200000, + 0x2015c, 0xffffffff, 0x00000f40, + 0x88c4, 0x001f3ae3, 0x00000082, + 0x88d4, 0x0000001f, 0x00000010, + 0x30934, 0xffffffff, 0x00000000 +}; + + static void cik_init_golden_registers(struct radeon_device *rdev) { switch (rdev->family) { @@ -1504,6 +1547,20 @@ static void cik_init_golden_registers(struct radeon_device *rdev) kalindi_golden_spm_registers, (const u32)ARRAY_SIZE(kalindi_golden_spm_registers)); break; + case CHIP_MULLINS: + radeon_program_register_sequence(rdev, + kalindi_mgcg_cgcg_init, + (const u32)ARRAY_SIZE(kalindi_mgcg_cgcg_init)); + radeon_program_register_sequence(rdev, + godavari_golden_registers, + (const u32)ARRAY_SIZE(godavari_golden_registers)); + radeon_program_register_sequence(rdev, + kalindi_golden_common_registers, + (const u32)ARRAY_SIZE(kalindi_golden_common_registers)); + radeon_program_register_sequence(rdev, + kalindi_golden_spm_registers, + (const u32)ARRAY_SIZE(kalindi_golden_spm_registers)); + break; case CHIP_KAVERI: radeon_program_register_sequence(rdev, spectre_mgcg_cgcg_init, @@ -1834,6 +1891,15 @@ static int cik_init_microcode(struct radeon_device *rdev) rlc_req_size = KB_RLC_UCODE_SIZE * 4; sdma_req_size = CIK_SDMA_UCODE_SIZE * 4; break; + case CHIP_MULLINS: + chip_name = "MULLINS"; + pfp_req_size = CIK_PFP_UCODE_SIZE * 4; + me_req_size = CIK_ME_UCODE_SIZE * 4; + ce_req_size = CIK_CE_UCODE_SIZE * 4; + mec_req_size = CIK_MEC_UCODE_SIZE * 4; + rlc_req_size = ML_RLC_UCODE_SIZE * 4; + sdma_req_size = CIK_SDMA_UCODE_SIZE * 4; + break; default: BUG(); } @@ -3272,6 +3338,7 @@ static void cik_gpu_init(struct radeon_device *rdev) gb_addr_config = BONAIRE_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_KABINI: + case CHIP_MULLINS: default: rdev->config.cik.max_shader_engines = 1; rdev->config.cik.max_tile_pipes = 2; @@ -3702,6 +3769,7 @@ int cik_copy_cpdma(struct radeon_device *rdev, r = radeon_fence_emit(rdev, fence, ring->idx); if (r) { radeon_ring_unlock_undo(rdev, ring); + radeon_semaphore_free(rdev, &sem, NULL); return r; } @@ -5800,6 +5868,9 @@ static int cik_rlc_resume(struct radeon_device *rdev) case CHIP_KABINI: size = KB_RLC_UCODE_SIZE; break; + case CHIP_MULLINS: + size = ML_RLC_UCODE_SIZE; + break; } cik_rlc_stop(rdev); @@ -6548,6 +6619,7 @@ void cik_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer) buffer[count++] = cpu_to_le32(0x00000000); break; case CHIP_KABINI: + case CHIP_MULLINS: buffer[count++] = cpu_to_le32(0x00000000); /* XXX */ buffer[count++] = cpu_to_le32(0x00000000); break; @@ -6693,6 +6765,19 @@ static void cik_disable_interrupt_state(struct radeon_device *rdev) WREG32(LB_INTERRUPT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); WREG32(LB_INTERRUPT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); } + /* pflip */ + if (rdev->num_crtc >= 2) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); + } + if (rdev->num_crtc >= 4) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); + } + if (rdev->num_crtc >= 6) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + } /* dac hotplug */ WREG32(DAC_AUTODETECT_INT_CONTROL, 0); @@ -7049,6 +7134,25 @@ int cik_irq_set(struct radeon_device *rdev) WREG32(LB_INTERRUPT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6); } + if (rdev->num_crtc >= 2) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + } + if (rdev->num_crtc >= 4) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + } + if (rdev->num_crtc >= 6) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + } + WREG32(DC_HPD1_INT_CONTROL, hpd1); WREG32(DC_HPD2_INT_CONTROL, hpd2); WREG32(DC_HPD3_INT_CONTROL, hpd3); @@ -7085,6 +7189,29 @@ static inline void cik_irq_ack(struct radeon_device *rdev) rdev->irq.stat_regs.cik.disp_int_cont5 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE5); rdev->irq.stat_regs.cik.disp_int_cont6 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE6); + rdev->irq.stat_regs.cik.d1grph_int = RREG32(GRPH_INT_STATUS + + EVERGREEN_CRTC0_REGISTER_OFFSET); + rdev->irq.stat_regs.cik.d2grph_int = RREG32(GRPH_INT_STATUS + + EVERGREEN_CRTC1_REGISTER_OFFSET); + if (rdev->num_crtc >= 4) { + rdev->irq.stat_regs.cik.d3grph_int = RREG32(GRPH_INT_STATUS + + EVERGREEN_CRTC2_REGISTER_OFFSET); + rdev->irq.stat_regs.cik.d4grph_int = RREG32(GRPH_INT_STATUS + + EVERGREEN_CRTC3_REGISTER_OFFSET); + } + if (rdev->num_crtc >= 6) { + rdev->irq.stat_regs.cik.d5grph_int = RREG32(GRPH_INT_STATUS + + EVERGREEN_CRTC4_REGISTER_OFFSET); + rdev->irq.stat_regs.cik.d6grph_int = RREG32(GRPH_INT_STATUS + + EVERGREEN_CRTC5_REGISTER_OFFSET); + } + + if (rdev->irq.stat_regs.cik.d1grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, + GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.cik.d2grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, + GRPH_PFLIP_INT_CLEAR); if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VBLANK_INTERRUPT) WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK); if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VLINE_INTERRUPT) @@ -7095,6 +7222,12 @@ static inline void cik_irq_ack(struct radeon_device *rdev) WREG32(LB_VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK); if (rdev->num_crtc >= 4) { + if (rdev->irq.stat_regs.cik.d3grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, + GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.cik.d4grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, + GRPH_PFLIP_INT_CLEAR); if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK); if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) @@ -7106,6 +7239,12 @@ static inline void cik_irq_ack(struct radeon_device *rdev) } if (rdev->num_crtc >= 6) { + if (rdev->irq.stat_regs.cik.d5grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, + GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.cik.d6grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, + GRPH_PFLIP_INT_CLEAR); if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK); if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) @@ -7457,6 +7596,15 @@ restart_ih: break; } break; + case 8: /* D1 page flip */ + case 10: /* D2 page flip */ + case 12: /* D3 page flip */ + case 14: /* D4 page flip */ + case 16: /* D5 page flip */ + case 18: /* D6 page flip */ + DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1); + radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1); + break; case 42: /* HPD hotplug */ switch (src_data) { case 0: diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c index f7e46cf682af..72e464c79a88 100644 --- a/drivers/gpu/drm/radeon/cik_sdma.c +++ b/drivers/gpu/drm/radeon/cik_sdma.c @@ -562,6 +562,7 @@ int cik_copy_dma(struct radeon_device *rdev, r = radeon_fence_emit(rdev, fence, ring->idx); if (r) { radeon_ring_unlock_undo(rdev, ring); + radeon_semaphore_free(rdev, &sem, NULL); return r; } diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index 213873270d5f..dd7926394a8f 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h @@ -888,6 +888,15 @@ # define DC_HPD6_RX_INTERRUPT (1 << 18) #define DISP_INTERRUPT_STATUS_CONTINUE6 0x6780 +/* 0x6858, 0x7458, 0x10058, 0x10c58, 0x11858, 0x12458 */ +#define GRPH_INT_STATUS 0x6858 +# define GRPH_PFLIP_INT_OCCURRED (1 << 0) +# define GRPH_PFLIP_INT_CLEAR (1 << 8) +/* 0x685c, 0x745c, 0x1005c, 0x10c5c, 0x1185c, 0x1245c */ +#define GRPH_INT_CONTROL 0x685c +# define GRPH_PFLIP_INT_MASK (1 << 0) +# define GRPH_PFLIP_INT_TYPE (1 << 8) + #define DAC_AUTODETECT_INT_CONTROL 0x67c8 #define DC_HPD1_INT_STATUS 0x601c diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index b406546440da..0f7a51a3694f 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -4371,7 +4371,6 @@ int evergreen_irq_set(struct radeon_device *rdev) u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0; u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6; u32 grbm_int_cntl = 0; - u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0; u32 afmt1 = 0, afmt2 = 0, afmt3 = 0, afmt4 = 0, afmt5 = 0, afmt6 = 0; u32 dma_cntl, dma_cntl1 = 0; u32 thermal_int = 0; @@ -4554,15 +4553,21 @@ int evergreen_irq_set(struct radeon_device *rdev) WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6); } - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); if (rdev->num_crtc >= 4) { - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); } if (rdev->num_crtc >= 6) { - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); } WREG32(DC_HPD1_INT_CONTROL, hpd1); @@ -4951,6 +4956,15 @@ restart_ih: break; } break; + case 8: /* D1 page flip */ + case 10: /* D2 page flip */ + case 12: /* D3 page flip */ + case 14: /* D4 page flip */ + case 16: /* D5 page flip */ + case 18: /* D6 page flip */ + DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1); + radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1); + break; case 42: /* HPD hotplug */ switch (src_data) { case 0: diff --git a/drivers/gpu/drm/radeon/evergreen_dma.c b/drivers/gpu/drm/radeon/evergreen_dma.c index 287fe966d7de..478caefe0fef 100644 --- a/drivers/gpu/drm/radeon/evergreen_dma.c +++ b/drivers/gpu/drm/radeon/evergreen_dma.c @@ -151,6 +151,7 @@ int evergreen_copy_dma(struct radeon_device *rdev, r = radeon_fence_emit(rdev, fence, ring->idx); if (r) { radeon_ring_unlock_undo(rdev, ring); + radeon_semaphore_free(rdev, &sem, NULL); return r; } diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c index 16ec9d56a234..3f6e817d97ee 100644 --- a/drivers/gpu/drm/radeon/kv_dpm.c +++ b/drivers/gpu/drm/radeon/kv_dpm.c @@ -546,6 +546,52 @@ static int kv_set_divider_value(struct radeon_device *rdev, return 0; } +static u32 kv_convert_vid2_to_vid7(struct radeon_device *rdev, + struct sumo_vid_mapping_table *vid_mapping_table, + u32 vid_2bit) +{ + struct radeon_clock_voltage_dependency_table *vddc_sclk_table = + &rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk; + u32 i; + + if (vddc_sclk_table && vddc_sclk_table->count) { + if (vid_2bit < vddc_sclk_table->count) + return vddc_sclk_table->entries[vid_2bit].v; + else + return vddc_sclk_table->entries[vddc_sclk_table->count - 1].v; + } else { + for (i = 0; i < vid_mapping_table->num_entries; i++) { + if (vid_mapping_table->entries[i].vid_2bit == vid_2bit) + return vid_mapping_table->entries[i].vid_7bit; + } + return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_7bit; + } +} + +static u32 kv_convert_vid7_to_vid2(struct radeon_device *rdev, + struct sumo_vid_mapping_table *vid_mapping_table, + u32 vid_7bit) +{ + struct radeon_clock_voltage_dependency_table *vddc_sclk_table = + &rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk; + u32 i; + + if (vddc_sclk_table && vddc_sclk_table->count) { + for (i = 0; i < vddc_sclk_table->count; i++) { + if (vddc_sclk_table->entries[i].v == vid_7bit) + return i; + } + return vddc_sclk_table->count - 1; + } else { + for (i = 0; i < vid_mapping_table->num_entries; i++) { + if (vid_mapping_table->entries[i].vid_7bit == vid_7bit) + return vid_mapping_table->entries[i].vid_2bit; + } + + return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_2bit; + } +} + static u16 kv_convert_8bit_index_to_voltage(struct radeon_device *rdev, u16 voltage) { @@ -556,9 +602,9 @@ static u16 kv_convert_2bit_index_to_voltage(struct radeon_device *rdev, u32 vid_2bit) { struct kv_power_info *pi = kv_get_pi(rdev); - u32 vid_8bit = sumo_convert_vid2_to_vid7(rdev, - &pi->sys_info.vid_mapping_table, - vid_2bit); + u32 vid_8bit = kv_convert_vid2_to_vid7(rdev, + &pi->sys_info.vid_mapping_table, + vid_2bit); return kv_convert_8bit_index_to_voltage(rdev, (u16)vid_8bit); } @@ -639,7 +685,7 @@ static int kv_force_lowest_valid(struct radeon_device *rdev) static int kv_unforce_levels(struct radeon_device *rdev) { - if (rdev->family == CHIP_KABINI) + if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) return kv_notify_message_to_smu(rdev, PPSMC_MSG_NoForcedLevel); else return kv_set_enabled_levels(rdev); @@ -1362,13 +1408,20 @@ static int kv_update_uvd_dpm(struct radeon_device *rdev, bool gate) struct radeon_uvd_clock_voltage_dependency_table *table = &rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; int ret; + u32 mask; if (!gate) { - if (!pi->caps_uvd_dpm || table->count || pi->caps_stable_p_state) + if (table->count) pi->uvd_boot_level = table->count - 1; else pi->uvd_boot_level = 0; + if (!pi->caps_uvd_dpm || pi->caps_stable_p_state) { + mask = 1 << pi->uvd_boot_level; + } else { + mask = 0x1f; + } + ret = kv_copy_bytes_to_smc(rdev, pi->dpm_table_start + offsetof(SMU7_Fusion_DpmTable, UvdBootLevel), @@ -1377,11 +1430,9 @@ static int kv_update_uvd_dpm(struct radeon_device *rdev, bool gate) if (ret) return ret; - if (!pi->caps_uvd_dpm || - pi->caps_stable_p_state) - kv_send_msg_to_smc_with_parameter(rdev, - PPSMC_MSG_UVDDPM_SetEnabledMask, - (1 << pi->uvd_boot_level)); + kv_send_msg_to_smc_with_parameter(rdev, + PPSMC_MSG_UVDDPM_SetEnabledMask, + mask); } return kv_enable_uvd_dpm(rdev, !gate); @@ -1617,7 +1668,7 @@ static void kv_dpm_powergate_acp(struct radeon_device *rdev, bool gate) if (pi->acp_power_gated == gate) return; - if (rdev->family == CHIP_KABINI) + if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) return; pi->acp_power_gated = gate; @@ -1786,7 +1837,7 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) } } - if (rdev->family == CHIP_KABINI) { + if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) { if (pi->enable_dpm) { kv_set_valid_clock_range(rdev, new_ps); kv_update_dfs_bypass_settings(rdev, new_ps); @@ -1812,6 +1863,8 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) return ret; } kv_update_sclk_t(rdev); + if (rdev->family == CHIP_MULLINS) + kv_enable_nb_dpm(rdev); } } else { if (pi->enable_dpm) { @@ -1862,7 +1915,7 @@ void kv_dpm_reset_asic(struct radeon_device *rdev) { struct kv_power_info *pi = kv_get_pi(rdev); - if (rdev->family == CHIP_KABINI) { + if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) { kv_force_lowest_valid(rdev); kv_init_graphics_levels(rdev); kv_program_bootup_state(rdev); @@ -1901,14 +1954,41 @@ static void kv_construct_max_power_limits_table(struct radeon_device *rdev, static void kv_patch_voltage_values(struct radeon_device *rdev) { int i; - struct radeon_uvd_clock_voltage_dependency_table *table = + struct radeon_uvd_clock_voltage_dependency_table *uvd_table = &rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; + struct radeon_vce_clock_voltage_dependency_table *vce_table = + &rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; + struct radeon_clock_voltage_dependency_table *samu_table = + &rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table; + struct radeon_clock_voltage_dependency_table *acp_table = + &rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table; - if (table->count) { - for (i = 0; i < table->count; i++) - table->entries[i].v = + if (uvd_table->count) { + for (i = 0; i < uvd_table->count; i++) + uvd_table->entries[i].v = kv_convert_8bit_index_to_voltage(rdev, - table->entries[i].v); + uvd_table->entries[i].v); + } + + if (vce_table->count) { + for (i = 0; i < vce_table->count; i++) + vce_table->entries[i].v = + kv_convert_8bit_index_to_voltage(rdev, + vce_table->entries[i].v); + } + + if (samu_table->count) { + for (i = 0; i < samu_table->count; i++) + samu_table->entries[i].v = + kv_convert_8bit_index_to_voltage(rdev, + samu_table->entries[i].v); + } + + if (acp_table->count) { + for (i = 0; i < acp_table->count; i++) + acp_table->entries[i].v = + kv_convert_8bit_index_to_voltage(rdev, + acp_table->entries[i].v); } } @@ -1941,7 +2021,7 @@ static int kv_force_dpm_highest(struct radeon_device *rdev) break; } - if (rdev->family == CHIP_KABINI) + if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i); else return kv_set_enabled_level(rdev, i); @@ -1961,7 +2041,7 @@ static int kv_force_dpm_lowest(struct radeon_device *rdev) break; } - if (rdev->family == CHIP_KABINI) + if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i); else return kv_set_enabled_level(rdev, i); @@ -2118,7 +2198,7 @@ static void kv_apply_state_adjust_rules(struct radeon_device *rdev, else pi->battery_state = false; - if (rdev->family == CHIP_KABINI) { + if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) { ps->dpm0_pg_nb_ps_lo = 0x1; ps->dpm0_pg_nb_ps_hi = 0x0; ps->dpmx_nb_ps_lo = 0x1; @@ -2179,7 +2259,7 @@ static int kv_calculate_nbps_level_settings(struct radeon_device *rdev) if (pi->lowest_valid > pi->highest_valid) return -EINVAL; - if (rdev->family == CHIP_KABINI) { + if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) { for (i = pi->lowest_valid; i <= pi->highest_valid; i++) { pi->graphics_level[i].GnbSlow = 1; pi->graphics_level[i].ForceNbPs1 = 0; @@ -2253,9 +2333,9 @@ static void kv_init_graphics_levels(struct radeon_device *rdev) break; kv_set_divider_value(rdev, i, table->entries[i].clk); - vid_2bit = sumo_convert_vid7_to_vid2(rdev, - &pi->sys_info.vid_mapping_table, - table->entries[i].v); + vid_2bit = kv_convert_vid7_to_vid2(rdev, + &pi->sys_info.vid_mapping_table, + table->entries[i].v); kv_set_vid(rdev, i, vid_2bit); kv_set_at(rdev, i, pi->at[i]); kv_dpm_power_level_enabled_for_throttle(rdev, i, true); @@ -2324,7 +2404,7 @@ static void kv_program_nbps_index_settings(struct radeon_device *rdev, struct kv_power_info *pi = kv_get_pi(rdev); u32 nbdpmconfig1; - if (rdev->family == CHIP_KABINI) + if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) return; if (pi->sys_info.nb_dpm_enable) { @@ -2631,9 +2711,6 @@ int kv_dpm_init(struct radeon_device *rdev) pi->sram_end = SMC_RAM_END; - if (rdev->family == CHIP_KABINI) - pi->high_voltage_t = 4001; - pi->enable_nb_dpm = true; pi->caps_power_containment = true; diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 6e887d004eba..bbc189fd3ddc 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2839,6 +2839,7 @@ int r600_copy_cpdma(struct radeon_device *rdev, r = radeon_fence_emit(rdev, fence, ring->idx); if (r) { radeon_ring_unlock_undo(rdev, ring); + radeon_semaphore_free(rdev, &sem, NULL); return r; } @@ -3505,7 +3506,6 @@ int r600_irq_set(struct radeon_device *rdev) u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0; u32 grbm_int_cntl = 0; u32 hdmi0, hdmi1; - u32 d1grph = 0, d2grph = 0; u32 dma_cntl; u32 thermal_int = 0; @@ -3614,8 +3614,8 @@ int r600_irq_set(struct radeon_device *rdev) WREG32(CP_INT_CNTL, cp_int_cntl); WREG32(DMA_CNTL, dma_cntl); WREG32(DxMODE_INT_MASK, mode_int); - WREG32(D1GRPH_INTERRUPT_CONTROL, d1grph); - WREG32(D2GRPH_INTERRUPT_CONTROL, d2grph); + WREG32(D1GRPH_INTERRUPT_CONTROL, DxGRPH_PFLIP_INT_MASK); + WREG32(D2GRPH_INTERRUPT_CONTROL, DxGRPH_PFLIP_INT_MASK); WREG32(GRBM_INT_CNTL, grbm_int_cntl); if (ASIC_IS_DCE3(rdev)) { WREG32(DC_HPD1_INT_CONTROL, hpd1); @@ -3918,6 +3918,14 @@ restart_ih: break; } break; + case 9: /* D1 pflip */ + DRM_DEBUG("IH: D1 flip\n"); + radeon_crtc_handle_flip(rdev, 0); + break; + case 11: /* D2 pflip */ + DRM_DEBUG("IH: D2 flip\n"); + radeon_crtc_handle_flip(rdev, 1); + break; case 19: /* HPD/DAC hotplug */ switch (src_data) { case 0: diff --git a/drivers/gpu/drm/radeon/r600_dma.c b/drivers/gpu/drm/radeon/r600_dma.c index 53fcb28f5578..4969cef44a19 100644 --- a/drivers/gpu/drm/radeon/r600_dma.c +++ b/drivers/gpu/drm/radeon/r600_dma.c @@ -489,6 +489,7 @@ int r600_copy_dma(struct radeon_device *rdev, r = radeon_fence_emit(rdev, fence, ring->idx); if (r) { radeon_ring_unlock_undo(rdev, ring); + radeon_semaphore_free(rdev, &sem, NULL); return r; } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index b58e1afdda76..68528619834a 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -730,6 +730,12 @@ struct cik_irq_stat_regs { u32 disp_int_cont4; u32 disp_int_cont5; u32 disp_int_cont6; + u32 d1grph_int; + u32 d2grph_int; + u32 d3grph_int; + u32 d4grph_int; + u32 d5grph_int; + u32 d6grph_int; }; union radeon_irq_stat_regs { diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index b8a24a75d4ff..be20e62dac83 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -2516,6 +2516,7 @@ int radeon_asic_init(struct radeon_device *rdev) break; case CHIP_KAVERI: case CHIP_KABINI: + case CHIP_MULLINS: rdev->asic = &kv_asic; /* set num crtcs */ if (rdev->family == CHIP_KAVERI) { diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 511fe26198e4..0e770bbf7e29 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -99,6 +99,7 @@ static const char radeon_family_name[][16] = { "KAVERI", "KABINI", "HAWAII", + "MULLINS", "LAST", }; diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 8d99d5ee8014..408b6ac53f0b 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -284,6 +284,10 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) u32 update_pending; int vpos, hpos; + /* can happen during initialization */ + if (radeon_crtc == NULL) + return; + spin_lock_irqsave(&rdev->ddev->event_lock, flags); work = radeon_crtc->unpin_work; if (work == NULL || @@ -826,14 +830,14 @@ static void avivo_reduce_ratio(unsigned *nom, unsigned *den, /* make sure nominator is large enough */ if (*nom < nom_min) { - tmp = (nom_min + *nom - 1) / *nom; + tmp = DIV_ROUND_UP(nom_min, *nom); *nom *= tmp; *den *= tmp; } /* make sure the denominator is large enough */ if (*den < den_min) { - tmp = (den_min + *den - 1) / *den; + tmp = DIV_ROUND_UP(den_min, *den); *nom *= tmp; *den *= tmp; } @@ -858,7 +862,7 @@ static void avivo_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div, unsigned *fb_div, unsigned *ref_div) { /* limit reference * post divider to a maximum */ - ref_div_max = min(210 / post_div, ref_div_max); + ref_div_max = min(128 / post_div, ref_div_max); /* get matching reference and feedback divider */ *ref_div = min(max(DIV_ROUND_CLOSEST(den, post_div), 1u), ref_div_max); @@ -993,6 +997,16 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, /* this also makes sure that the reference divider is large enough */ avivo_reduce_ratio(&fb_div, &ref_div, fb_div_min, ref_div_min); + /* avoid high jitter with small fractional dividers */ + if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV && (fb_div % 10)) { + fb_div_min = max(fb_div_min, (9 - (fb_div % 10)) * 20 + 60); + if (fb_div < fb_div_min) { + unsigned tmp = DIV_ROUND_UP(fb_div_min, fb_div); + fb_div *= tmp; + ref_div *= tmp; + } + } + /* and finally save the result */ if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) { *fb_div_p = fb_div / 10; diff --git a/drivers/gpu/drm/radeon/radeon_family.h b/drivers/gpu/drm/radeon/radeon_family.h index 9da5da4ffd17..4b7b87f71a63 100644 --- a/drivers/gpu/drm/radeon/radeon_family.h +++ b/drivers/gpu/drm/radeon/radeon_family.h @@ -97,6 +97,7 @@ enum radeon_family { CHIP_KAVERI, CHIP_KABINI, CHIP_HAWAII, + CHIP_MULLINS, CHIP_LAST, }; diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 6fac8efe8340..f30b8426eee2 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -1300,6 +1300,7 @@ int radeon_pm_init(struct radeon_device *rdev) case CHIP_KABINI: case CHIP_KAVERI: case CHIP_HAWAII: + case CHIP_MULLINS: /* DPM requires the RLC, RV770+ dGPU requires SMC */ if (!rdev->rlc_fw) rdev->pm.pm_method = PM_METHOD_PROFILE; diff --git a/drivers/gpu/drm/radeon/radeon_ucode.h b/drivers/gpu/drm/radeon/radeon_ucode.h index 58d12938c0b8..4e7c3269b183 100644 --- a/drivers/gpu/drm/radeon/radeon_ucode.h +++ b/drivers/gpu/drm/radeon/radeon_ucode.h @@ -52,6 +52,7 @@ #define BONAIRE_RLC_UCODE_SIZE 2048 #define KB_RLC_UCODE_SIZE 2560 #define KV_RLC_UCODE_SIZE 2560 +#define ML_RLC_UCODE_SIZE 2560 /* MC */ #define BTC_MC_UCODE_SIZE 6024 diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 5748bdaeacce..1b65ae2433cd 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -99,6 +99,7 @@ int radeon_uvd_init(struct radeon_device *rdev) case CHIP_KABINI: case CHIP_KAVERI: case CHIP_HAWAII: + case CHIP_MULLINS: fw_name = FIRMWARE_BONAIRE; break; @@ -465,6 +466,10 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p, cmd = radeon_get_ib_value(p, p->idx) >> 1; if (cmd < 0x4) { + if (end <= start) { + DRM_ERROR("invalid reloc offset %X!\n", offset); + return -EINVAL; + } if ((end - start) < buf_sizes[cmd]) { DRM_ERROR("buffer (%d) to small (%d / %d)!\n", cmd, (unsigned)(end - start), buf_sizes[cmd]); diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c index ced53dd03e7c..f73324c81491 100644 --- a/drivers/gpu/drm/radeon/radeon_vce.c +++ b/drivers/gpu/drm/radeon/radeon_vce.c @@ -66,6 +66,7 @@ int radeon_vce_init(struct radeon_device *rdev) case CHIP_BONAIRE: case CHIP_KAVERI: case CHIP_KABINI: + case CHIP_MULLINS: fw_name = FIRMWARE_BONAIRE; break; diff --git a/drivers/gpu/drm/radeon/rv770_dma.c b/drivers/gpu/drm/radeon/rv770_dma.c index aca8cbe8a335..bbf2e076ee45 100644 --- a/drivers/gpu/drm/radeon/rv770_dma.c +++ b/drivers/gpu/drm/radeon/rv770_dma.c @@ -86,6 +86,7 @@ int rv770_copy_dma(struct radeon_device *rdev, r = radeon_fence_emit(rdev, fence, ring->idx); if (r) { radeon_ring_unlock_undo(rdev, ring); + radeon_semaphore_free(rdev, &sem, NULL); return r; } diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index ac708e006180..22a63c98ba14 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -5780,7 +5780,6 @@ int si_irq_set(struct radeon_device *rdev) u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0; u32 hpd1 = 0, hpd2 = 0, hpd3 = 0, hpd4 = 0, hpd5 = 0, hpd6 = 0; u32 grbm_int_cntl = 0; - u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0; u32 dma_cntl, dma_cntl1; u32 thermal_int = 0; @@ -5919,16 +5918,22 @@ int si_irq_set(struct radeon_device *rdev) } if (rdev->num_crtc >= 2) { - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); } if (rdev->num_crtc >= 4) { - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); } if (rdev->num_crtc >= 6) { - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, + GRPH_PFLIP_INT_MASK); } if (!ASIC_IS_NODCE(rdev)) { @@ -6292,6 +6297,15 @@ restart_ih: break; } break; + case 8: /* D1 page flip */ + case 10: /* D2 page flip */ + case 12: /* D3 page flip */ + case 14: /* D4 page flip */ + case 16: /* D5 page flip */ + case 18: /* D6 page flip */ + DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1); + radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1); + break; case 42: /* HPD hotplug */ switch (src_data) { case 0: diff --git a/drivers/gpu/drm/radeon/si_dma.c b/drivers/gpu/drm/radeon/si_dma.c index cf0fdad8c278..de0ca070122f 100644 --- a/drivers/gpu/drm/radeon/si_dma.c +++ b/drivers/gpu/drm/radeon/si_dma.c @@ -213,6 +213,7 @@ int si_copy_dma(struct radeon_device *rdev, r = radeon_fence_emit(rdev, fence, ring->idx); if (r) { radeon_ring_unlock_undo(rdev, ring); + radeon_semaphore_free(rdev, &sem, NULL); return r; } diff --git a/drivers/gpu/drm/radeon/uvd_v1_0.c b/drivers/gpu/drm/radeon/uvd_v1_0.c index 0a243f0e5d68..be42c8125203 100644 --- a/drivers/gpu/drm/radeon/uvd_v1_0.c +++ b/drivers/gpu/drm/radeon/uvd_v1_0.c @@ -83,7 +83,10 @@ int uvd_v1_0_init(struct radeon_device *rdev) int r; /* raise clocks while booting up the VCPU */ - radeon_set_uvd_clocks(rdev, 53300, 40000); + if (rdev->family < CHIP_RV740) + radeon_set_uvd_clocks(rdev, 10000, 10000); + else + radeon_set_uvd_clocks(rdev, 53300, 40000); r = uvd_v1_0_start(rdev); if (r) @@ -407,7 +410,10 @@ int uvd_v1_0_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) struct radeon_fence *fence = NULL; int r; - r = radeon_set_uvd_clocks(rdev, 53300, 40000); + if (rdev->family < CHIP_RV740) + r = radeon_set_uvd_clocks(rdev, 10000, 10000); + else + r = radeon_set_uvd_clocks(rdev, 53300, 40000); if (r) { DRM_ERROR("radeon: failed to raise UVD clocks (%d).\n", r); return r; diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 36c717af6cf9..edb871d7d395 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -312,7 +312,7 @@ static void tegra_crtc_disable(struct drm_crtc *crtc) struct drm_device *drm = crtc->dev; struct drm_plane *plane; - list_for_each_entry(plane, &drm->mode_config.plane_list, head) { + drm_for_each_legacy_plane(plane, &drm->mode_config.plane_list) { if (plane->crtc == crtc) { tegra_plane_disable(plane); plane->crtc = NULL; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 931490b9cfed..87df0b3674fd 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -1214,14 +1214,36 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv, SVGA3dCmdSurfaceDMA dma; } *cmd; int ret; + SVGA3dCmdSurfaceDMASuffix *suffix; + uint32_t bo_size; cmd = container_of(header, struct vmw_dma_cmd, header); + suffix = (SVGA3dCmdSurfaceDMASuffix *)((unsigned long) &cmd->dma + + header->size - sizeof(*suffix)); + + /* Make sure device and verifier stays in sync. */ + if (unlikely(suffix->suffixSize != sizeof(*suffix))) { + DRM_ERROR("Invalid DMA suffix size.\n"); + return -EINVAL; + } + ret = vmw_translate_guest_ptr(dev_priv, sw_context, &cmd->dma.guest.ptr, &vmw_bo); if (unlikely(ret != 0)) return ret; + /* Make sure DMA doesn't cross BO boundaries. */ + bo_size = vmw_bo->base.num_pages * PAGE_SIZE; + if (unlikely(cmd->dma.guest.ptr.offset > bo_size)) { + DRM_ERROR("Invalid DMA offset.\n"); + return -EINVAL; + } + + bo_size -= cmd->dma.guest.ptr.offset; + if (unlikely(suffix->maximumOffset > bo_size)) + suffix->maximumOffset = bo_size; + ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, user_surface_converter, &cmd->dma.host.sid, NULL); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 10a2c0866459..da52279de939 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1253,7 +1253,8 @@ EXPORT_SYMBOL_GPL(hid_output_report); static int hid_report_len(struct hid_report *report) { - return ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7; + /* equivalent to DIV_ROUND_UP(report->size, 8) + !!(report->id > 0) */ + return ((report->size - 1) >> 3) + 1 + (report->id > 0); } /* @@ -1266,7 +1267,7 @@ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags) * of implement() working on 8 byte chunks */ - int len = hid_report_len(report); + int len = hid_report_len(report) + 7; return kmalloc(len, flags); } diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index c8af7202c28d..34bb2205d2ea 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -301,6 +301,9 @@ #define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34 +#define USB_VENDOR_ID_ELITEGROUP 0x03fc +#define USB_DEVICE_ID_ELITEGROUP_05D8 0x05d8 + #define USB_VENDOR_ID_ELO 0x04E7 #define USB_DEVICE_ID_ELO_TS2515 0x0022 #define USB_DEVICE_ID_ELO_TS2700 0x0020 @@ -834,6 +837,10 @@ #define USB_DEVICE_ID_SYNAPTICS_LTS2 0x1d10 #define USB_DEVICE_ID_SYNAPTICS_HD 0x0ac3 #define USB_DEVICE_ID_SYNAPTICS_QUAD_HD 0x1ac3 +#define USB_DEVICE_ID_SYNAPTICS_TP_V103 0x5710 + +#define USB_VENDOR_ID_TEXAS_INSTRUMENTS 0x2047 +#define USB_DEVICE_ID_TEXAS_INSTRUMENTS_LENOVO_YOGA 0x0855 #define USB_VENDOR_ID_THINGM 0x27b8 #define USB_DEVICE_ID_BLINK1 0x01ed diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 35278e43c7a4..51e25b9407f2 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1155,6 +1155,11 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) }, + /* Elitegroup panel */ + { .driver_data = MT_CLS_SERIAL, + MT_USB_DEVICE(USB_VENDOR_ID_ELITEGROUP, + USB_DEVICE_ID_ELITEGROUP_05D8) }, + /* Flatfrog Panels */ { .driver_data = MT_CLS_FLATFROG, MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG, diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index af8244b1c1f4..be14b5690e94 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -708,6 +708,9 @@ static const struct hid_device_id sensor_hub_devices[] = { { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0, USB_DEVICE_ID_STM_HID_SENSOR), .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, + { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_TEXAS_INSTRUMENTS, + USB_DEVICE_ID_TEXAS_INSTRUMENTS_LENOVO_YOGA), + .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID, HID_ANY_ID) }, { } diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index dbd83878ff99..8e4ddb369883 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -119,6 +119,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103, HID_QUIRK_NO_INIT_REPORTS }, { 0, 0 } }; diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 6d02e3b06375..d76f0b70c6e0 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -365,12 +365,12 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) if (cpu_has_tjmax(c)) dev_warn(dev, "Unable to read TjMax from CPU %u\n", id); } else { - val = (eax >> 16) & 0x7f; + val = (eax >> 16) & 0xff; /* * If the TjMax is not plausible, an assumption * will be used */ - if (val >= 85) { + if (val) { dev_dbg(dev, "TjMax is %d degrees C\n", val); return val * 1000; } diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c index 90ec1173b8a1..01723f04fe45 100644 --- a/drivers/hwmon/emc1403.c +++ b/drivers/hwmon/emc1403.c @@ -163,7 +163,7 @@ static ssize_t store_hyst(struct device *dev, if (retval < 0) goto fail; - hyst = val - retval * 1000; + hyst = retval * 1000 - val; hyst = DIV_ROUND_CLOSEST(hyst, 1000); if (hyst < 0 || hyst > 255) { retval = -ERANGE; @@ -330,7 +330,7 @@ static int emc1403_detect(struct i2c_client *client, } id = i2c_smbus_read_byte_data(client, THERMAL_REVISION_REG); - if (id != 0x01) + if (id < 0x01 || id > 0x04) return -ENODEV; return 0; @@ -355,9 +355,9 @@ static int emc1403_probe(struct i2c_client *client, if (id->driver_data) data->groups[1] = &emc1404_group; - hwmon_dev = hwmon_device_register_with_groups(&client->dev, - client->name, data, - data->groups); + hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev, + client->name, data, + data->groups); if (IS_ERR(hwmon_dev)) return PTR_ERR(hwmon_dev); diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index d86196cfe4b4..24c28e3f93a3 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -106,7 +106,7 @@ config AT91_ADC Say yes here to build support for Atmel AT91 ADC. config EXYNOS_ADC - bool "Exynos ADC driver support" + tristate "Exynos ADC driver support" depends on OF help Core support for the ADC block found in the Samsung EXYNOS series @@ -114,7 +114,7 @@ config EXYNOS_ADC this resource. config LP8788_ADC - bool "LP8788 ADC driver" + tristate "LP8788 ADC driver" depends on MFD_LP8788 help Say yes here to build support for TI LP8788 ADC. diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c index d25b262193a7..affa93f51789 100644 --- a/drivers/iio/adc/exynos_adc.c +++ b/drivers/iio/adc/exynos_adc.c @@ -344,7 +344,7 @@ static int exynos_adc_probe(struct platform_device *pdev) exynos_adc_hw_init(info); - ret = of_platform_populate(np, exynos_adc_match, NULL, &pdev->dev); + ret = of_platform_populate(np, exynos_adc_match, NULL, &indio_dev->dev); if (ret < 0) { dev_err(&pdev->dev, "failed adding child nodes\n"); goto err_of_populate; @@ -353,7 +353,7 @@ static int exynos_adc_probe(struct platform_device *pdev) return 0; err_of_populate: - device_for_each_child(&pdev->dev, NULL, + device_for_each_child(&indio_dev->dev, NULL, exynos_adc_remove_devices); regulator_disable(info->vdd); clk_disable_unprepare(info->clk); @@ -369,7 +369,7 @@ static int exynos_adc_remove(struct platform_device *pdev) struct iio_dev *indio_dev = platform_get_drvdata(pdev); struct exynos_adc *info = iio_priv(indio_dev); - device_for_each_child(&pdev->dev, NULL, + device_for_each_child(&indio_dev->dev, NULL, exynos_adc_remove_devices); regulator_disable(info->vdd); clk_disable_unprepare(info->clk); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index cb9f96b446a5..d8ad606c7cd0 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -660,6 +660,7 @@ static int inv_mpu_probe(struct i2c_client *client, { struct inv_mpu6050_state *st; struct iio_dev *indio_dev; + struct inv_mpu6050_platform_data *pdata; int result; if (!i2c_check_functionality(client->adapter, @@ -672,8 +673,10 @@ static int inv_mpu_probe(struct i2c_client *client, st = iio_priv(indio_dev); st->client = client; - st->plat_data = *(struct inv_mpu6050_platform_data - *)dev_get_platdata(&client->dev); + pdata = (struct inv_mpu6050_platform_data + *)dev_get_platdata(&client->dev); + if (pdata) + st->plat_data = *pdata; /* power is turned on inside check chip type*/ result = inv_check_and_setup_chip(st, id); if (result) diff --git a/drivers/infiniband/hw/cxgb4/Kconfig b/drivers/infiniband/hw/cxgb4/Kconfig index d4e8983fba53..23f38cf2c5cd 100644 --- a/drivers/infiniband/hw/cxgb4/Kconfig +++ b/drivers/infiniband/hw/cxgb4/Kconfig @@ -1,10 +1,10 @@ config INFINIBAND_CXGB4 - tristate "Chelsio T4 RDMA Driver" + tristate "Chelsio T4/T5 RDMA Driver" depends on CHELSIO_T4 && INET && (IPV6 || IPV6=n) select GENERIC_ALLOCATOR ---help--- - This is an iWARP/RDMA driver for the Chelsio T4 1GbE and - 10GbE adapters. + This is an iWARP/RDMA driver for the Chelsio T4 and T5 + 1GbE, 10GbE adapters and T5 40GbE adapter. For general information about Chelsio and our products, visit our website at <http://www.chelsio.com>. diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 185452abf32c..1f863a96a480 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -587,6 +587,10 @@ static int send_connect(struct c4iw_ep *ep) opt2 |= SACK_EN(1); if (wscale && enable_tcp_window_scaling) opt2 |= WND_SCALE_EN(1); + if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) { + opt2 |= T5_OPT_2_VALID; + opt2 |= V_CONG_CNTRL(CONG_ALG_TAHOE); + } t4_set_arp_err_handler(skb, NULL, act_open_req_arp_failure); if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) { @@ -996,7 +1000,7 @@ static void close_complete_upcall(struct c4iw_ep *ep, int status) static int abort_connection(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp) { PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); - state_set(&ep->com, ABORTING); + __state_set(&ep->com, ABORTING); set_bit(ABORT_CONN, &ep->com.history); return send_abort(ep, skb, gfp); } @@ -1154,7 +1158,7 @@ static int update_rx_credits(struct c4iw_ep *ep, u32 credits) return credits; } -static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb) +static int process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb) { struct mpa_message *mpa; struct mpa_v2_conn_params *mpa_v2_params; @@ -1164,6 +1168,7 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb) struct c4iw_qp_attributes attrs; enum c4iw_qp_attr_mask mask; int err; + int disconnect = 0; PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); @@ -1173,7 +1178,7 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb) * will abort the connection. */ if (stop_ep_timer(ep)) - return; + return 0; /* * If we get more than the supported amount of private data @@ -1195,7 +1200,7 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb) * if we don't even have the mpa message, then bail. */ if (ep->mpa_pkt_len < sizeof(*mpa)) - return; + return 0; mpa = (struct mpa_message *) ep->mpa_pkt; /* Validate MPA header. */ @@ -1235,7 +1240,7 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb) * We'll continue process when more data arrives. */ if (ep->mpa_pkt_len < (sizeof(*mpa) + plen)) - return; + return 0; if (mpa->flags & MPA_REJECT) { err = -ECONNREFUSED; @@ -1337,9 +1342,11 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb) attrs.layer_etype = LAYER_MPA | DDP_LLP; attrs.ecode = MPA_NOMATCH_RTR; attrs.next_state = C4IW_QP_STATE_TERMINATE; + attrs.send_term = 1; err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, - C4IW_QP_ATTR_NEXT_STATE, &attrs, 0); + C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); err = -ENOMEM; + disconnect = 1; goto out; } @@ -1355,9 +1362,11 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb) attrs.layer_etype = LAYER_MPA | DDP_LLP; attrs.ecode = MPA_INSUFF_IRD; attrs.next_state = C4IW_QP_STATE_TERMINATE; + attrs.send_term = 1; err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, - C4IW_QP_ATTR_NEXT_STATE, &attrs, 0); + C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); err = -ENOMEM; + disconnect = 1; goto out; } goto out; @@ -1366,7 +1375,7 @@ err: send_abort(ep, skb, GFP_KERNEL); out: connect_reply_upcall(ep, err); - return; + return disconnect; } static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb) @@ -1524,6 +1533,7 @@ static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb) unsigned int tid = GET_TID(hdr); struct tid_info *t = dev->rdev.lldi.tids; __u8 status = hdr->status; + int disconnect = 0; ep = lookup_tid(t, tid); if (!ep) @@ -1539,7 +1549,7 @@ static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb) switch (ep->com.state) { case MPA_REQ_SENT: ep->rcv_seq += dlen; - process_mpa_reply(ep, skb); + disconnect = process_mpa_reply(ep, skb); break; case MPA_REQ_WAIT: ep->rcv_seq += dlen; @@ -1555,13 +1565,16 @@ static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb) ep->com.state, ep->hwtid, status); attrs.next_state = C4IW_QP_STATE_TERMINATE; c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, - C4IW_QP_ATTR_NEXT_STATE, &attrs, 0); + C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); + disconnect = 1; break; } default: break; } mutex_unlock(&ep->com.mutex); + if (disconnect) + c4iw_ep_disconnect(ep, 0, GFP_KERNEL); return 0; } @@ -2009,6 +2022,10 @@ static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb, if (tcph->ece && tcph->cwr) opt2 |= CCTRL_ECN(1); } + if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) { + opt2 |= T5_OPT_2_VALID; + opt2 |= V_CONG_CNTRL(CONG_ALG_TAHOE); + } rpl = cplhdr(skb); INIT_TP_WR(rpl, ep->hwtid); @@ -3482,9 +3499,9 @@ static void process_timeout(struct c4iw_ep *ep) __func__, ep, ep->hwtid, ep->com.state); abort = 0; } - mutex_unlock(&ep->com.mutex); if (abort) abort_connection(ep, NULL, GFP_KERNEL); + mutex_unlock(&ep->com.mutex); c4iw_put_ep(&ep->com); } diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h index 7b8c5806a09d..7474b490760a 100644 --- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h @@ -435,6 +435,7 @@ struct c4iw_qp_attributes { u8 ecode; u16 sq_db_inc; u16 rq_db_inc; + u8 send_term; }; struct c4iw_qp { diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index 7b5114cb486f..086f62f5dc9e 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -1388,11 +1388,12 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp, qhp->attr.layer_etype = attrs->layer_etype; qhp->attr.ecode = attrs->ecode; ep = qhp->ep; - disconnect = 1; - c4iw_get_ep(&qhp->ep->com); - if (!internal) + if (!internal) { + c4iw_get_ep(&qhp->ep->com); terminate = 1; - else { + disconnect = 1; + } else { + terminate = qhp->attr.send_term; ret = rdma_fini(rhp, qhp, ep); if (ret) goto err; @@ -1776,11 +1777,15 @@ int c4iw_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, /* * Use SQ_PSN and RQ_PSN to pass in IDX_INC values for * ringing the queue db when we're in DB_FULL mode. + * Only allow this on T4 devices. */ attrs.sq_db_inc = attr->sq_psn; attrs.rq_db_inc = attr->rq_psn; mask |= (attr_mask & IB_QP_SQ_PSN) ? C4IW_QP_ATTR_SQ_DB : 0; mask |= (attr_mask & IB_QP_RQ_PSN) ? C4IW_QP_ATTR_RQ_DB : 0; + if (is_t5(to_c4iw_qp(ibqp)->rhp->rdev.lldi.adapter_type) && + (mask & (C4IW_QP_ATTR_SQ_DB|C4IW_QP_ATTR_RQ_DB))) + return -EINVAL; return c4iw_modify_qp(rhp, qhp, mask, &attrs, 0); } diff --git a/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h b/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h index dc193c292671..6121ca08fe58 100644 --- a/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h +++ b/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h @@ -836,4 +836,18 @@ struct ulptx_idata { #define V_RX_DACK_CHANGE(x) ((x) << S_RX_DACK_CHANGE) #define F_RX_DACK_CHANGE V_RX_DACK_CHANGE(1U) +enum { /* TCP congestion control algorithms */ + CONG_ALG_RENO, + CONG_ALG_TAHOE, + CONG_ALG_NEWRENO, + CONG_ALG_HIGHSPEED +}; + +#define S_CONG_CNTRL 14 +#define M_CONG_CNTRL 0x3 +#define V_CONG_CNTRL(x) ((x) << S_CONG_CNTRL) +#define G_CONG_CNTRL(x) (((x) >> S_CONG_CNTRL) & M_CONG_CNTRL) + +#define T5_OPT_2_VALID (1 << 31) + #endif /* _T4FW_RI_API_H_ */ diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 2626773ff29b..2dd1d0dd4f7d 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -243,6 +243,12 @@ static void (*atkbd_platform_fixup)(struct atkbd *, const void *data); static void *atkbd_platform_fixup_data; static unsigned int (*atkbd_platform_scancode_fixup)(struct atkbd *, unsigned int); +/* + * Certain keyboards to not like ATKBD_CMD_RESET_DIS and stop responding + * to many commands until full reset (ATKBD_CMD_RESET_BAT) is performed. + */ +static bool atkbd_skip_deactivate; + static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, ssize_t (*handler)(struct atkbd *, char *)); static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count, @@ -768,7 +774,8 @@ static int atkbd_probe(struct atkbd *atkbd) * Make sure nothing is coming from the keyboard and disturbs our * internal state. */ - atkbd_deactivate(atkbd); + if (!atkbd_skip_deactivate) + atkbd_deactivate(atkbd); return 0; } @@ -1638,6 +1645,12 @@ static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id) return 1; } +static int __init atkbd_deactivate_fixup(const struct dmi_system_id *id) +{ + atkbd_skip_deactivate = true; + return 1; +} + static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = { { .matches = { @@ -1775,6 +1788,20 @@ static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = { .callback = atkbd_setup_scancode_fixup, .driver_data = atkbd_oqo_01plus_scancode_fixup, }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), + DMI_MATCH(DMI_PRODUCT_NAME, "LW25-B7HV"), + }, + .callback = atkbd_deactivate_fixup, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), + DMI_MATCH(DMI_PRODUCT_NAME, "P1-J273B"), + }, + .callback = atkbd_deactivate_fixup, + }, { } }; diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c index 55c15304ddbc..4e491c1762cf 100644 --- a/drivers/input/keyboard/tca8418_keypad.c +++ b/drivers/input/keyboard/tca8418_keypad.c @@ -392,6 +392,13 @@ static const struct of_device_id tca8418_dt_ids[] = { { } }; MODULE_DEVICE_TABLE(of, tca8418_dt_ids); + +/* + * The device tree based i2c loader looks for + * "i2c:" + second_component_of(property("compatible")) + * and therefore we need an alias to be found. + */ +MODULE_ALIAS("i2c:tca8418"); #endif static struct i2c_driver tca8418_keypad_driver = { diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c index 52d3a9b28f0b..b36831c828d3 100644 --- a/drivers/input/misc/bma150.c +++ b/drivers/input/misc/bma150.c @@ -70,6 +70,7 @@ #define BMA150_CFG_5_REG 0x11 #define BMA150_CHIP_ID 2 +#define BMA180_CHIP_ID 3 #define BMA150_CHIP_ID_REG BMA150_DATA_0_REG #define BMA150_ACC_X_LSB_REG BMA150_DATA_2_REG @@ -539,7 +540,7 @@ static int bma150_probe(struct i2c_client *client, } chip_id = i2c_smbus_read_byte_data(client, BMA150_CHIP_ID_REG); - if (chip_id != BMA150_CHIP_ID) { + if (chip_id != BMA150_CHIP_ID && chip_id != BMA180_CHIP_ID) { dev_err(&client->dev, "BMA150 chip id error: %d\n", chip_id); return -EINVAL; } @@ -643,6 +644,7 @@ static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL); static const struct i2c_device_id bma150_id[] = { { "bma150", 0 }, + { "bma180", 0 }, { "smb380", 0 }, { "bma023", 0 }, { } diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 088d3541c7d3..b96e978a37b7 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -11,6 +11,7 @@ */ #include <linux/delay.h> +#include <linux/dmi.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/input.h> @@ -831,7 +832,11 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) break; case 3: - etd->reg_10 = 0x0b; + if (etd->set_hw_resolution) + etd->reg_10 = 0x0b; + else + etd->reg_10 = 0x03; + if (elantech_write_reg(psmouse, 0x10, etd->reg_10)) rc = -1; @@ -1331,6 +1336,22 @@ static int elantech_reconnect(struct psmouse *psmouse) } /* + * Some hw_version 3 models go into error state when we try to set bit 3 of r10 + */ +static const struct dmi_system_id no_hw_res_dmi_table[] = { +#if defined(CONFIG_DMI) && defined(CONFIG_X86) + { + /* Gigabyte U2442 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), + DMI_MATCH(DMI_PRODUCT_NAME, "U2442"), + }, + }, +#endif + { } +}; + +/* * determine hardware version and set some properties according to it. */ static int elantech_set_properties(struct elantech_data *etd) @@ -1390,6 +1411,9 @@ static int elantech_set_properties(struct elantech_data *etd) */ etd->crc_enabled = ((etd->fw_version & 0x4000) == 0x4000); + /* Enable real hardware resolution on hw_version 3 ? */ + etd->set_hw_resolution = !dmi_check_system(no_hw_res_dmi_table); + return 0; } diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index 036a04abaef7..9e0e2a1f340d 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h @@ -130,6 +130,7 @@ struct elantech_data { bool jumpy_cursor; bool reports_pressure; bool crc_enabled; + bool set_hw_resolution; unsigned char hw_version; unsigned int fw_version; unsigned int single_finger_reports; diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index ef9f4913450d..d68d33fb5ac2 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -1566,6 +1566,14 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = { .driver_data = (int []){1232, 5710, 1156, 4696}, }, { + /* Lenovo ThinkPad Edge E431 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Edge E431"), + }, + .driver_data = (int []){1024, 5022, 2508, 4832}, + }, + { /* Lenovo ThinkPad T431s */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 41be897df8d5..3899ba7821c5 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -41,6 +41,7 @@ #define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30) #define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS (0x34) #define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4) +#define ARMADA_370_XP_INT_SOURCE_CPU_MASK 0xF #define ARMADA_370_XP_CPU_INTACK_OFFS (0x44) #define ARMADA_375_PPI_CAUSE (0x10) @@ -132,8 +133,7 @@ static int armada_370_xp_setup_msi_irq(struct msi_chip *chip, struct msi_desc *desc) { struct msi_msg msg; - irq_hw_number_t hwirq; - int virq; + int virq, hwirq; hwirq = armada_370_xp_alloc_msi(); if (hwirq < 0) @@ -159,8 +159,19 @@ static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip, unsigned int irq) { struct irq_data *d = irq_get_irq_data(irq); + unsigned long hwirq = d->hwirq; + irq_dispose_mapping(irq); - armada_370_xp_free_msi(d->hwirq); + armada_370_xp_free_msi(hwirq); +} + +static int armada_370_xp_check_msi_device(struct msi_chip *chip, struct pci_dev *dev, + int nvec, int type) +{ + /* We support MSI, but not MSI-X */ + if (type == PCI_CAP_ID_MSI) + return 0; + return -EINVAL; } static struct irq_chip armada_370_xp_msi_irq_chip = { @@ -201,6 +212,7 @@ static int armada_370_xp_msi_init(struct device_node *node, msi_chip->setup_irq = armada_370_xp_setup_msi_irq; msi_chip->teardown_irq = armada_370_xp_teardown_msi_irq; + msi_chip->check_device = armada_370_xp_check_msi_device; msi_chip->of_node = node; armada_370_xp_msi_domain = @@ -244,35 +256,18 @@ static DEFINE_RAW_SPINLOCK(irq_controller_lock); static int armada_xp_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force) { - unsigned long reg; - unsigned long new_mask = 0; - unsigned long online_mask = 0; - unsigned long count = 0; irq_hw_number_t hwirq = irqd_to_hwirq(d); + unsigned long reg, mask; int cpu; - for_each_cpu(cpu, mask_val) { - new_mask |= 1 << cpu_logical_map(cpu); - count++; - } - - /* - * Forbid mutlicore interrupt affinity - * This is required since the MPIC HW doesn't limit - * several CPUs from acknowledging the same interrupt. - */ - if (count > 1) - return -EINVAL; - - for_each_cpu(cpu, cpu_online_mask) - online_mask |= 1 << cpu_logical_map(cpu); + /* Select a single core from the affinity mask which is online */ + cpu = cpumask_any_and(mask_val, cpu_online_mask); + mask = 1UL << cpu_logical_map(cpu); raw_spin_lock(&irq_controller_lock); - reg = readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); - reg = (reg & (~online_mask)) | new_mask; + reg = (reg & (~ARMADA_370_XP_INT_SOURCE_CPU_MASK)) | mask; writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); - raw_spin_unlock(&irq_controller_lock); return 0; @@ -494,15 +489,6 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, #ifdef CONFIG_SMP armada_xp_mpic_smp_cpu_init(); - - /* - * Set the default affinity from all CPUs to the boot cpu. - * This is required since the MPIC doesn't limit several CPUs - * from acknowledging the same interrupt. - */ - cpumask_clear(irq_default_affinity); - cpumask_set_cpu(smp_processor_id(), irq_default_affinity); - #endif armada_370_xp_msi_init(node, main_int_res.start); diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c index fc817d28d1fe..3d15d16a7088 100644 --- a/drivers/irqchip/irq-crossbar.c +++ b/drivers/irqchip/irq-crossbar.c @@ -107,7 +107,7 @@ static int __init crossbar_of_init(struct device_node *node) int i, size, max, reserved = 0, entry; const __be32 *irqsr; - cb = kzalloc(sizeof(struct cb_device *), GFP_KERNEL); + cb = kzalloc(sizeof(*cb), GFP_KERNEL); if (!cb) return -ENOMEM; diff --git a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c index 51dae9167238..96d1df05044f 100644 --- a/drivers/isdn/hisax/icc.c +++ b/drivers/isdn/hisax/icc.c @@ -425,7 +425,7 @@ afterXPR: if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ICC %02x -> MOX1", cs->dc.icc.mon_tx[cs->dc.icc.mon_txp - 1]); } - AfterMOX1: + AfterMOX1: ; #endif } } diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 1bf4a71919ec..9380be7b1895 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -2488,6 +2488,7 @@ static int cache_map(struct dm_target *ti, struct bio *bio) } else { inc_hit_counter(cache, bio); + pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds); if (bio_data_dir(bio) == WRITE && writethrough_mode(&cache->features) && !is_dirty(cache, lookup_result.cblock)) diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 53728be84dee..13abade76ad9 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -232,6 +232,13 @@ struct thin_c { struct bio_list deferred_bio_list; struct bio_list retry_on_resume_list; struct rb_root sort_bio_list; /* sorted list of deferred bios */ + + /* + * Ensures the thin is not destroyed until the worker has finished + * iterating the active_thins list. + */ + atomic_t refcount; + struct completion can_destroy; }; /*----------------------------------------------------------------*/ @@ -1486,6 +1493,45 @@ static void process_thin_deferred_bios(struct thin_c *tc) blk_finish_plug(&plug); } +static void thin_get(struct thin_c *tc); +static void thin_put(struct thin_c *tc); + +/* + * We can't hold rcu_read_lock() around code that can block. So we + * find a thin with the rcu lock held; bump a refcount; then drop + * the lock. + */ +static struct thin_c *get_first_thin(struct pool *pool) +{ + struct thin_c *tc = NULL; + + rcu_read_lock(); + if (!list_empty(&pool->active_thins)) { + tc = list_entry_rcu(pool->active_thins.next, struct thin_c, list); + thin_get(tc); + } + rcu_read_unlock(); + + return tc; +} + +static struct thin_c *get_next_thin(struct pool *pool, struct thin_c *tc) +{ + struct thin_c *old_tc = tc; + + rcu_read_lock(); + list_for_each_entry_continue_rcu(tc, &pool->active_thins, list) { + thin_get(tc); + thin_put(old_tc); + rcu_read_unlock(); + return tc; + } + thin_put(old_tc); + rcu_read_unlock(); + + return NULL; +} + static void process_deferred_bios(struct pool *pool) { unsigned long flags; @@ -1493,10 +1539,11 @@ static void process_deferred_bios(struct pool *pool) struct bio_list bios; struct thin_c *tc; - rcu_read_lock(); - list_for_each_entry_rcu(tc, &pool->active_thins, list) + tc = get_first_thin(pool); + while (tc) { process_thin_deferred_bios(tc); - rcu_read_unlock(); + tc = get_next_thin(pool, tc); + } /* * If there are any deferred flush bios, we must commit @@ -1578,7 +1625,7 @@ static void noflush_work(struct thin_c *tc, void (*fn)(struct work_struct *)) { struct noflush_work w; - INIT_WORK(&w.worker, fn); + INIT_WORK_ONSTACK(&w.worker, fn); w.tc = tc; atomic_set(&w.complete, 0); init_waitqueue_head(&w.wait); @@ -3061,11 +3108,25 @@ static struct target_type pool_target = { /*---------------------------------------------------------------- * Thin target methods *--------------------------------------------------------------*/ +static void thin_get(struct thin_c *tc) +{ + atomic_inc(&tc->refcount); +} + +static void thin_put(struct thin_c *tc) +{ + if (atomic_dec_and_test(&tc->refcount)) + complete(&tc->can_destroy); +} + static void thin_dtr(struct dm_target *ti) { struct thin_c *tc = ti->private; unsigned long flags; + thin_put(tc); + wait_for_completion(&tc->can_destroy); + spin_lock_irqsave(&tc->pool->lock, flags); list_del_rcu(&tc->list); spin_unlock_irqrestore(&tc->pool->lock, flags); @@ -3101,6 +3162,7 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv) struct thin_c *tc; struct dm_dev *pool_dev, *origin_dev; struct mapped_device *pool_md; + unsigned long flags; mutex_lock(&dm_thin_pool_table.mutex); @@ -3191,9 +3253,12 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv) mutex_unlock(&dm_thin_pool_table.mutex); - spin_lock(&tc->pool->lock); + atomic_set(&tc->refcount, 1); + init_completion(&tc->can_destroy); + + spin_lock_irqsave(&tc->pool->lock, flags); list_add_tail_rcu(&tc->list, &tc->pool->active_thins); - spin_unlock(&tc->pool->lock); + spin_unlock_irqrestore(&tc->pool->lock, flags); /* * This synchronize_rcu() call is needed here otherwise we risk a * wake_worker() call finding no bios to process (because the newly diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c index 796007a5e0e1..7a7bab8947ae 100644 --- a/drivers/md/dm-verity.c +++ b/drivers/md/dm-verity.c @@ -330,15 +330,17 @@ test_block_hash: return r; } } - todo = 1 << v->data_dev_block_bits; - while (io->iter.bi_size) { + do { u8 *page; + unsigned len; struct bio_vec bv = bio_iter_iovec(bio, io->iter); page = kmap_atomic(bv.bv_page); - r = crypto_shash_update(desc, page + bv.bv_offset, - bv.bv_len); + len = bv.bv_len; + if (likely(len >= todo)) + len = todo; + r = crypto_shash_update(desc, page + bv.bv_offset, len); kunmap_atomic(page); if (r < 0) { @@ -346,8 +348,9 @@ test_block_hash: return r; } - bio_advance_iter(bio, &io->iter, bv.bv_len); - } + bio_advance_iter(bio, &io->iter, len); + todo -= len; + } while (todo); if (!v->version) { r = crypto_shash_update(desc, v->salt, v->salt_size); diff --git a/drivers/md/md.c b/drivers/md/md.c index 8fda38d23e38..237b7e0ddc7a 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -8516,7 +8516,8 @@ static int md_notify_reboot(struct notifier_block *this, if (mddev_trylock(mddev)) { if (mddev->pers) __md_stop_writes(mddev); - mddev->safemode = 2; + if (mddev->persistent) + mddev->safemode = 2; mddev_unlock(mddev); } need_delay = 1; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 33fc408e5eac..cb882aae9e20 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1172,6 +1172,13 @@ static void __make_request(struct mddev *mddev, struct bio *bio) int max_sectors; int sectors; + /* + * Register the new request and wait if the reconstruction + * thread has put up a bar for new requests. + * Continue immediately if no resync is active currently. + */ + wait_barrier(conf); + sectors = bio_sectors(bio); while (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && bio->bi_iter.bi_sector < conf->reshape_progress && @@ -1552,12 +1559,6 @@ static void make_request(struct mddev *mddev, struct bio *bio) md_write_start(mddev, bio); - /* - * Register the new request and wait if the reconstruction - * thread has put up a bar for new requests. - * Continue immediately if no resync is active currently. - */ - wait_barrier(conf); do { diff --git a/drivers/memory/mvebu-devbus.c b/drivers/memory/mvebu-devbus.c index 110c03627051..b59a17fb7c3e 100644 --- a/drivers/memory/mvebu-devbus.c +++ b/drivers/memory/mvebu-devbus.c @@ -108,8 +108,19 @@ static int devbus_set_timing_params(struct devbus *devbus, node->full_name); return err; } - /* Convert bit width to byte width */ - r.bus_width /= 8; + + /* + * The bus width is encoded into the register as 0 for 8 bits, + * and 1 for 16 bits, so we do the necessary conversion here. + */ + if (r.bus_width == 8) + r.bus_width = 0; + else if (r.bus_width == 16) + r.bus_width = 1; + else { + dev_err(devbus->dev, "invalid bus width %d\n", r.bus_width); + return -EINVAL; + } err = get_timing_param_ps(devbus, node, "devbus,badr-skew-ps", &r.badr_skew); diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index c9de3d598ea5..1d15735f9ef9 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c @@ -338,28 +338,58 @@ int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist, int num_sg, bool read, int timeout) { struct completion trans_done; - int err = 0, count; + u8 dir; + int err = 0, i, count; long timeleft; unsigned long flags; + struct scatterlist *sg; + enum dma_data_direction dma_dir; + u32 val; + dma_addr_t addr; + unsigned int len; + + dev_dbg(&(pcr->pci->dev), "--> %s: num_sg = %d\n", __func__, num_sg); + + /* don't transfer data during abort processing */ + if (pcr->remove_pci) + return -EINVAL; + + if ((sglist == NULL) || (num_sg <= 0)) + return -EINVAL; - count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, read); + if (read) { + dir = DEVICE_TO_HOST; + dma_dir = DMA_FROM_DEVICE; + } else { + dir = HOST_TO_DEVICE; + dma_dir = DMA_TO_DEVICE; + } + + count = dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir); if (count < 1) { dev_err(&(pcr->pci->dev), "scatterlist map failed\n"); return -EINVAL; } dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count); + val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE; + pcr->sgi = 0; + for_each_sg(sglist, sg, count, i) { + addr = sg_dma_address(sg); + len = sg_dma_len(sg); + rtsx_pci_add_sg_tbl(pcr, addr, len, i == count - 1); + } spin_lock_irqsave(&pcr->lock, flags); pcr->done = &trans_done; pcr->trans_result = TRANS_NOT_READY; init_completion(&trans_done); + rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr); + rtsx_pci_writel(pcr, RTSX_HDBCTLR, val); spin_unlock_irqrestore(&pcr->lock, flags); - rtsx_pci_dma_transfer(pcr, sglist, count, read); - timeleft = wait_for_completion_interruptible_timeout( &trans_done, msecs_to_jiffies(timeout)); if (timeleft <= 0) { @@ -383,7 +413,7 @@ out: pcr->done = NULL; spin_unlock_irqrestore(&pcr->lock, flags); - rtsx_pci_dma_unmap_sg(pcr, sglist, num_sg, read); + dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir); if ((err < 0) && (err != -ENODEV)) rtsx_pci_stop_cmd(pcr); @@ -395,73 +425,6 @@ out: } EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data); -int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist, - int num_sg, bool read) -{ - enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; - - if (pcr->remove_pci) - return -EINVAL; - - if ((sglist == NULL) || num_sg < 1) - return -EINVAL; - - return dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dir); -} -EXPORT_SYMBOL_GPL(rtsx_pci_dma_map_sg); - -int rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist, - int num_sg, bool read) -{ - enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; - - if (pcr->remove_pci) - return -EINVAL; - - if (sglist == NULL || num_sg < 1) - return -EINVAL; - - dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dir); - return num_sg; -} -EXPORT_SYMBOL_GPL(rtsx_pci_dma_unmap_sg); - -int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist, - int sg_count, bool read) -{ - struct scatterlist *sg; - dma_addr_t addr; - unsigned int len; - int i; - u32 val; - u8 dir = read ? DEVICE_TO_HOST : HOST_TO_DEVICE; - unsigned long flags; - - if (pcr->remove_pci) - return -EINVAL; - - if ((sglist == NULL) || (sg_count < 1)) - return -EINVAL; - - val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE; - pcr->sgi = 0; - for_each_sg(sglist, sg, sg_count, i) { - addr = sg_dma_address(sg); - len = sg_dma_len(sg); - rtsx_pci_add_sg_tbl(pcr, addr, len, i == sg_count - 1); - } - - spin_lock_irqsave(&pcr->lock, flags); - - rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr); - rtsx_pci_writel(pcr, RTSX_HDBCTLR, val); - - spin_unlock_irqrestore(&pcr->lock, flags); - - return 0; -} -EXPORT_SYMBOL_GPL(rtsx_pci_dma_transfer); - int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len) { int err; @@ -873,8 +836,6 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id) int_reg = rtsx_pci_readl(pcr, RTSX_BIPR); /* Clear interrupt flag */ rtsx_pci_writel(pcr, RTSX_BIPR, int_reg); - dev_dbg(&pcr->pci->dev, "=========== BIPR 0x%8x ==========\n", int_reg); - if ((int_reg & pcr->bier) == 0) { spin_unlock(&pcr->lock); return IRQ_NONE; @@ -905,28 +866,17 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id) } if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) { - if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) + if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) { pcr->trans_result = TRANS_RESULT_FAIL; - else if (int_reg & TRANS_OK_INT) + if (pcr->done) + complete(pcr->done); + } else if (int_reg & TRANS_OK_INT) { pcr->trans_result = TRANS_RESULT_OK; - - if (pcr->done) - complete(pcr->done); - - if (int_reg & SD_EXIST) { - struct rtsx_slot *slot = &pcr->slots[RTSX_SD_CARD]; - if (slot && slot->done_transfer) - slot->done_transfer(slot->p_dev); - } - - if (int_reg & MS_EXIST) { - struct rtsx_slot *slot = &pcr->slots[RTSX_SD_CARD]; - if (slot && slot->done_transfer) - slot->done_transfer(slot->p_dev); + if (pcr->done) + complete(pcr->done); } } - if (pcr->card_inserted || pcr->card_removed) schedule_delayed_work(&pcr->carddet_work, msecs_to_jiffies(200)); diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index 5fb994f9a653..0b9ded13a3ae 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c @@ -31,28 +31,14 @@ #include <linux/mfd/rtsx_pci.h> #include <asm/unaligned.h> -struct realtek_next { - unsigned int sg_count; - s32 cookie; -}; - struct realtek_pci_sdmmc { struct platform_device *pdev; struct rtsx_pcr *pcr; struct mmc_host *mmc; struct mmc_request *mrq; - struct mmc_command *cmd; - struct mmc_data *data; - - spinlock_t lock; - struct timer_list timer; - struct tasklet_struct cmd_tasklet; - struct tasklet_struct data_tasklet; - struct tasklet_struct finish_tasklet; - - u8 rsp_type; - u8 rsp_len; - int sg_count; + + struct mutex host_mutex; + u8 ssc_depth; unsigned int clock; bool vpclk; @@ -62,13 +48,8 @@ struct realtek_pci_sdmmc { int power_state; #define SDMMC_POWER_ON 1 #define SDMMC_POWER_OFF 0 - - struct realtek_next next_data; }; -static int sd_start_multi_rw(struct realtek_pci_sdmmc *host, - struct mmc_request *mrq); - static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host) { return &(host->pdev->dev); @@ -105,95 +86,6 @@ static void sd_print_debug_regs(struct realtek_pci_sdmmc *host) #define sd_print_debug_regs(host) #endif /* DEBUG */ -static void sd_isr_done_transfer(struct platform_device *pdev) -{ - struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); - - spin_lock(&host->lock); - if (host->cmd) - tasklet_schedule(&host->cmd_tasklet); - if (host->data) - tasklet_schedule(&host->data_tasklet); - spin_unlock(&host->lock); -} - -static void sd_request_timeout(unsigned long host_addr) -{ - struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr; - unsigned long flags; - - spin_lock_irqsave(&host->lock, flags); - - if (!host->mrq) { - dev_err(sdmmc_dev(host), "error: no request exist\n"); - goto out; - } - - if (host->cmd) - host->cmd->error = -ETIMEDOUT; - if (host->data) - host->data->error = -ETIMEDOUT; - - dev_dbg(sdmmc_dev(host), "timeout for request\n"); - -out: - tasklet_schedule(&host->finish_tasklet); - spin_unlock_irqrestore(&host->lock, flags); -} - -static void sd_finish_request(unsigned long host_addr) -{ - struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr; - struct rtsx_pcr *pcr = host->pcr; - struct mmc_request *mrq; - struct mmc_command *cmd; - struct mmc_data *data; - unsigned long flags; - bool any_error; - - spin_lock_irqsave(&host->lock, flags); - - del_timer(&host->timer); - mrq = host->mrq; - if (!mrq) { - dev_err(sdmmc_dev(host), "error: no request need finish\n"); - goto out; - } - - cmd = mrq->cmd; - data = mrq->data; - - any_error = (mrq->sbc && mrq->sbc->error) || - (mrq->stop && mrq->stop->error) || - (cmd && cmd->error) || (data && data->error); - - if (any_error) { - rtsx_pci_stop_cmd(pcr); - sd_clear_error(host); - } - - if (data) { - if (any_error) - data->bytes_xfered = 0; - else - data->bytes_xfered = data->blocks * data->blksz; - - if (!data->host_cookie) - rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len, - data->flags & MMC_DATA_READ); - - } - - host->mrq = NULL; - host->cmd = NULL; - host->data = NULL; - -out: - spin_unlock_irqrestore(&host->lock, flags); - mutex_unlock(&pcr->pcr_mutex); - mmc_request_done(host->mmc, mrq); -} - static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt, u8 *buf, int buf_len, int timeout) { @@ -311,7 +203,8 @@ static int sd_write_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt, return 0; } -static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd) +static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, + struct mmc_command *cmd) { struct rtsx_pcr *pcr = host->pcr; u8 cmd_idx = (u8)cmd->opcode; @@ -319,14 +212,11 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd) int err = 0; int timeout = 100; int i; + u8 *ptr; + int stat_idx = 0; u8 rsp_type; int rsp_len = 5; - unsigned long flags; - - if (host->cmd) - dev_err(sdmmc_dev(host), "error: cmd already exist\n"); - - host->cmd = cmd; + bool clock_toggled = false; dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", __func__, cmd_idx, arg); @@ -361,8 +251,6 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd) err = -EINVAL; goto out; } - host->rsp_type = rsp_type; - host->rsp_len = rsp_len; if (rsp_type == SD_RSP_TYPE_R1b) timeout = 3000; @@ -372,6 +260,8 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd) 0xFF, SD_CLK_TOGGLE_EN); if (err < 0) goto out; + + clock_toggled = true; } rtsx_pci_init_cmd(pcr); @@ -395,60 +285,25 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd) /* Read data from ping-pong buffer */ for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++) rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); + stat_idx = 16; } else if (rsp_type != SD_RSP_TYPE_R0) { /* Read data from SD_CMDx registers */ for (i = SD_CMD0; i <= SD_CMD4; i++) rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); + stat_idx = 5; } rtsx_pci_add_cmd(pcr, READ_REG_CMD, SD_STAT1, 0, 0); - mod_timer(&host->timer, jiffies + msecs_to_jiffies(timeout)); - - spin_lock_irqsave(&pcr->lock, flags); - pcr->trans_result = TRANS_NOT_READY; - rtsx_pci_send_cmd_no_wait(pcr); - spin_unlock_irqrestore(&pcr->lock, flags); - - return; - -out: - cmd->error = err; - tasklet_schedule(&host->finish_tasklet); -} - -static void sd_get_rsp(unsigned long host_addr) -{ - struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr; - struct rtsx_pcr *pcr = host->pcr; - struct mmc_command *cmd; - int i, err = 0, stat_idx; - u8 *ptr, rsp_type; - unsigned long flags; - - spin_lock_irqsave(&host->lock, flags); - - cmd = host->cmd; - host->cmd = NULL; - - if (!cmd) { - dev_err(sdmmc_dev(host), "error: cmd not exist\n"); + err = rtsx_pci_send_cmd(pcr, timeout); + if (err < 0) { + sd_print_debug_regs(host); + sd_clear_error(host); + dev_dbg(sdmmc_dev(host), + "rtsx_pci_send_cmd error (err = %d)\n", err); goto out; } - spin_lock(&pcr->lock); - if (pcr->trans_result == TRANS_NO_DEVICE) - err = -ENODEV; - else if (pcr->trans_result != TRANS_RESULT_OK) - err = -EINVAL; - spin_unlock(&pcr->lock); - - if (err < 0) - goto out; - - rsp_type = host->rsp_type; - stat_idx = host->rsp_len; - if (rsp_type == SD_RSP_TYPE_R0) { err = 0; goto out; @@ -485,106 +340,26 @@ static void sd_get_rsp(unsigned long host_addr) cmd->resp[0]); } - if (cmd == host->mrq->sbc) { - sd_send_cmd(host, host->mrq->cmd); - spin_unlock_irqrestore(&host->lock, flags); - return; - } - - if (cmd == host->mrq->stop) - goto out; - - if (cmd->data) { - sd_start_multi_rw(host, host->mrq); - spin_unlock_irqrestore(&host->lock, flags); - return; - } - out: cmd->error = err; - tasklet_schedule(&host->finish_tasklet); - spin_unlock_irqrestore(&host->lock, flags); -} - -static int sd_pre_dma_transfer(struct realtek_pci_sdmmc *host, - struct mmc_data *data, struct realtek_next *next) -{ - struct rtsx_pcr *pcr = host->pcr; - int read = data->flags & MMC_DATA_READ; - int sg_count = 0; - - if (!next && data->host_cookie && - data->host_cookie != host->next_data.cookie) { - dev_err(sdmmc_dev(host), - "error: invalid cookie data[%d] host[%d]\n", - data->host_cookie, host->next_data.cookie); - data->host_cookie = 0; - } - - if (next || (!next && data->host_cookie != host->next_data.cookie)) - sg_count = rtsx_pci_dma_map_sg(pcr, - data->sg, data->sg_len, read); - else - sg_count = host->next_data.sg_count; - - if (next) { - next->sg_count = sg_count; - if (++next->cookie < 0) - next->cookie = 1; - data->host_cookie = next->cookie; - } - - return sg_count; -} - -static void sdmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq, - bool is_first_req) -{ - struct realtek_pci_sdmmc *host = mmc_priv(mmc); - struct mmc_data *data = mrq->data; - - if (data->host_cookie) { - dev_err(sdmmc_dev(host), - "error: descard already cookie data[%d]\n", - data->host_cookie); - data->host_cookie = 0; - } - - dev_dbg(sdmmc_dev(host), "dma sg prepared: %d\n", - sd_pre_dma_transfer(host, data, &host->next_data)); -} - -static void sdmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, - int err) -{ - struct realtek_pci_sdmmc *host = mmc_priv(mmc); - struct rtsx_pcr *pcr = host->pcr; - struct mmc_data *data = mrq->data; - int read = data->flags & MMC_DATA_READ; - - rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len, read); - data->host_cookie = 0; + if (err && clock_toggled) + rtsx_pci_write_register(pcr, SD_BUS_STAT, + SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); } -static int sd_start_multi_rw(struct realtek_pci_sdmmc *host, - struct mmc_request *mrq) +static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq) { struct rtsx_pcr *pcr = host->pcr; struct mmc_host *mmc = host->mmc; struct mmc_card *card = mmc->card; struct mmc_data *data = mrq->data; int uhs = mmc_card_uhs(card); - int read = data->flags & MMC_DATA_READ; + int read = (data->flags & MMC_DATA_READ) ? 1 : 0; u8 cfg2, trans_mode; int err; size_t data_len = data->blksz * data->blocks; - if (host->data) - dev_err(sdmmc_dev(host), "error: data already exist\n"); - - host->data = data; - if (read) { cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0; @@ -635,54 +410,15 @@ static int sd_start_multi_rw(struct realtek_pci_sdmmc *host, rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END); - mod_timer(&host->timer, jiffies + 10 * HZ); rtsx_pci_send_cmd_no_wait(pcr); - err = rtsx_pci_dma_transfer(pcr, data->sg, host->sg_count, read); - if (err < 0) { - data->error = err; - tasklet_schedule(&host->finish_tasklet); - } - return 0; -} - -static void sd_finish_multi_rw(unsigned long host_addr) -{ - struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr; - struct rtsx_pcr *pcr = host->pcr; - struct mmc_data *data; - int err = 0; - unsigned long flags; - - spin_lock_irqsave(&host->lock, flags); - - if (!host->data) { - dev_err(sdmmc_dev(host), "error: no data exist\n"); - goto out; - } - - data = host->data; - host->data = NULL; - - if (pcr->trans_result == TRANS_NO_DEVICE) - err = -ENODEV; - else if (pcr->trans_result != TRANS_RESULT_OK) - err = -EINVAL; - + err = rtsx_pci_transfer_data(pcr, data->sg, data->sg_len, read, 10000); if (err < 0) { - data->error = err; - goto out; - } - - if (!host->mrq->sbc && data->stop) { - sd_send_cmd(host, data->stop); - spin_unlock_irqrestore(&host->lock, flags); - return; + sd_clear_error(host); + return err; } -out: - tasklet_schedule(&host->finish_tasklet); - spin_unlock_irqrestore(&host->lock, flags); + return 0; } static inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host) @@ -901,13 +637,6 @@ static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode) return 0; } -static inline bool sd_use_muti_rw(struct mmc_command *cmd) -{ - return mmc_op_multi(cmd->opcode) || - (cmd->opcode == MMC_READ_SINGLE_BLOCK) || - (cmd->opcode == MMC_WRITE_BLOCK); -} - static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) { struct realtek_pci_sdmmc *host = mmc_priv(mmc); @@ -916,14 +645,6 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) struct mmc_data *data = mrq->data; unsigned int data_size = 0; int err; - unsigned long flags; - - mutex_lock(&pcr->pcr_mutex); - spin_lock_irqsave(&host->lock, flags); - - if (host->mrq) - dev_err(sdmmc_dev(host), "error: request already exist\n"); - host->mrq = mrq; if (host->eject) { cmd->error = -ENOMEDIUM; @@ -936,6 +657,8 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) goto finish; } + mutex_lock(&pcr->pcr_mutex); + rtsx_pci_start_run(pcr); rtsx_pci_switch_clock(pcr, host->clock, host->ssc_depth, @@ -944,28 +667,46 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) rtsx_pci_write_register(pcr, CARD_SHARE_MODE, CARD_SHARE_MASK, CARD_SHARE_48_SD); + mutex_lock(&host->host_mutex); + host->mrq = mrq; + mutex_unlock(&host->host_mutex); + if (mrq->data) data_size = data->blocks * data->blksz; - if (sd_use_muti_rw(cmd)) - host->sg_count = sd_pre_dma_transfer(host, data, NULL); + if (!data_size || mmc_op_multi(cmd->opcode) || + (cmd->opcode == MMC_READ_SINGLE_BLOCK) || + (cmd->opcode == MMC_WRITE_BLOCK)) { + sd_send_cmd_get_rsp(host, cmd); - if (!data_size || sd_use_muti_rw(cmd)) { - if (mrq->sbc) - sd_send_cmd(host, mrq->sbc); - else - sd_send_cmd(host, cmd); - spin_unlock_irqrestore(&host->lock, flags); + if (!cmd->error && data_size) { + sd_rw_multi(host, mrq); + + if (mmc_op_multi(cmd->opcode) && mrq->stop) + sd_send_cmd_get_rsp(host, mrq->stop); + } } else { - spin_unlock_irqrestore(&host->lock, flags); sd_normal_rw(host, mrq); - tasklet_schedule(&host->finish_tasklet); } - return; + + if (mrq->data) { + if (cmd->error || data->error) + data->bytes_xfered = 0; + else + data->bytes_xfered = data->blocks * data->blksz; + } + + mutex_unlock(&pcr->pcr_mutex); finish: - tasklet_schedule(&host->finish_tasklet); - spin_unlock_irqrestore(&host->lock, flags); + if (cmd->error) + dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error); + + mutex_lock(&host->host_mutex); + host->mrq = NULL; + mutex_unlock(&host->host_mutex); + + mmc_request_done(mmc, mrq); } static int sd_set_bus_width(struct realtek_pci_sdmmc *host, @@ -1400,8 +1141,6 @@ out: } static const struct mmc_host_ops realtek_pci_sdmmc_ops = { - .pre_req = sdmmc_pre_req, - .post_req = sdmmc_post_req, .request = sdmmc_request, .set_ios = sdmmc_set_ios, .get_ro = sdmmc_get_ro, @@ -1465,7 +1204,6 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev) struct realtek_pci_sdmmc *host; struct rtsx_pcr *pcr; struct pcr_handle *handle = pdev->dev.platform_data; - unsigned long host_addr; if (!handle) return -ENXIO; @@ -1489,15 +1227,8 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev) pcr->slots[RTSX_SD_CARD].p_dev = pdev; pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event; - host_addr = (unsigned long)host; - host->next_data.cookie = 1; - setup_timer(&host->timer, sd_request_timeout, host_addr); - tasklet_init(&host->cmd_tasklet, sd_get_rsp, host_addr); - tasklet_init(&host->data_tasklet, sd_finish_multi_rw, host_addr); - tasklet_init(&host->finish_tasklet, sd_finish_request, host_addr); - spin_lock_init(&host->lock); + mutex_init(&host->host_mutex); - pcr->slots[RTSX_SD_CARD].done_transfer = sd_isr_done_transfer; realtek_init_host(host); mmc_add_host(mmc); @@ -1510,8 +1241,6 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev) struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); struct rtsx_pcr *pcr; struct mmc_host *mmc; - struct mmc_request *mrq; - unsigned long flags; if (!host) return 0; @@ -1519,33 +1248,22 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev) pcr = host->pcr; pcr->slots[RTSX_SD_CARD].p_dev = NULL; pcr->slots[RTSX_SD_CARD].card_event = NULL; - pcr->slots[RTSX_SD_CARD].done_transfer = NULL; mmc = host->mmc; - mrq = host->mrq; - spin_lock_irqsave(&host->lock, flags); + mutex_lock(&host->host_mutex); if (host->mrq) { dev_dbg(&(pdev->dev), "%s: Controller removed during transfer\n", mmc_hostname(mmc)); - if (mrq->sbc) - mrq->sbc->error = -ENOMEDIUM; - if (mrq->cmd) - mrq->cmd->error = -ENOMEDIUM; - if (mrq->stop) - mrq->stop->error = -ENOMEDIUM; - if (mrq->data) - mrq->data->error = -ENOMEDIUM; + rtsx_pci_complete_unfinished_transfer(pcr); - tasklet_schedule(&host->finish_tasklet); + host->mrq->cmd->error = -ENOMEDIUM; + if (host->mrq->stop) + host->mrq->stop->error = -ENOMEDIUM; + mmc_request_done(mmc, host->mrq); } - spin_unlock_irqrestore(&host->lock, flags); - - del_timer_sync(&host->timer); - tasklet_kill(&host->cmd_tasklet); - tasklet_kill(&host->data_tasklet); - tasklet_kill(&host->finish_tasklet); + mutex_unlock(&host->host_mutex); mmc_remove_host(mmc); host->eject = true; diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 4615d79fc93f..b922c8efcf40 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -523,6 +523,7 @@ static struct nand_ecclayout hwecc4_2048 = { #if defined(CONFIG_OF) static const struct of_device_id davinci_nand_of_match[] = { {.compatible = "ti,davinci-nand", }, + {.compatible = "ti,keystone-nand", }, {}, }; MODULE_DEVICE_TABLE(of, davinci_nand_of_match); @@ -581,6 +582,11 @@ static struct davinci_nand_pdata of_property_read_bool(pdev->dev.of_node, "ti,davinci-nand-use-bbt")) pdata->bbt_options = NAND_BBT_USE_FLASH; + + if (of_device_is_compatible(pdev->dev.of_node, + "ti,keystone-nand")) { + pdata->options |= NAND_NO_SUBPAGE_WRITE; + } } return dev_get_platdata(&pdev->dev); diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c index 7ff473c871a9..8d659e6a1b4c 100644 --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c @@ -431,7 +431,7 @@ int ubiblock_create(struct ubi_volume_info *vi) * Create one workqueue per volume (per registered block device). * Rembember workqueues are cheap, they're not threads. */ - dev->wq = alloc_workqueue(gd->disk_name, 0, 0); + dev->wq = alloc_workqueue("%s", 0, 0, gd->disk_name); if (!dev->wq) goto out_free_queue; INIT_WORK(&dev->work, ubiblock_do_work); diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 02317c1c0238..0f3425dac910 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -671,6 +671,8 @@ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi) e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF); self_check_in_wl_tree(ubi, e, &ubi->free); + ubi->free_count--; + ubi_assert(ubi->free_count >= 0); rb_erase(&e->u.rb, &ubi->free); return e; @@ -684,6 +686,9 @@ int ubi_wl_get_peb(struct ubi_device *ubi) peb = __wl_get_peb(ubi); spin_unlock(&ubi->wl_lock); + if (peb < 0) + return peb; + err = ubi_self_check_all_ff(ubi, peb, ubi->vid_hdr_aloffset, ubi->peb_size - ubi->vid_hdr_aloffset); if (err) { @@ -1068,6 +1073,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, /* Give the unused PEB back */ wl_tree_add(e2, &ubi->free); + ubi->free_count++; goto out_cancel; } self_check_in_wl_tree(ubi, e1, &ubi->used); diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 0e8b268da0a0..5f6babcfc26e 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -534,7 +534,7 @@ static ssize_t bonding_show_min_links(struct device *d, { struct bonding *bond = to_bond(d); - return sprintf(buf, "%d\n", bond->params.min_links); + return sprintf(buf, "%u\n", bond->params.min_links); } static ssize_t bonding_store_min_links(struct device *d, diff --git a/drivers/net/can/c_can/Kconfig b/drivers/net/can/c_can/Kconfig index 61ffc12d8fd8..8ab7103d4f44 100644 --- a/drivers/net/can/c_can/Kconfig +++ b/drivers/net/can/c_can/Kconfig @@ -14,6 +14,13 @@ config CAN_C_CAN_PLATFORM SPEAr1310 and SPEAr320 evaluation boards & TI (www.ti.com) boards like am335x, dm814x, dm813x and dm811x. +config CAN_C_CAN_STRICT_FRAME_ORDERING + bool "Force a strict RX CAN frame order (may cause frame loss)" + ---help--- + The RX split buffer prevents packet reordering but can cause packet + loss. Only enable this option when you accept to lose CAN frames + in favour of getting the received CAN frames in the correct order. + config CAN_C_CAN_PCI tristate "Generic PCI Bus based C_CAN/D_CAN driver" depends on PCI diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index a5c8dcfa8357..a2ca820b5373 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -60,6 +60,8 @@ #define CONTROL_IE BIT(1) #define CONTROL_INIT BIT(0) +#define CONTROL_IRQMSK (CONTROL_EIE | CONTROL_IE | CONTROL_SIE) + /* test register */ #define TEST_RX BIT(7) #define TEST_TX1 BIT(6) @@ -108,11 +110,14 @@ #define IF_COMM_CONTROL BIT(4) #define IF_COMM_CLR_INT_PND BIT(3) #define IF_COMM_TXRQST BIT(2) +#define IF_COMM_CLR_NEWDAT IF_COMM_TXRQST #define IF_COMM_DATAA BIT(1) #define IF_COMM_DATAB BIT(0) -#define IF_COMM_ALL (IF_COMM_MASK | IF_COMM_ARB | \ - IF_COMM_CONTROL | IF_COMM_TXRQST | \ - IF_COMM_DATAA | IF_COMM_DATAB) + +/* TX buffer setup */ +#define IF_COMM_TX (IF_COMM_ARB | IF_COMM_CONTROL | \ + IF_COMM_TXRQST | \ + IF_COMM_DATAA | IF_COMM_DATAB) /* For the low buffers we clear the interrupt bit, but keep newdat */ #define IF_COMM_RCV_LOW (IF_COMM_MASK | IF_COMM_ARB | \ @@ -120,12 +125,19 @@ IF_COMM_DATAA | IF_COMM_DATAB) /* For the high buffers we clear the interrupt bit and newdat */ -#define IF_COMM_RCV_HIGH (IF_COMM_RCV_LOW | IF_COMM_TXRQST) +#define IF_COMM_RCV_HIGH (IF_COMM_RCV_LOW | IF_COMM_CLR_NEWDAT) + + +/* Receive setup of message objects */ +#define IF_COMM_RCV_SETUP (IF_COMM_MASK | IF_COMM_ARB | IF_COMM_CONTROL) + +/* Invalidation of message objects */ +#define IF_COMM_INVAL (IF_COMM_ARB | IF_COMM_CONTROL) /* IFx arbitration */ -#define IF_ARB_MSGVAL BIT(15) -#define IF_ARB_MSGXTD BIT(14) -#define IF_ARB_TRANSMIT BIT(13) +#define IF_ARB_MSGVAL BIT(31) +#define IF_ARB_MSGXTD BIT(30) +#define IF_ARB_TRANSMIT BIT(29) /* IFx message control */ #define IF_MCONT_NEWDAT BIT(15) @@ -139,19 +151,17 @@ #define IF_MCONT_EOB BIT(7) #define IF_MCONT_DLC_MASK 0xf +#define IF_MCONT_RCV (IF_MCONT_RXIE | IF_MCONT_UMASK) +#define IF_MCONT_RCV_EOB (IF_MCONT_RCV | IF_MCONT_EOB) + +#define IF_MCONT_TX (IF_MCONT_TXIE | IF_MCONT_EOB) + /* * Use IF1 for RX and IF2 for TX */ #define IF_RX 0 #define IF_TX 1 -/* status interrupt */ -#define STATUS_INTERRUPT 0x8000 - -/* global interrupt masks */ -#define ENABLE_ALL_INTERRUPTS 1 -#define DISABLE_ALL_INTERRUPTS 0 - /* minimum timeout for checking BUSY status */ #define MIN_TIMEOUT_VALUE 6 @@ -171,6 +181,7 @@ enum c_can_lec_type { LEC_BIT0_ERROR, LEC_CRC_ERROR, LEC_UNUSED, + LEC_MASK = LEC_UNUSED, }; /* @@ -226,143 +237,115 @@ static inline void c_can_reset_ram(const struct c_can_priv *priv, bool enable) priv->raminit(priv, enable); } -static inline int get_tx_next_msg_obj(const struct c_can_priv *priv) +static void c_can_irq_control(struct c_can_priv *priv, bool enable) { - return (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) + - C_CAN_MSG_OBJ_TX_FIRST; -} - -static inline int get_tx_echo_msg_obj(int txecho) -{ - return (txecho & C_CAN_NEXT_MSG_OBJ_MASK) + C_CAN_MSG_OBJ_TX_FIRST; -} - -static u32 c_can_read_reg32(struct c_can_priv *priv, enum reg index) -{ - u32 val = priv->read_reg(priv, index); - val |= ((u32) priv->read_reg(priv, index + 1)) << 16; - return val; -} - -static void c_can_enable_all_interrupts(struct c_can_priv *priv, - int enable) -{ - unsigned int cntrl_save = priv->read_reg(priv, - C_CAN_CTRL_REG); + u32 ctrl = priv->read_reg(priv, C_CAN_CTRL_REG) & ~CONTROL_IRQMSK; if (enable) - cntrl_save |= (CONTROL_SIE | CONTROL_EIE | CONTROL_IE); - else - cntrl_save &= ~(CONTROL_EIE | CONTROL_IE | CONTROL_SIE); + ctrl |= CONTROL_IRQMSK; - priv->write_reg(priv, C_CAN_CTRL_REG, cntrl_save); + priv->write_reg(priv, C_CAN_CTRL_REG, ctrl); } -static inline int c_can_msg_obj_is_busy(struct c_can_priv *priv, int iface) +static void c_can_obj_update(struct net_device *dev, int iface, u32 cmd, u32 obj) { - int count = MIN_TIMEOUT_VALUE; + struct c_can_priv *priv = netdev_priv(dev); + int cnt, reg = C_CAN_IFACE(COMREQ_REG, iface); + + priv->write_reg(priv, reg + 1, cmd); + priv->write_reg(priv, reg, obj); - while (count && priv->read_reg(priv, - C_CAN_IFACE(COMREQ_REG, iface)) & - IF_COMR_BUSY) { - count--; + for (cnt = MIN_TIMEOUT_VALUE; cnt; cnt--) { + if (!(priv->read_reg(priv, reg) & IF_COMR_BUSY)) + return; udelay(1); } + netdev_err(dev, "Updating object timed out\n"); - if (!count) - return 1; +} - return 0; +static inline void c_can_object_get(struct net_device *dev, int iface, + u32 obj, u32 cmd) +{ + c_can_obj_update(dev, iface, cmd, obj); } -static inline void c_can_object_get(struct net_device *dev, - int iface, int objno, int mask) +static inline void c_can_object_put(struct net_device *dev, int iface, + u32 obj, u32 cmd) { - struct c_can_priv *priv = netdev_priv(dev); + c_can_obj_update(dev, iface, cmd | IF_COMM_WR, obj); +} - /* - * As per specs, after writting the message object number in the - * IF command request register the transfer b/w interface - * register and message RAM must be complete in 6 CAN-CLK - * period. - */ - priv->write_reg(priv, C_CAN_IFACE(COMMSK_REG, iface), - IFX_WRITE_LOW_16BIT(mask)); - priv->write_reg(priv, C_CAN_IFACE(COMREQ_REG, iface), - IFX_WRITE_LOW_16BIT(objno)); +/* + * Note: According to documentation clearing TXIE while MSGVAL is set + * is not allowed, but works nicely on C/DCAN. And that lowers the I/O + * load significantly. + */ +static void c_can_inval_tx_object(struct net_device *dev, int iface, int obj) +{ + struct c_can_priv *priv = netdev_priv(dev); - if (c_can_msg_obj_is_busy(priv, iface)) - netdev_err(dev, "timed out in object get\n"); + priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0); + c_can_object_put(dev, iface, obj, IF_COMM_INVAL); } -static inline void c_can_object_put(struct net_device *dev, - int iface, int objno, int mask) +static void c_can_inval_msg_object(struct net_device *dev, int iface, int obj) { struct c_can_priv *priv = netdev_priv(dev); - /* - * As per specs, after writting the message object number in the - * IF command request register the transfer b/w interface - * register and message RAM must be complete in 6 CAN-CLK - * period. - */ - priv->write_reg(priv, C_CAN_IFACE(COMMSK_REG, iface), - (IF_COMM_WR | IFX_WRITE_LOW_16BIT(mask))); - priv->write_reg(priv, C_CAN_IFACE(COMREQ_REG, iface), - IFX_WRITE_LOW_16BIT(objno)); - - if (c_can_msg_obj_is_busy(priv, iface)) - netdev_err(dev, "timed out in object put\n"); + priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), 0); + priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), 0); + c_can_inval_tx_object(dev, iface, obj); } -static void c_can_write_msg_object(struct net_device *dev, - int iface, struct can_frame *frame, int objno) +static void c_can_setup_tx_object(struct net_device *dev, int iface, + struct can_frame *frame, int idx) { - int i; - u16 flags = 0; - unsigned int id; struct c_can_priv *priv = netdev_priv(dev); - - if (!(frame->can_id & CAN_RTR_FLAG)) - flags |= IF_ARB_TRANSMIT; + u16 ctrl = IF_MCONT_TX | frame->can_dlc; + bool rtr = frame->can_id & CAN_RTR_FLAG; + u32 arb = IF_ARB_MSGVAL; + int i; if (frame->can_id & CAN_EFF_FLAG) { - id = frame->can_id & CAN_EFF_MASK; - flags |= IF_ARB_MSGXTD; - } else - id = ((frame->can_id & CAN_SFF_MASK) << 18); + arb |= frame->can_id & CAN_EFF_MASK; + arb |= IF_ARB_MSGXTD; + } else { + arb |= (frame->can_id & CAN_SFF_MASK) << 18; + } + + if (!rtr) + arb |= IF_ARB_TRANSMIT; - flags |= IF_ARB_MSGVAL; + /* + * If we change the DIR bit, we need to invalidate the buffer + * first, i.e. clear the MSGVAL flag in the arbiter. + */ + if (rtr != (bool)test_bit(idx, &priv->tx_dir)) { + u32 obj = idx + C_CAN_MSG_OBJ_TX_FIRST; + + c_can_inval_msg_object(dev, iface, obj); + change_bit(idx, &priv->tx_dir); + } + + priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), arb); + priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), arb >> 16); - priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), - IFX_WRITE_LOW_16BIT(id)); - priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), flags | - IFX_WRITE_HIGH_16BIT(id)); + priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl); for (i = 0; i < frame->can_dlc; i += 2) { priv->write_reg(priv, C_CAN_IFACE(DATA1_REG, iface) + i / 2, frame->data[i] | (frame->data[i + 1] << 8)); } - - /* enable interrupt for this message object */ - priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), - IF_MCONT_TXIE | IF_MCONT_TXRQST | IF_MCONT_EOB | - frame->can_dlc); - c_can_object_put(dev, iface, objno, IF_COMM_ALL); } static inline void c_can_activate_all_lower_rx_msg_obj(struct net_device *dev, - int iface, - int ctrl_mask) + int iface) { int i; - struct c_can_priv *priv = netdev_priv(dev); - for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_RX_LOW_LAST; i++) { - priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), - ctrl_mask & ~IF_MCONT_NEWDAT); - c_can_object_put(dev, iface, i, IF_COMM_CONTROL); - } + for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_RX_LOW_LAST; i++) + c_can_object_get(dev, iface, i, IF_COMM_CLR_NEWDAT); } static int c_can_handle_lost_msg_obj(struct net_device *dev, @@ -377,6 +360,9 @@ static int c_can_handle_lost_msg_obj(struct net_device *dev, priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl); c_can_object_put(dev, iface, objno, IF_COMM_CONTROL); + stats->rx_errors++; + stats->rx_over_errors++; + /* create an error msg */ skb = alloc_can_err_skb(dev, &frame); if (unlikely(!skb)) @@ -384,22 +370,18 @@ static int c_can_handle_lost_msg_obj(struct net_device *dev, frame->can_id |= CAN_ERR_CRTL; frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; - stats->rx_errors++; - stats->rx_over_errors++; netif_receive_skb(skb); return 1; } -static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl) +static int c_can_read_msg_object(struct net_device *dev, int iface, u32 ctrl) { - u16 flags, data; - int i; - unsigned int val; - struct c_can_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; - struct sk_buff *skb; + struct c_can_priv *priv = netdev_priv(dev); struct can_frame *frame; + struct sk_buff *skb; + u32 arb, data; skb = alloc_can_skb(dev, &frame); if (!skb) { @@ -409,115 +391,82 @@ static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl) frame->can_dlc = get_can_dlc(ctrl & 0x0F); - flags = priv->read_reg(priv, C_CAN_IFACE(ARB2_REG, iface)); - val = priv->read_reg(priv, C_CAN_IFACE(ARB1_REG, iface)) | - (flags << 16); + arb = priv->read_reg(priv, C_CAN_IFACE(ARB1_REG, iface)); + arb |= priv->read_reg(priv, C_CAN_IFACE(ARB2_REG, iface)) << 16; - if (flags & IF_ARB_MSGXTD) - frame->can_id = (val & CAN_EFF_MASK) | CAN_EFF_FLAG; + if (arb & IF_ARB_MSGXTD) + frame->can_id = (arb & CAN_EFF_MASK) | CAN_EFF_FLAG; else - frame->can_id = (val >> 18) & CAN_SFF_MASK; + frame->can_id = (arb >> 18) & CAN_SFF_MASK; - if (flags & IF_ARB_TRANSMIT) + if (arb & IF_ARB_TRANSMIT) { frame->can_id |= CAN_RTR_FLAG; - else { - for (i = 0; i < frame->can_dlc; i += 2) { - data = priv->read_reg(priv, - C_CAN_IFACE(DATA1_REG, iface) + i / 2); + } else { + int i, dreg = C_CAN_IFACE(DATA1_REG, iface); + + for (i = 0; i < frame->can_dlc; i += 2, dreg ++) { + data = priv->read_reg(priv, dreg); frame->data[i] = data; frame->data[i + 1] = data >> 8; } } - netif_receive_skb(skb); - stats->rx_packets++; stats->rx_bytes += frame->can_dlc; + + netif_receive_skb(skb); return 0; } static void c_can_setup_receive_object(struct net_device *dev, int iface, - int objno, unsigned int mask, - unsigned int id, unsigned int mcont) + u32 obj, u32 mask, u32 id, u32 mcont) { struct c_can_priv *priv = netdev_priv(dev); - priv->write_reg(priv, C_CAN_IFACE(MASK1_REG, iface), - IFX_WRITE_LOW_16BIT(mask)); - - /* According to C_CAN documentation, the reserved bit - * in IFx_MASK2 register is fixed 1 - */ - priv->write_reg(priv, C_CAN_IFACE(MASK2_REG, iface), - IFX_WRITE_HIGH_16BIT(mask) | BIT(13)); + mask |= BIT(29); + priv->write_reg(priv, C_CAN_IFACE(MASK1_REG, iface), mask); + priv->write_reg(priv, C_CAN_IFACE(MASK2_REG, iface), mask >> 16); - priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), - IFX_WRITE_LOW_16BIT(id)); - priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), - (IF_ARB_MSGVAL | IFX_WRITE_HIGH_16BIT(id))); + id |= IF_ARB_MSGVAL; + priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), id); + priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), id >> 16); priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), mcont); - c_can_object_put(dev, iface, objno, IF_COMM_ALL & ~IF_COMM_TXRQST); - - netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno, - c_can_read_reg32(priv, C_CAN_MSGVAL1_REG)); -} - -static void c_can_inval_msg_object(struct net_device *dev, int iface, int objno) -{ - struct c_can_priv *priv = netdev_priv(dev); - - priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), 0); - priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), 0); - priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0); - - c_can_object_put(dev, iface, objno, IF_COMM_ARB | IF_COMM_CONTROL); - - netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno, - c_can_read_reg32(priv, C_CAN_MSGVAL1_REG)); -} - -static inline int c_can_is_next_tx_obj_busy(struct c_can_priv *priv, int objno) -{ - int val = c_can_read_reg32(priv, C_CAN_TXRQST1_REG); - - /* - * as transmission request register's bit n-1 corresponds to - * message object n, we need to handle the same properly. - */ - if (val & (1 << (objno - 1))) - return 1; - - return 0; + c_can_object_put(dev, iface, obj, IF_COMM_RCV_SETUP); } static netdev_tx_t c_can_start_xmit(struct sk_buff *skb, - struct net_device *dev) + struct net_device *dev) { - u32 msg_obj_no; - struct c_can_priv *priv = netdev_priv(dev); struct can_frame *frame = (struct can_frame *)skb->data; + struct c_can_priv *priv = netdev_priv(dev); + u32 idx, obj; if (can_dropped_invalid_skb(dev, skb)) return NETDEV_TX_OK; - - spin_lock_bh(&priv->xmit_lock); - msg_obj_no = get_tx_next_msg_obj(priv); - - /* prepare message object for transmission */ - c_can_write_msg_object(dev, IF_TX, frame, msg_obj_no); - priv->dlc[msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST] = frame->can_dlc; - can_put_echo_skb(skb, dev, msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST); - /* - * we have to stop the queue in case of a wrap around or - * if the next TX message object is still in use + * This is not a FIFO. C/D_CAN sends out the buffers + * prioritized. The lowest buffer number wins. */ - priv->tx_next++; - if (c_can_is_next_tx_obj_busy(priv, get_tx_next_msg_obj(priv)) || - (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) == 0) + idx = fls(atomic_read(&priv->tx_active)); + obj = idx + C_CAN_MSG_OBJ_TX_FIRST; + + /* If this is the last buffer, stop the xmit queue */ + if (idx == C_CAN_MSG_OBJ_TX_NUM - 1) netif_stop_queue(dev); - spin_unlock_bh(&priv->xmit_lock); + /* + * Store the message in the interface so we can call + * can_put_echo_skb(). We must do this before we enable + * transmit as we might race against do_tx(). + */ + c_can_setup_tx_object(dev, IF_TX, frame, idx); + priv->dlc[idx] = frame->can_dlc; + can_put_echo_skb(skb, dev, idx); + + /* Update the active bits */ + atomic_add((1 << idx), &priv->tx_active); + /* Start transmission */ + c_can_object_put(dev, IF_TX, obj, IF_COMM_TX); return NETDEV_TX_OK; } @@ -594,11 +543,10 @@ static void c_can_configure_msg_objects(struct net_device *dev) /* setup receive message objects */ for (i = C_CAN_MSG_OBJ_RX_FIRST; i < C_CAN_MSG_OBJ_RX_LAST; i++) - c_can_setup_receive_object(dev, IF_RX, i, 0, 0, - (IF_MCONT_RXIE | IF_MCONT_UMASK) & ~IF_MCONT_EOB); + c_can_setup_receive_object(dev, IF_RX, i, 0, 0, IF_MCONT_RCV); c_can_setup_receive_object(dev, IF_RX, C_CAN_MSG_OBJ_RX_LAST, 0, 0, - IF_MCONT_EOB | IF_MCONT_RXIE | IF_MCONT_UMASK); + IF_MCONT_RCV_EOB); } /* @@ -612,30 +560,22 @@ static int c_can_chip_config(struct net_device *dev) struct c_can_priv *priv = netdev_priv(dev); /* enable automatic retransmission */ - priv->write_reg(priv, C_CAN_CTRL_REG, - CONTROL_ENABLE_AR); + priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR); if ((priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) && (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)) { /* loopback + silent mode : useful for hot self-test */ - priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_EIE | - CONTROL_SIE | CONTROL_IE | CONTROL_TEST); - priv->write_reg(priv, C_CAN_TEST_REG, - TEST_LBACK | TEST_SILENT); + priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST); + priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK | TEST_SILENT); } else if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { /* loopback mode : useful for self-test function */ - priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_EIE | - CONTROL_SIE | CONTROL_IE | CONTROL_TEST); + priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST); priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK); } else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) { /* silent mode : bus-monitoring mode */ - priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_EIE | - CONTROL_SIE | CONTROL_IE | CONTROL_TEST); + priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST); priv->write_reg(priv, C_CAN_TEST_REG, TEST_SILENT); - } else - /* normal mode*/ - priv->write_reg(priv, C_CAN_CTRL_REG, - CONTROL_EIE | CONTROL_SIE | CONTROL_IE); + } /* configure message objects */ c_can_configure_msg_objects(dev); @@ -643,6 +583,11 @@ static int c_can_chip_config(struct net_device *dev) /* set a `lec` value so that we can check for updates later */ priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); + /* Clear all internal status */ + atomic_set(&priv->tx_active, 0); + priv->rxmasked = 0; + priv->tx_dir = 0; + /* set bittiming params */ return c_can_set_bittiming(dev); } @@ -657,13 +602,11 @@ static int c_can_start(struct net_device *dev) if (err) return err; - priv->can.state = CAN_STATE_ERROR_ACTIVE; - - /* reset tx helper pointers */ - priv->tx_next = priv->tx_echo = 0; + /* Setup the command for new messages */ + priv->comm_rcv_high = priv->type != BOSCH_D_CAN ? + IF_COMM_RCV_LOW : IF_COMM_RCV_HIGH; - /* enable status change, error and module interrupts */ - c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS); + priv->can.state = CAN_STATE_ERROR_ACTIVE; return 0; } @@ -672,15 +615,13 @@ static void c_can_stop(struct net_device *dev) { struct c_can_priv *priv = netdev_priv(dev); - /* disable all interrupts */ - c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS); - - /* set the state as STOPPED */ + c_can_irq_control(priv, false); priv->can.state = CAN_STATE_STOPPED; } static int c_can_set_mode(struct net_device *dev, enum can_mode mode) { + struct c_can_priv *priv = netdev_priv(dev); int err; switch (mode) { @@ -689,6 +630,7 @@ static int c_can_set_mode(struct net_device *dev, enum can_mode mode) if (err) return err; netif_wake_queue(dev); + c_can_irq_control(priv, true); break; default: return -EOPNOTSUPP; @@ -724,42 +666,29 @@ static int c_can_get_berr_counter(const struct net_device *dev, return err; } -/* - * priv->tx_echo holds the number of the oldest can_frame put for - * transmission into the hardware, but not yet ACKed by the CAN tx - * complete IRQ. - * - * We iterate from priv->tx_echo to priv->tx_next and check if the - * packet has been transmitted, echo it back to the CAN framework. - * If we discover a not yet transmitted packet, stop looking for more. - */ static void c_can_do_tx(struct net_device *dev) { struct c_can_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; - u32 val, obj, pkts = 0, bytes = 0; - - spin_lock_bh(&priv->xmit_lock); + u32 idx, obj, pkts = 0, bytes = 0, pend, clr; - for (; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) { - obj = get_tx_echo_msg_obj(priv->tx_echo); - val = c_can_read_reg32(priv, C_CAN_TXRQST1_REG); + clr = pend = priv->read_reg(priv, C_CAN_INTPND2_REG); - if (val & (1 << (obj - 1))) - break; - - can_get_echo_skb(dev, obj - C_CAN_MSG_OBJ_TX_FIRST); - bytes += priv->dlc[obj - C_CAN_MSG_OBJ_TX_FIRST]; + while ((idx = ffs(pend))) { + idx--; + pend &= ~(1 << idx); + obj = idx + C_CAN_MSG_OBJ_TX_FIRST; + c_can_inval_tx_object(dev, IF_RX, obj); + can_get_echo_skb(dev, idx); + bytes += priv->dlc[idx]; pkts++; - c_can_inval_msg_object(dev, IF_TX, obj); } - /* restart queue if wrap-up or if queue stalled on last pkt */ - if (((priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) != 0) || - ((priv->tx_echo & C_CAN_NEXT_MSG_OBJ_MASK) == 0)) - netif_wake_queue(dev); + /* Clear the bits in the tx_active mask */ + atomic_sub(clr, &priv->tx_active); - spin_unlock_bh(&priv->xmit_lock); + if (clr & (1 << (C_CAN_MSG_OBJ_TX_NUM - 1))) + netif_wake_queue(dev); if (pkts) { stats->tx_bytes += bytes; @@ -800,18 +729,42 @@ static u32 c_can_adjust_pending(u32 pend) return pend & ~((1 << lasts) - 1); } +static inline void c_can_rx_object_get(struct net_device *dev, + struct c_can_priv *priv, u32 obj) +{ +#ifdef CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING + if (obj < C_CAN_MSG_RX_LOW_LAST) + c_can_object_get(dev, IF_RX, obj, IF_COMM_RCV_LOW); + else +#endif + c_can_object_get(dev, IF_RX, obj, priv->comm_rcv_high); +} + +static inline void c_can_rx_finalize(struct net_device *dev, + struct c_can_priv *priv, u32 obj) +{ +#ifdef CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING + if (obj < C_CAN_MSG_RX_LOW_LAST) + priv->rxmasked |= BIT(obj - 1); + else if (obj == C_CAN_MSG_RX_LOW_LAST) { + priv->rxmasked = 0; + /* activate all lower message objects */ + c_can_activate_all_lower_rx_msg_obj(dev, IF_RX); + } +#endif + if (priv->type != BOSCH_D_CAN) + c_can_object_get(dev, IF_RX, obj, IF_COMM_CLR_NEWDAT); +} + static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv, u32 pend, int quota) { - u32 pkts = 0, ctrl, obj, mcmd; + u32 pkts = 0, ctrl, obj; while ((obj = ffs(pend)) && quota > 0) { pend &= ~BIT(obj - 1); - mcmd = obj < C_CAN_MSG_RX_LOW_LAST ? - IF_COMM_RCV_LOW : IF_COMM_RCV_HIGH; - - c_can_object_get(dev, IF_RX, obj, mcmd); + c_can_rx_object_get(dev, priv, obj); ctrl = priv->read_reg(priv, C_CAN_IFACE(MSGCTRL_REG, IF_RX)); if (ctrl & IF_MCONT_MSGLST) { @@ -833,9 +786,7 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv, /* read the data from the message object */ c_can_read_msg_object(dev, IF_RX, ctrl); - if (obj == C_CAN_MSG_RX_LOW_LAST) - /* activate all lower message objects */ - c_can_activate_all_lower_rx_msg_obj(dev, IF_RX, ctrl); + c_can_rx_finalize(dev, priv, obj); pkts++; quota--; @@ -844,6 +795,16 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv, return pkts; } +static inline u32 c_can_get_pending(struct c_can_priv *priv) +{ + u32 pend = priv->read_reg(priv, C_CAN_NEWDAT1_REG); + +#ifdef CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING + pend &= ~priv->rxmasked; +#endif + return pend; +} + /* * theory of operation: * @@ -853,6 +814,8 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv, * has arrived. To work-around this issue, we keep two groups of message * objects whose partitioning is defined by C_CAN_MSG_OBJ_RX_SPLIT. * + * If CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING = y + * * To ensure in-order frame reception we use the following * approach while re-activating a message object to receive further * frames: @@ -865,6 +828,14 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv, * - if the current message object number is greater than * C_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of * only this message object. + * + * This can cause packet loss! + * + * If CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING = n + * + * We clear the newdat bit right away. + * + * This can result in packet reordering when the readout is slow. */ static int c_can_do_rx_poll(struct net_device *dev, int quota) { @@ -880,7 +851,7 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota) while (quota > 0) { if (!pend) { - pend = priv->read_reg(priv, C_CAN_INTPND1_REG); + pend = c_can_get_pending(priv); if (!pend) break; /* @@ -905,12 +876,6 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota) return pkts; } -static inline int c_can_has_and_handle_berr(struct c_can_priv *priv) -{ - return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) && - (priv->current_status & LEC_UNUSED); -} - static int c_can_handle_state_change(struct net_device *dev, enum c_can_bus_error_types error_type) { @@ -922,6 +887,26 @@ static int c_can_handle_state_change(struct net_device *dev, struct sk_buff *skb; struct can_berr_counter bec; + switch (error_type) { + case C_CAN_ERROR_WARNING: + /* error warning state */ + priv->can.can_stats.error_warning++; + priv->can.state = CAN_STATE_ERROR_WARNING; + break; + case C_CAN_ERROR_PASSIVE: + /* error passive state */ + priv->can.can_stats.error_passive++; + priv->can.state = CAN_STATE_ERROR_PASSIVE; + break; + case C_CAN_BUS_OFF: + /* bus-off state */ + priv->can.state = CAN_STATE_BUS_OFF; + can_bus_off(dev); + break; + default: + break; + } + /* propagate the error condition to the CAN stack */ skb = alloc_can_err_skb(dev, &cf); if (unlikely(!skb)) @@ -935,8 +920,6 @@ static int c_can_handle_state_change(struct net_device *dev, switch (error_type) { case C_CAN_ERROR_WARNING: /* error warning state */ - priv->can.can_stats.error_warning++; - priv->can.state = CAN_STATE_ERROR_WARNING; cf->can_id |= CAN_ERR_CRTL; cf->data[1] = (bec.txerr > bec.rxerr) ? CAN_ERR_CRTL_TX_WARNING : @@ -947,8 +930,6 @@ static int c_can_handle_state_change(struct net_device *dev, break; case C_CAN_ERROR_PASSIVE: /* error passive state */ - priv->can.can_stats.error_passive++; - priv->can.state = CAN_STATE_ERROR_PASSIVE; cf->can_id |= CAN_ERR_CRTL; if (rx_err_passive) cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; @@ -960,22 +941,16 @@ static int c_can_handle_state_change(struct net_device *dev, break; case C_CAN_BUS_OFF: /* bus-off state */ - priv->can.state = CAN_STATE_BUS_OFF; cf->can_id |= CAN_ERR_BUSOFF; - /* - * disable all interrupts in bus-off mode to ensure that - * the CPU is not hogged down - */ - c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS); can_bus_off(dev); break; default: break; } - netif_receive_skb(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_receive_skb(skb); return 1; } @@ -996,6 +971,13 @@ static int c_can_handle_bus_err(struct net_device *dev, if (lec_type == LEC_UNUSED || lec_type == LEC_NO_ERROR) return 0; + if (!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) + return 0; + + /* common for all type of bus errors */ + priv->can.can_stats.bus_error++; + stats->rx_errors++; + /* propagate the error condition to the CAN stack */ skb = alloc_can_err_skb(dev, &cf); if (unlikely(!skb)) @@ -1005,10 +987,6 @@ static int c_can_handle_bus_err(struct net_device *dev, * check for 'last error code' which tells us the * type of the last error to occur on the CAN bus */ - - /* common for all type of bus errors */ - priv->can.can_stats.bus_error++; - stats->rx_errors++; cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; cf->data[2] |= CAN_ERR_PROT_UNSPEC; @@ -1043,95 +1021,64 @@ static int c_can_handle_bus_err(struct net_device *dev, break; } - /* set a `lec` value so that we can check for updates later */ - priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); - - netif_receive_skb(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; - + netif_receive_skb(skb); return 1; } static int c_can_poll(struct napi_struct *napi, int quota) { - u16 irqstatus; - int lec_type = 0; - int work_done = 0; struct net_device *dev = napi->dev; struct c_can_priv *priv = netdev_priv(dev); + u16 curr, last = priv->last_status; + int work_done = 0; - irqstatus = priv->irqstatus; - if (!irqstatus) - goto end; + priv->last_status = curr = priv->read_reg(priv, C_CAN_STS_REG); + /* Ack status on C_CAN. D_CAN is self clearing */ + if (priv->type != BOSCH_D_CAN) + priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); - /* status events have the highest priority */ - if (irqstatus == STATUS_INTERRUPT) { - priv->current_status = priv->read_reg(priv, - C_CAN_STS_REG); - - /* handle Tx/Rx events */ - if (priv->current_status & STATUS_TXOK) - priv->write_reg(priv, C_CAN_STS_REG, - priv->current_status & ~STATUS_TXOK); - - if (priv->current_status & STATUS_RXOK) - priv->write_reg(priv, C_CAN_STS_REG, - priv->current_status & ~STATUS_RXOK); - - /* handle state changes */ - if ((priv->current_status & STATUS_EWARN) && - (!(priv->last_status & STATUS_EWARN))) { - netdev_dbg(dev, "entered error warning state\n"); - work_done += c_can_handle_state_change(dev, - C_CAN_ERROR_WARNING); - } - if ((priv->current_status & STATUS_EPASS) && - (!(priv->last_status & STATUS_EPASS))) { - netdev_dbg(dev, "entered error passive state\n"); - work_done += c_can_handle_state_change(dev, - C_CAN_ERROR_PASSIVE); - } - if ((priv->current_status & STATUS_BOFF) && - (!(priv->last_status & STATUS_BOFF))) { - netdev_dbg(dev, "entered bus off state\n"); - work_done += c_can_handle_state_change(dev, - C_CAN_BUS_OFF); - } + /* handle state changes */ + if ((curr & STATUS_EWARN) && (!(last & STATUS_EWARN))) { + netdev_dbg(dev, "entered error warning state\n"); + work_done += c_can_handle_state_change(dev, C_CAN_ERROR_WARNING); + } - /* handle bus recovery events */ - if ((!(priv->current_status & STATUS_BOFF)) && - (priv->last_status & STATUS_BOFF)) { - netdev_dbg(dev, "left bus off state\n"); - priv->can.state = CAN_STATE_ERROR_ACTIVE; - } - if ((!(priv->current_status & STATUS_EPASS)) && - (priv->last_status & STATUS_EPASS)) { - netdev_dbg(dev, "left error passive state\n"); - priv->can.state = CAN_STATE_ERROR_ACTIVE; - } + if ((curr & STATUS_EPASS) && (!(last & STATUS_EPASS))) { + netdev_dbg(dev, "entered error passive state\n"); + work_done += c_can_handle_state_change(dev, C_CAN_ERROR_PASSIVE); + } + + if ((curr & STATUS_BOFF) && (!(last & STATUS_BOFF))) { + netdev_dbg(dev, "entered bus off state\n"); + work_done += c_can_handle_state_change(dev, C_CAN_BUS_OFF); + goto end; + } - priv->last_status = priv->current_status; - - /* handle lec errors on the bus */ - lec_type = c_can_has_and_handle_berr(priv); - if (lec_type) - work_done += c_can_handle_bus_err(dev, lec_type); - } else if ((irqstatus >= C_CAN_MSG_OBJ_RX_FIRST) && - (irqstatus <= C_CAN_MSG_OBJ_RX_LAST)) { - /* handle events corresponding to receive message objects */ - work_done += c_can_do_rx_poll(dev, (quota - work_done)); - } else if ((irqstatus >= C_CAN_MSG_OBJ_TX_FIRST) && - (irqstatus <= C_CAN_MSG_OBJ_TX_LAST)) { - /* handle events corresponding to transmit message objects */ - c_can_do_tx(dev); + /* handle bus recovery events */ + if ((!(curr & STATUS_BOFF)) && (last & STATUS_BOFF)) { + netdev_dbg(dev, "left bus off state\n"); + priv->can.state = CAN_STATE_ERROR_ACTIVE; + } + if ((!(curr & STATUS_EPASS)) && (last & STATUS_EPASS)) { + netdev_dbg(dev, "left error passive state\n"); + priv->can.state = CAN_STATE_ERROR_ACTIVE; } + /* handle lec errors on the bus */ + work_done += c_can_handle_bus_err(dev, curr & LEC_MASK); + + /* Handle Tx/Rx events. We do this unconditionally */ + work_done += c_can_do_rx_poll(dev, (quota - work_done)); + c_can_do_tx(dev); + end: if (work_done < quota) { napi_complete(napi); - /* enable all IRQs */ - c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS); + /* enable all IRQs if we are not in bus off state */ + if (priv->can.state != CAN_STATE_BUS_OFF) + c_can_irq_control(priv, true); } return work_done; @@ -1142,12 +1089,11 @@ static irqreturn_t c_can_isr(int irq, void *dev_id) struct net_device *dev = (struct net_device *)dev_id; struct c_can_priv *priv = netdev_priv(dev); - priv->irqstatus = priv->read_reg(priv, C_CAN_INT_REG); - if (!priv->irqstatus) + if (!priv->read_reg(priv, C_CAN_INT_REG)) return IRQ_NONE; /* disable all interrupts and schedule the NAPI */ - c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS); + c_can_irq_control(priv, false); napi_schedule(&priv->napi); return IRQ_HANDLED; @@ -1184,6 +1130,8 @@ static int c_can_open(struct net_device *dev) can_led_event(dev, CAN_LED_EVENT_OPEN); napi_enable(&priv->napi); + /* enable status change, error and module interrupts */ + c_can_irq_control(priv, true); netif_start_queue(dev); return 0; @@ -1226,7 +1174,6 @@ struct net_device *alloc_c_can_dev(void) return NULL; priv = netdev_priv(dev); - spin_lock_init(&priv->xmit_lock); netif_napi_add(dev, &priv->napi, c_can_poll, C_CAN_NAPI_WEIGHT); priv->dev = dev; @@ -1281,6 +1228,7 @@ int c_can_power_up(struct net_device *dev) u32 val; unsigned long time_out; struct c_can_priv *priv = netdev_priv(dev); + int ret; if (!(dev->flags & IFF_UP)) return 0; @@ -1307,7 +1255,11 @@ int c_can_power_up(struct net_device *dev) if (time_after(jiffies, time_out)) return -ETIMEDOUT; - return c_can_start(dev); + ret = c_can_start(dev); + if (!ret) + c_can_irq_control(priv, true); + + return ret; } EXPORT_SYMBOL_GPL(c_can_power_up); #endif diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h index faa8404162b3..c56f1b1c11ca 100644 --- a/drivers/net/can/c_can/c_can.h +++ b/drivers/net/can/c_can/c_can.h @@ -22,14 +22,6 @@ #ifndef C_CAN_H #define C_CAN_H -/* - * IFx register masks: - * allow easy operation on 16-bit registers when the - * argument is 32-bit instead - */ -#define IFX_WRITE_LOW_16BIT(x) ((x) & 0xFFFF) -#define IFX_WRITE_HIGH_16BIT(x) (((x) & 0xFFFF0000) >> 16) - /* message object split */ #define C_CAN_NO_OF_OBJECTS 32 #define C_CAN_MSG_OBJ_RX_NUM 16 @@ -45,8 +37,6 @@ #define C_CAN_MSG_OBJ_RX_SPLIT 9 #define C_CAN_MSG_RX_LOW_LAST (C_CAN_MSG_OBJ_RX_SPLIT - 1) - -#define C_CAN_NEXT_MSG_OBJ_MASK (C_CAN_MSG_OBJ_TX_NUM - 1) #define RECEIVE_OBJECT_BITS 0x0000ffff enum reg { @@ -183,23 +173,20 @@ struct c_can_priv { struct napi_struct napi; struct net_device *dev; struct device *device; - spinlock_t xmit_lock; - int tx_object; - int current_status; + atomic_t tx_active; + unsigned long tx_dir; int last_status; u16 (*read_reg) (struct c_can_priv *priv, enum reg index); void (*write_reg) (struct c_can_priv *priv, enum reg index, u16 val); void __iomem *base; const u16 *regs; - unsigned long irq_flags; /* for request_irq() */ - unsigned int tx_next; - unsigned int tx_echo; void *priv; /* for board-specific data */ - u16 irqstatus; enum c_can_dev_id type; u32 __iomem *raminit_ctrlreg; - unsigned int instance; + int instance; void (*raminit) (const struct c_can_priv *priv, bool enable); + u32 comm_rcv_high; + u32 rxmasked; u32 dlc[C_CAN_MSG_OBJ_TX_NUM]; }; diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c index bce0be54c2f5..fe5f6303b584 100644 --- a/drivers/net/can/c_can/c_can_pci.c +++ b/drivers/net/can/c_can/c_can_pci.c @@ -84,8 +84,11 @@ static int c_can_pci_probe(struct pci_dev *pdev, goto out_disable_device; } - pci_set_master(pdev); - pci_enable_msi(pdev); + ret = pci_enable_msi(pdev); + if (!ret) { + dev_info(&pdev->dev, "MSI enabled\n"); + pci_set_master(pdev); + } addr = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); if (!addr) { @@ -132,6 +135,8 @@ static int c_can_pci_probe(struct pci_dev *pdev, goto out_free_c_can; } + priv->type = c_can_pci_data->type; + /* Configure access to registers */ switch (c_can_pci_data->reg_align) { case C_CAN_REG_ALIGN_32: diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index 806d92753427..1df0b322d1e4 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -222,7 +222,7 @@ static int c_can_plat_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 1); priv->raminit_ctrlreg = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(priv->raminit_ctrlreg) || (int)priv->instance < 0) + if (IS_ERR(priv->raminit_ctrlreg) || priv->instance < 0) dev_info(&pdev->dev, "control memory is not used for raminit\n"); else priv->raminit = c_can_hw_raminit; diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index c7a260478749..e318e87e2bfc 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -256,7 +256,7 @@ static int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt, /* Check if the CAN device has bit-timing parameters */ if (!btc) - return -ENOTSUPP; + return -EOPNOTSUPP; /* * Depending on the given can_bittiming parameter structure the CAN diff --git a/drivers/net/can/sja1000/sja1000_isa.c b/drivers/net/can/sja1000/sja1000_isa.c index df136a2516c4..014695d7e6a3 100644 --- a/drivers/net/can/sja1000/sja1000_isa.c +++ b/drivers/net/can/sja1000/sja1000_isa.c @@ -46,6 +46,7 @@ static int clk[MAXDEV]; static unsigned char cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff}; static unsigned char ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff}; static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1}; +static spinlock_t indirect_lock[MAXDEV]; /* lock for indirect access mode */ module_param_array(port, ulong, NULL, S_IRUGO); MODULE_PARM_DESC(port, "I/O port number"); @@ -101,19 +102,26 @@ static void sja1000_isa_port_write_reg(const struct sja1000_priv *priv, static u8 sja1000_isa_port_read_reg_indirect(const struct sja1000_priv *priv, int reg) { - unsigned long base = (unsigned long)priv->reg_base; + unsigned long flags, base = (unsigned long)priv->reg_base; + u8 readval; + spin_lock_irqsave(&indirect_lock[priv->dev->dev_id], flags); outb(reg, base); - return inb(base + 1); + readval = inb(base + 1); + spin_unlock_irqrestore(&indirect_lock[priv->dev->dev_id], flags); + + return readval; } static void sja1000_isa_port_write_reg_indirect(const struct sja1000_priv *priv, int reg, u8 val) { - unsigned long base = (unsigned long)priv->reg_base; + unsigned long flags, base = (unsigned long)priv->reg_base; + spin_lock_irqsave(&indirect_lock[priv->dev->dev_id], flags); outb(reg, base); outb(val, base + 1); + spin_unlock_irqrestore(&indirect_lock[priv->dev->dev_id], flags); } static int sja1000_isa_probe(struct platform_device *pdev) @@ -169,6 +177,7 @@ static int sja1000_isa_probe(struct platform_device *pdev) if (iosize == SJA1000_IOSIZE_INDIRECT) { priv->read_reg = sja1000_isa_port_read_reg_indirect; priv->write_reg = sja1000_isa_port_write_reg_indirect; + spin_lock_init(&indirect_lock[idx]); } else { priv->read_reg = sja1000_isa_port_read_reg; priv->write_reg = sja1000_isa_port_write_reg; @@ -198,6 +207,7 @@ static int sja1000_isa_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); SET_NETDEV_DEV(dev, &pdev->dev); + dev->dev_id = idx; err = register_sja1000dev(dev); if (err) { diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index f5b16e0e3a12..dcf9196f6316 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -322,13 +322,13 @@ static void slcan_write_wakeup(struct tty_struct *tty) if (!sl || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev)) return; - spin_lock(&sl->lock); + spin_lock_bh(&sl->lock); if (sl->xleft <= 0) { /* Now serial buffer is almost free & we can start * transmission of another packet */ sl->dev->stats.tx_packets++; clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - spin_unlock(&sl->lock); + spin_unlock_bh(&sl->lock); netif_wake_queue(sl->dev); return; } @@ -336,7 +336,7 @@ static void slcan_write_wakeup(struct tty_struct *tty) actual = tty->ops->write(tty, sl->xhead, sl->xleft); sl->xleft -= actual; sl->xhead += actual; - spin_unlock(&sl->lock); + spin_unlock_bh(&sl->lock); } /* Send a can_frame to a TTY queue. */ diff --git a/drivers/net/ethernet/altera/Kconfig b/drivers/net/ethernet/altera/Kconfig index 80c1ab74a4b8..fdddba51473e 100644 --- a/drivers/net/ethernet/altera/Kconfig +++ b/drivers/net/ethernet/altera/Kconfig @@ -1,5 +1,6 @@ config ALTERA_TSE tristate "Altera Triple-Speed Ethernet MAC support" + depends on HAS_DMA select PHYLIB ---help--- This driver supports the Altera Triple-Speed (TSE) Ethernet MAC. diff --git a/drivers/net/ethernet/altera/altera_msgdma.c b/drivers/net/ethernet/altera/altera_msgdma.c index 3df18669ea30..4d1f2fdd5c32 100644 --- a/drivers/net/ethernet/altera/altera_msgdma.c +++ b/drivers/net/ethernet/altera/altera_msgdma.c @@ -18,6 +18,7 @@ #include "altera_utils.h" #include "altera_tse.h" #include "altera_msgdmahw.h" +#include "altera_msgdma.h" /* No initialization work to do for MSGDMA */ int msgdma_initialize(struct altera_tse_private *priv) @@ -29,6 +30,10 @@ void msgdma_uninitialize(struct altera_tse_private *priv) { } +void msgdma_start_rxdma(struct altera_tse_private *priv) +{ +} + void msgdma_reset(struct altera_tse_private *priv) { int counter; @@ -154,7 +159,7 @@ u32 msgdma_tx_completions(struct altera_tse_private *priv) /* Put buffer to the mSGDMA RX FIFO */ -int msgdma_add_rx_desc(struct altera_tse_private *priv, +void msgdma_add_rx_desc(struct altera_tse_private *priv, struct tse_buffer *rxbuffer) { struct msgdma_extended_desc *desc = priv->rx_dma_desc; @@ -175,7 +180,6 @@ int msgdma_add_rx_desc(struct altera_tse_private *priv, iowrite32(0, &desc->burst_seq_num); iowrite32(0x00010001, &desc->stride); iowrite32(control, &desc->control); - return 1; } /* status is returned on upper 16 bits, diff --git a/drivers/net/ethernet/altera/altera_msgdma.h b/drivers/net/ethernet/altera/altera_msgdma.h index 7f0f5bf2bba2..42cf61c81057 100644 --- a/drivers/net/ethernet/altera/altera_msgdma.h +++ b/drivers/net/ethernet/altera/altera_msgdma.h @@ -25,10 +25,11 @@ void msgdma_disable_txirq(struct altera_tse_private *); void msgdma_clear_rxirq(struct altera_tse_private *); void msgdma_clear_txirq(struct altera_tse_private *); u32 msgdma_tx_completions(struct altera_tse_private *); -int msgdma_add_rx_desc(struct altera_tse_private *, struct tse_buffer *); +void msgdma_add_rx_desc(struct altera_tse_private *, struct tse_buffer *); int msgdma_tx_buffer(struct altera_tse_private *, struct tse_buffer *); u32 msgdma_rx_status(struct altera_tse_private *); int msgdma_initialize(struct altera_tse_private *); void msgdma_uninitialize(struct altera_tse_private *); +void msgdma_start_rxdma(struct altera_tse_private *); #endif /* __ALTERA_MSGDMA_H__ */ diff --git a/drivers/net/ethernet/altera/altera_sgdma.c b/drivers/net/ethernet/altera/altera_sgdma.c index 0ee96639ae44..9ce8630692b6 100644 --- a/drivers/net/ethernet/altera/altera_sgdma.c +++ b/drivers/net/ethernet/altera/altera_sgdma.c @@ -20,15 +20,15 @@ #include "altera_sgdmahw.h" #include "altera_sgdma.h" -static void sgdma_descrip(struct sgdma_descrip *desc, - struct sgdma_descrip *ndesc, - dma_addr_t ndesc_phys, - dma_addr_t raddr, - dma_addr_t waddr, - u16 length, - int generate_eop, - int rfixed, - int wfixed); +static void sgdma_setup_descrip(struct sgdma_descrip *desc, + struct sgdma_descrip *ndesc, + dma_addr_t ndesc_phys, + dma_addr_t raddr, + dma_addr_t waddr, + u16 length, + int generate_eop, + int rfixed, + int wfixed); static int sgdma_async_write(struct altera_tse_private *priv, struct sgdma_descrip *desc); @@ -64,11 +64,15 @@ queue_rx_peekhead(struct altera_tse_private *priv); int sgdma_initialize(struct altera_tse_private *priv) { - priv->txctrlreg = SGDMA_CTRLREG_ILASTD; + priv->txctrlreg = SGDMA_CTRLREG_ILASTD | + SGDMA_CTRLREG_INTEN; priv->rxctrlreg = SGDMA_CTRLREG_IDESCRIP | + SGDMA_CTRLREG_INTEN | SGDMA_CTRLREG_ILASTD; + priv->sgdmadesclen = sizeof(struct sgdma_descrip); + INIT_LIST_HEAD(&priv->txlisthd); INIT_LIST_HEAD(&priv->rxlisthd); @@ -93,6 +97,16 @@ int sgdma_initialize(struct altera_tse_private *priv) return -EINVAL; } + /* Initialize descriptor memory to all 0's, sync memory to cache */ + memset(priv->tx_dma_desc, 0, priv->txdescmem); + memset(priv->rx_dma_desc, 0, priv->rxdescmem); + + dma_sync_single_for_device(priv->device, priv->txdescphys, + priv->txdescmem, DMA_TO_DEVICE); + + dma_sync_single_for_device(priv->device, priv->rxdescphys, + priv->rxdescmem, DMA_TO_DEVICE); + return 0; } @@ -130,26 +144,23 @@ void sgdma_reset(struct altera_tse_private *priv) iowrite32(0, &prxsgdma->control); } +/* For SGDMA, interrupts remain enabled after initially enabling, + * so no need to provide implementations for abstract enable + * and disable + */ + void sgdma_enable_rxirq(struct altera_tse_private *priv) { - struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr; - priv->rxctrlreg |= SGDMA_CTRLREG_INTEN; - tse_set_bit(&csr->control, SGDMA_CTRLREG_INTEN); } void sgdma_enable_txirq(struct altera_tse_private *priv) { - struct sgdma_csr *csr = (struct sgdma_csr *)priv->tx_dma_csr; - priv->txctrlreg |= SGDMA_CTRLREG_INTEN; - tse_set_bit(&csr->control, SGDMA_CTRLREG_INTEN); } -/* for SGDMA, RX interrupts remain enabled after enabling */ void sgdma_disable_rxirq(struct altera_tse_private *priv) { } -/* for SGDMA, TX interrupts remain enabled after enabling */ void sgdma_disable_txirq(struct altera_tse_private *priv) { } @@ -184,15 +195,15 @@ int sgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *buffer) if (sgdma_txbusy(priv)) return 0; - sgdma_descrip(cdesc, /* current descriptor */ - ndesc, /* next descriptor */ - sgdma_txphysaddr(priv, ndesc), - buffer->dma_addr, /* address of packet to xmit */ - 0, /* write addr 0 for tx dma */ - buffer->len, /* length of packet */ - SGDMA_CONTROL_EOP, /* Generate EOP */ - 0, /* read fixed */ - SGDMA_CONTROL_WR_FIXED); /* Generate SOP */ + sgdma_setup_descrip(cdesc, /* current descriptor */ + ndesc, /* next descriptor */ + sgdma_txphysaddr(priv, ndesc), + buffer->dma_addr, /* address of packet to xmit */ + 0, /* write addr 0 for tx dma */ + buffer->len, /* length of packet */ + SGDMA_CONTROL_EOP, /* Generate EOP */ + 0, /* read fixed */ + SGDMA_CONTROL_WR_FIXED); /* Generate SOP */ pktstx = sgdma_async_write(priv, cdesc); @@ -219,11 +230,15 @@ u32 sgdma_tx_completions(struct altera_tse_private *priv) return ready; } -int sgdma_add_rx_desc(struct altera_tse_private *priv, - struct tse_buffer *rxbuffer) +void sgdma_start_rxdma(struct altera_tse_private *priv) +{ + sgdma_async_read(priv); +} + +void sgdma_add_rx_desc(struct altera_tse_private *priv, + struct tse_buffer *rxbuffer) { queue_rx(priv, rxbuffer); - return sgdma_async_read(priv); } /* status is returned on upper 16 bits, @@ -240,28 +255,52 @@ u32 sgdma_rx_status(struct altera_tse_private *priv) unsigned int pktstatus = 0; struct tse_buffer *rxbuffer = NULL; - dma_sync_single_for_cpu(priv->device, - priv->rxdescphys, - priv->rxdescmem, - DMA_BIDIRECTIONAL); + u32 sts = ioread32(&csr->status); desc = &base[0]; - if ((ioread32(&csr->status) & SGDMA_STSREG_EOP) || - (desc->status & SGDMA_STATUS_EOP)) { + if (sts & SGDMA_STSREG_EOP) { + dma_sync_single_for_cpu(priv->device, + priv->rxdescphys, + priv->sgdmadesclen, + DMA_FROM_DEVICE); + pktlength = desc->bytes_xferred; pktstatus = desc->status & 0x3f; rxstatus = pktstatus; rxstatus = rxstatus << 16; rxstatus |= (pktlength & 0xffff); - desc->status = 0; + if (rxstatus) { + desc->status = 0; - rxbuffer = dequeue_rx(priv); - if (rxbuffer == NULL) - netdev_err(priv->dev, - "sgdma rx and rx queue empty!\n"); + rxbuffer = dequeue_rx(priv); + if (rxbuffer == NULL) + netdev_info(priv->dev, + "sgdma rx and rx queue empty!\n"); + + /* Clear control */ + iowrite32(0, &csr->control); + /* clear status */ + iowrite32(0xf, &csr->status); - /* kick the rx sgdma after reaping this descriptor */ + /* kick the rx sgdma after reaping this descriptor */ + pktsrx = sgdma_async_read(priv); + + } else { + /* If the SGDMA indicated an end of packet on recv, + * then it's expected that the rxstatus from the + * descriptor is non-zero - meaning a valid packet + * with a nonzero length, or an error has been + * indicated. if not, then all we can do is signal + * an error and return no packet received. Most likely + * there is a system design error, or an error in the + * underlying kernel (cache or cache management problem) + */ + netdev_err(priv->dev, + "SGDMA RX Error Info: %x, %x, %x\n", + sts, desc->status, rxstatus); + } + } else if (sts == 0) { pktsrx = sgdma_async_read(priv); } @@ -270,15 +309,15 @@ u32 sgdma_rx_status(struct altera_tse_private *priv) /* Private functions */ -static void sgdma_descrip(struct sgdma_descrip *desc, - struct sgdma_descrip *ndesc, - dma_addr_t ndesc_phys, - dma_addr_t raddr, - dma_addr_t waddr, - u16 length, - int generate_eop, - int rfixed, - int wfixed) +static void sgdma_setup_descrip(struct sgdma_descrip *desc, + struct sgdma_descrip *ndesc, + dma_addr_t ndesc_phys, + dma_addr_t raddr, + dma_addr_t waddr, + u16 length, + int generate_eop, + int rfixed, + int wfixed) { /* Clear the next descriptor as not owned by hardware */ u32 ctrl = ndesc->control; @@ -319,35 +358,29 @@ static int sgdma_async_read(struct altera_tse_private *priv) struct sgdma_descrip *cdesc = &descbase[0]; struct sgdma_descrip *ndesc = &descbase[1]; - unsigned int sts = ioread32(&csr->status); struct tse_buffer *rxbuffer = NULL; if (!sgdma_rxbusy(priv)) { rxbuffer = queue_rx_peekhead(priv); - if (rxbuffer == NULL) + if (rxbuffer == NULL) { + netdev_err(priv->dev, "no rx buffers available\n"); return 0; - - sgdma_descrip(cdesc, /* current descriptor */ - ndesc, /* next descriptor */ - sgdma_rxphysaddr(priv, ndesc), - 0, /* read addr 0 for rx dma */ - rxbuffer->dma_addr, /* write addr for rx dma */ - 0, /* read 'til EOP */ - 0, /* EOP: NA for rx dma */ - 0, /* read fixed: NA for rx dma */ - 0); /* SOP: NA for rx DMA */ - - /* clear control and status */ - iowrite32(0, &csr->control); - - /* If status available, clear those bits */ - if (sts & 0xf) - iowrite32(0xf, &csr->status); + } + + sgdma_setup_descrip(cdesc, /* current descriptor */ + ndesc, /* next descriptor */ + sgdma_rxphysaddr(priv, ndesc), + 0, /* read addr 0 for rx dma */ + rxbuffer->dma_addr, /* write addr for rx dma */ + 0, /* read 'til EOP */ + 0, /* EOP: NA for rx dma */ + 0, /* read fixed: NA for rx dma */ + 0); /* SOP: NA for rx DMA */ dma_sync_single_for_device(priv->device, priv->rxdescphys, - priv->rxdescmem, - DMA_BIDIRECTIONAL); + priv->sgdmadesclen, + DMA_TO_DEVICE); iowrite32(lower_32_bits(sgdma_rxphysaddr(priv, cdesc)), &csr->next_descrip); @@ -374,7 +407,7 @@ static int sgdma_async_write(struct altera_tse_private *priv, iowrite32(0x1f, &csr->status); dma_sync_single_for_device(priv->device, priv->txdescphys, - priv->txdescmem, DMA_TO_DEVICE); + priv->sgdmadesclen, DMA_TO_DEVICE); iowrite32(lower_32_bits(sgdma_txphysaddr(priv, desc)), &csr->next_descrip); diff --git a/drivers/net/ethernet/altera/altera_sgdma.h b/drivers/net/ethernet/altera/altera_sgdma.h index 07d471729dc4..584977e29ef9 100644 --- a/drivers/net/ethernet/altera/altera_sgdma.h +++ b/drivers/net/ethernet/altera/altera_sgdma.h @@ -26,10 +26,11 @@ void sgdma_clear_rxirq(struct altera_tse_private *); void sgdma_clear_txirq(struct altera_tse_private *); int sgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *); u32 sgdma_tx_completions(struct altera_tse_private *); -int sgdma_add_rx_desc(struct altera_tse_private *priv, struct tse_buffer *); +void sgdma_add_rx_desc(struct altera_tse_private *priv, struct tse_buffer *); void sgdma_status(struct altera_tse_private *); u32 sgdma_rx_status(struct altera_tse_private *); int sgdma_initialize(struct altera_tse_private *); void sgdma_uninitialize(struct altera_tse_private *); +void sgdma_start_rxdma(struct altera_tse_private *); #endif /* __ALTERA_SGDMA_H__ */ diff --git a/drivers/net/ethernet/altera/altera_tse.h b/drivers/net/ethernet/altera/altera_tse.h index 8feeed05de0e..465c4aabebbd 100644 --- a/drivers/net/ethernet/altera/altera_tse.h +++ b/drivers/net/ethernet/altera/altera_tse.h @@ -58,6 +58,8 @@ /* MAC function configuration default settings */ #define ALTERA_TSE_TX_IPG_LENGTH 12 +#define ALTERA_TSE_PAUSE_QUANTA 0xffff + #define GET_BIT_VALUE(v, bit) (((v) >> (bit)) & 0x1) /* MAC Command_Config Register Bit Definitions @@ -390,10 +392,11 @@ struct altera_dmaops { void (*clear_rxirq)(struct altera_tse_private *); int (*tx_buffer)(struct altera_tse_private *, struct tse_buffer *); u32 (*tx_completions)(struct altera_tse_private *); - int (*add_rx_desc)(struct altera_tse_private *, struct tse_buffer *); + void (*add_rx_desc)(struct altera_tse_private *, struct tse_buffer *); u32 (*get_rx_status)(struct altera_tse_private *); int (*init_dma)(struct altera_tse_private *); void (*uninit_dma)(struct altera_tse_private *); + void (*start_rxdma)(struct altera_tse_private *); }; /* This structure is private to each device. @@ -453,6 +456,7 @@ struct altera_tse_private { u32 rxctrlreg; dma_addr_t rxdescphys; dma_addr_t txdescphys; + size_t sgdmadesclen; struct list_head txlisthd; struct list_head rxlisthd; diff --git a/drivers/net/ethernet/altera/altera_tse_ethtool.c b/drivers/net/ethernet/altera/altera_tse_ethtool.c index 319ca74f5e74..76133caffa78 100644 --- a/drivers/net/ethernet/altera/altera_tse_ethtool.c +++ b/drivers/net/ethernet/altera/altera_tse_ethtool.c @@ -77,7 +77,7 @@ static void tse_get_drvinfo(struct net_device *dev, struct altera_tse_private *priv = netdev_priv(dev); u32 rev = ioread32(&priv->mac_dev->megacore_revision); - strcpy(info->driver, "Altera TSE MAC IP Driver"); + strcpy(info->driver, "altera_tse"); strcpy(info->version, "v8.0"); snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "v%d.%d", rev & 0xFFFF, (rev & 0xFFFF0000) >> 16); @@ -185,6 +185,12 @@ static void tse_get_regs(struct net_device *dev, struct ethtool_regs *regs, * how to do any special formatting of this data. * This version number will need to change if and * when this register table is changed. + * + * version[31:0] = 1: Dump the first 128 TSE Registers + * Upper bits are all 0 by default + * + * Upper 16-bits will indicate feature presence for + * Ethtool register decoding in future version. */ regs->version = 1; diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c index c70a29e0b9f7..e44a4aeb9701 100644 --- a/drivers/net/ethernet/altera/altera_tse_main.c +++ b/drivers/net/ethernet/altera/altera_tse_main.c @@ -224,6 +224,7 @@ static int tse_init_rx_buffer(struct altera_tse_private *priv, dev_kfree_skb_any(rxbuffer->skb); return -EINVAL; } + rxbuffer->dma_addr &= (dma_addr_t)~3; rxbuffer->len = len; return 0; } @@ -425,9 +426,10 @@ static int tse_rx(struct altera_tse_private *priv, int limit) priv->dev->stats.rx_bytes += pktlength; entry = next_entry; + + tse_rx_refill(priv); } - tse_rx_refill(priv); return count; } @@ -520,7 +522,6 @@ static irqreturn_t altera_isr(int irq, void *dev_id) struct altera_tse_private *priv; unsigned long int flags; - if (unlikely(!dev)) { pr_err("%s: invalid dev pointer\n", __func__); return IRQ_NONE; @@ -868,13 +869,13 @@ static int init_mac(struct altera_tse_private *priv) /* Disable RX/TX shift 16 for alignment of all received frames on 16-bit * start address */ - tse_clear_bit(&mac->rx_cmd_stat, ALTERA_TSE_RX_CMD_STAT_RX_SHIFT16); + tse_set_bit(&mac->rx_cmd_stat, ALTERA_TSE_RX_CMD_STAT_RX_SHIFT16); tse_clear_bit(&mac->tx_cmd_stat, ALTERA_TSE_TX_CMD_STAT_TX_SHIFT16 | ALTERA_TSE_TX_CMD_STAT_OMIT_CRC); /* Set the MAC options */ cmd = ioread32(&mac->command_config); - cmd |= MAC_CMDCFG_PAD_EN; /* Padding Removal on Receive */ + cmd &= ~MAC_CMDCFG_PAD_EN; /* No padding Removal on Receive */ cmd &= ~MAC_CMDCFG_CRC_FWD; /* CRC Removal */ cmd |= MAC_CMDCFG_RX_ERR_DISC; /* Automatically discard frames * with CRC errors @@ -882,8 +883,16 @@ static int init_mac(struct altera_tse_private *priv) cmd |= MAC_CMDCFG_CNTL_FRM_ENA; cmd &= ~MAC_CMDCFG_TX_ENA; cmd &= ~MAC_CMDCFG_RX_ENA; + + /* Default speed and duplex setting, full/100 */ + cmd &= ~MAC_CMDCFG_HD_ENA; + cmd &= ~MAC_CMDCFG_ETH_SPEED; + cmd &= ~MAC_CMDCFG_ENA_10; + iowrite32(cmd, &mac->command_config); + iowrite32(ALTERA_TSE_PAUSE_QUANTA, &mac->pause_quanta); + if (netif_msg_hw(priv)) dev_dbg(priv->device, "MAC post-initialization: CMD_CONFIG = 0x%08x\n", cmd); @@ -1085,17 +1094,19 @@ static int tse_open(struct net_device *dev) spin_unlock_irqrestore(&priv->rxdma_irq_lock, flags); - /* Start MAC Rx/Tx */ - spin_lock(&priv->mac_cfg_lock); - tse_set_mac(priv, true); - spin_unlock(&priv->mac_cfg_lock); - if (priv->phydev) phy_start(priv->phydev); napi_enable(&priv->napi); netif_start_queue(dev); + priv->dmaops->start_rxdma(priv); + + /* Start MAC Rx/Tx */ + spin_lock(&priv->mac_cfg_lock); + tse_set_mac(priv, true); + spin_unlock(&priv->mac_cfg_lock); + return 0; tx_request_irq_error: @@ -1167,7 +1178,6 @@ static struct net_device_ops altera_tse_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; - static int request_and_map(struct platform_device *pdev, const char *name, struct resource **res, void __iomem **ptr) { @@ -1235,7 +1245,7 @@ static int altera_tse_probe(struct platform_device *pdev) /* Get the mapped address to the SGDMA descriptor memory */ ret = request_and_map(pdev, "s1", &dma_res, &descmap); if (ret) - goto out_free; + goto err_free_netdev; /* Start of that memory is for transmit descriptors */ priv->tx_dma_desc = descmap; @@ -1254,24 +1264,24 @@ static int altera_tse_probe(struct platform_device *pdev) if (upper_32_bits(priv->rxdescmem_busaddr)) { dev_dbg(priv->device, "SGDMA bus addresses greater than 32-bits\n"); - goto out_free; + goto err_free_netdev; } if (upper_32_bits(priv->txdescmem_busaddr)) { dev_dbg(priv->device, "SGDMA bus addresses greater than 32-bits\n"); - goto out_free; + goto err_free_netdev; } } else if (priv->dmaops && priv->dmaops->altera_dtype == ALTERA_DTYPE_MSGDMA) { ret = request_and_map(pdev, "rx_resp", &dma_res, &priv->rx_dma_resp); if (ret) - goto out_free; + goto err_free_netdev; ret = request_and_map(pdev, "tx_desc", &dma_res, &priv->tx_dma_desc); if (ret) - goto out_free; + goto err_free_netdev; priv->txdescmem = resource_size(dma_res); priv->txdescmem_busaddr = dma_res->start; @@ -1279,13 +1289,13 @@ static int altera_tse_probe(struct platform_device *pdev) ret = request_and_map(pdev, "rx_desc", &dma_res, &priv->rx_dma_desc); if (ret) - goto out_free; + goto err_free_netdev; priv->rxdescmem = resource_size(dma_res); priv->rxdescmem_busaddr = dma_res->start; } else { - goto out_free; + goto err_free_netdev; } if (!dma_set_mask(priv->device, DMA_BIT_MASK(priv->dmaops->dmamask))) @@ -1294,26 +1304,26 @@ static int altera_tse_probe(struct platform_device *pdev) else if (!dma_set_mask(priv->device, DMA_BIT_MASK(32))) dma_set_coherent_mask(priv->device, DMA_BIT_MASK(32)); else - goto out_free; + goto err_free_netdev; /* MAC address space */ ret = request_and_map(pdev, "control_port", &control_port, (void __iomem **)&priv->mac_dev); if (ret) - goto out_free; + goto err_free_netdev; /* xSGDMA Rx Dispatcher address space */ ret = request_and_map(pdev, "rx_csr", &dma_res, &priv->rx_dma_csr); if (ret) - goto out_free; + goto err_free_netdev; /* xSGDMA Tx Dispatcher address space */ ret = request_and_map(pdev, "tx_csr", &dma_res, &priv->tx_dma_csr); if (ret) - goto out_free; + goto err_free_netdev; /* Rx IRQ */ @@ -1321,7 +1331,7 @@ static int altera_tse_probe(struct platform_device *pdev) if (priv->rx_irq == -ENXIO) { dev_err(&pdev->dev, "cannot obtain Rx IRQ\n"); ret = -ENXIO; - goto out_free; + goto err_free_netdev; } /* Tx IRQ */ @@ -1329,7 +1339,7 @@ static int altera_tse_probe(struct platform_device *pdev) if (priv->tx_irq == -ENXIO) { dev_err(&pdev->dev, "cannot obtain Tx IRQ\n"); ret = -ENXIO; - goto out_free; + goto err_free_netdev; } /* get FIFO depths from device tree */ @@ -1337,14 +1347,14 @@ static int altera_tse_probe(struct platform_device *pdev) &priv->rx_fifo_depth)) { dev_err(&pdev->dev, "cannot obtain rx-fifo-depth\n"); ret = -ENXIO; - goto out_free; + goto err_free_netdev; } if (of_property_read_u32(pdev->dev.of_node, "tx-fifo-depth", &priv->rx_fifo_depth)) { dev_err(&pdev->dev, "cannot obtain tx-fifo-depth\n"); ret = -ENXIO; - goto out_free; + goto err_free_netdev; } /* get hash filter settings for this instance */ @@ -1393,7 +1403,7 @@ static int altera_tse_probe(struct platform_device *pdev) ((priv->phy_addr >= 0) && (priv->phy_addr < PHY_MAX_ADDR)))) { dev_err(&pdev->dev, "invalid phy-addr specified %d\n", priv->phy_addr); - goto out_free; + goto err_free_netdev; } /* Create/attach to MDIO bus */ @@ -1401,7 +1411,7 @@ static int altera_tse_probe(struct platform_device *pdev) atomic_add_return(1, &instance_count)); if (ret) - goto out_free; + goto err_free_netdev; /* initialize netdev */ ether_setup(ndev); @@ -1438,7 +1448,7 @@ static int altera_tse_probe(struct platform_device *pdev) ret = register_netdev(ndev); if (ret) { dev_err(&pdev->dev, "failed to register TSE net device\n"); - goto out_free_mdio; + goto err_register_netdev; } platform_set_drvdata(pdev, ndev); @@ -1455,13 +1465,16 @@ static int altera_tse_probe(struct platform_device *pdev) ret = init_phy(ndev); if (ret != 0) { netdev_err(ndev, "Cannot attach to PHY (error: %d)\n", ret); - goto out_free_mdio; + goto err_init_phy; } return 0; -out_free_mdio: +err_init_phy: + unregister_netdev(ndev); +err_register_netdev: + netif_napi_del(&priv->napi); altera_tse_mdio_destroy(ndev); -out_free: +err_free_netdev: free_netdev(ndev); return ret; } @@ -1496,6 +1509,7 @@ struct altera_dmaops altera_dtype_sgdma = { .get_rx_status = sgdma_rx_status, .init_dma = sgdma_initialize, .uninit_dma = sgdma_uninitialize, + .start_rxdma = sgdma_start_rxdma, }; struct altera_dmaops altera_dtype_msgdma = { @@ -1514,6 +1528,7 @@ struct altera_dmaops altera_dtype_msgdma = { .get_rx_status = msgdma_rx_status, .init_dma = msgdma_initialize, .uninit_dma = msgdma_uninitialize, + .start_rxdma = msgdma_start_rxdma, }; static struct of_device_id altera_tse_ids[] = { diff --git a/drivers/net/ethernet/arc/emac.h b/drivers/net/ethernet/arc/emac.h index 928fac6dd10a..53f85bf71526 100644 --- a/drivers/net/ethernet/arc/emac.h +++ b/drivers/net/ethernet/arc/emac.h @@ -11,6 +11,7 @@ #include <linux/dma-mapping.h> #include <linux/netdevice.h> #include <linux/phy.h> +#include <linux/clk.h> /* STATUS and ENABLE Register bit masks */ #define TXINT_MASK (1<<0) /* Transmit interrupt */ @@ -131,6 +132,7 @@ struct arc_emac_priv { struct mii_bus *bus; void __iomem *regs; + struct clk *clk; struct napi_struct napi; struct net_device_stats stats; diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c index eeecc29cf5b7..d647a7d115ac 100644 --- a/drivers/net/ethernet/arc/emac_main.c +++ b/drivers/net/ethernet/arc/emac_main.c @@ -574,6 +574,18 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev) return NETDEV_TX_OK; } +static void arc_emac_set_address_internal(struct net_device *ndev) +{ + struct arc_emac_priv *priv = netdev_priv(ndev); + unsigned int addr_low, addr_hi; + + addr_low = le32_to_cpu(*(__le32 *) &ndev->dev_addr[0]); + addr_hi = le16_to_cpu(*(__le16 *) &ndev->dev_addr[4]); + + arc_reg_set(priv, R_ADDRL, addr_low); + arc_reg_set(priv, R_ADDRH, addr_hi); +} + /** * arc_emac_set_address - Set the MAC address for this device. * @ndev: Pointer to net_device structure. @@ -587,9 +599,7 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev) */ static int arc_emac_set_address(struct net_device *ndev, void *p) { - struct arc_emac_priv *priv = netdev_priv(ndev); struct sockaddr *addr = p; - unsigned int addr_low, addr_hi; if (netif_running(ndev)) return -EBUSY; @@ -599,11 +609,7 @@ static int arc_emac_set_address(struct net_device *ndev, void *p) memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len); - addr_low = le32_to_cpu(*(__le32 *) &ndev->dev_addr[0]); - addr_hi = le16_to_cpu(*(__le16 *) &ndev->dev_addr[4]); - - arc_reg_set(priv, R_ADDRL, addr_low); - arc_reg_set(priv, R_ADDRH, addr_hi); + arc_emac_set_address_internal(ndev); return 0; } @@ -643,13 +649,6 @@ static int arc_emac_probe(struct platform_device *pdev) return -ENODEV; } - /* Get CPU clock frequency from device tree */ - if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", - &clock_frequency)) { - dev_err(&pdev->dev, "failed to retrieve <clock-frequency> from device tree\n"); - return -EINVAL; - } - /* Get IRQ from device tree */ irq = irq_of_parse_and_map(pdev->dev.of_node, 0); if (!irq) { @@ -677,17 +676,36 @@ static int arc_emac_probe(struct platform_device *pdev) priv->regs = devm_ioremap_resource(&pdev->dev, &res_regs); if (IS_ERR(priv->regs)) { err = PTR_ERR(priv->regs); - goto out; + goto out_netdev; } dev_dbg(&pdev->dev, "Registers base address is 0x%p\n", priv->regs); + priv->clk = of_clk_get(pdev->dev.of_node, 0); + if (IS_ERR(priv->clk)) { + /* Get CPU clock frequency from device tree */ + if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", + &clock_frequency)) { + dev_err(&pdev->dev, "failed to retrieve <clock-frequency> from device tree\n"); + err = -EINVAL; + goto out_netdev; + } + } else { + err = clk_prepare_enable(priv->clk); + if (err) { + dev_err(&pdev->dev, "failed to enable clock\n"); + goto out_clkget; + } + + clock_frequency = clk_get_rate(priv->clk); + } + id = arc_reg_get(priv, R_ID); /* Check for EMAC revision 5 or 7, magic number */ if (!(id == 0x0005fd02 || id == 0x0007fd02)) { dev_err(&pdev->dev, "ARC EMAC not detected, id=0x%x\n", id); err = -ENODEV; - goto out; + goto out_clken; } dev_info(&pdev->dev, "ARC EMAC detected with id: 0x%x\n", id); @@ -702,7 +720,7 @@ static int arc_emac_probe(struct platform_device *pdev) ndev->name, ndev); if (err) { dev_err(&pdev->dev, "could not allocate IRQ\n"); - goto out; + goto out_clken; } /* Get MAC address from device tree */ @@ -713,6 +731,7 @@ static int arc_emac_probe(struct platform_device *pdev) else eth_hw_addr_random(ndev); + arc_emac_set_address_internal(ndev); dev_info(&pdev->dev, "MAC address is now %pM\n", ndev->dev_addr); /* Do 1 allocation instead of 2 separate ones for Rx and Tx BD rings */ @@ -722,7 +741,7 @@ static int arc_emac_probe(struct platform_device *pdev) if (!priv->rxbd) { dev_err(&pdev->dev, "failed to allocate data buffers\n"); err = -ENOMEM; - goto out; + goto out_clken; } priv->txbd = priv->rxbd + RX_BD_NUM; @@ -734,7 +753,7 @@ static int arc_emac_probe(struct platform_device *pdev) err = arc_mdio_probe(pdev, priv); if (err) { dev_err(&pdev->dev, "failed to probe MII bus\n"); - goto out; + goto out_clken; } priv->phy_dev = of_phy_connect(ndev, phy_node, arc_emac_adjust_link, 0, @@ -742,7 +761,7 @@ static int arc_emac_probe(struct platform_device *pdev) if (!priv->phy_dev) { dev_err(&pdev->dev, "of_phy_connect() failed\n"); err = -ENODEV; - goto out; + goto out_mdio; } dev_info(&pdev->dev, "connected to %s phy with id 0x%x\n", @@ -752,14 +771,25 @@ static int arc_emac_probe(struct platform_device *pdev) err = register_netdev(ndev); if (err) { - netif_napi_del(&priv->napi); dev_err(&pdev->dev, "failed to register network device\n"); - goto out; + goto out_netif_api; } return 0; -out: +out_netif_api: + netif_napi_del(&priv->napi); + phy_disconnect(priv->phy_dev); + priv->phy_dev = NULL; +out_mdio: + arc_mdio_remove(priv); +out_clken: + if (!IS_ERR(priv->clk)) + clk_disable_unprepare(priv->clk); +out_clkget: + if (!IS_ERR(priv->clk)) + clk_put(priv->clk); +out_netdev: free_netdev(ndev); return err; } @@ -774,6 +804,12 @@ static int arc_emac_remove(struct platform_device *pdev) arc_mdio_remove(priv); unregister_netdev(ndev); netif_napi_del(&priv->napi); + + if (!IS_ERR(priv->clk)) { + clk_disable_unprepare(priv->clk); + clk_put(priv->clk); + } + free_netdev(ndev); return 0; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index a78edaccceee..b260913db236 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -13233,6 +13233,8 @@ static void __bnx2x_remove(struct pci_dev *pdev, iounmap(bp->doorbells); bnx2x_release_firmware(bp); + } else { + bnx2x_vf_pci_dealloc(bp); } bnx2x_free_mem_bp(bp); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index 5c523b32db70..81cc2d9831c2 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -427,7 +427,9 @@ static int bnx2x_vf_mac_vlan_config(struct bnx2x *bp, if (filter->add && filter->type == BNX2X_VF_FILTER_VLAN && (atomic_read(&bnx2x_vfq(vf, qid, vlan_count)) >= vf_vlan_rules_cnt(vf))) { - BNX2X_ERR("No credits for vlan\n"); + BNX2X_ERR("No credits for vlan [%d >= %d]\n", + atomic_read(&bnx2x_vfq(vf, qid, vlan_count)), + vf_vlan_rules_cnt(vf)); return -ENOMEM; } @@ -610,6 +612,7 @@ int bnx2x_vf_mcast(struct bnx2x *bp, struct bnx2x_virtf *vf, } /* add new mcasts */ + mcast.mcast_list_len = mc_num; rc = bnx2x_config_mcast(bp, &mcast, BNX2X_MCAST_CMD_ADD); if (rc) BNX2X_ERR("Faled to add multicasts\n"); @@ -837,6 +840,29 @@ int bnx2x_vf_flr_clnup_epilog(struct bnx2x *bp, u8 abs_vfid) return 0; } +static void bnx2x_iov_re_set_vlan_filters(struct bnx2x *bp, + struct bnx2x_virtf *vf, + int new) +{ + int num = vf_vlan_rules_cnt(vf); + int diff = new - num; + bool rc = true; + + DP(BNX2X_MSG_IOV, "vf[%d] - %d vlan filter credits [previously %d]\n", + vf->abs_vfid, new, num); + + if (diff > 0) + rc = bp->vlans_pool.get(&bp->vlans_pool, diff); + else if (diff < 0) + rc = bp->vlans_pool.put(&bp->vlans_pool, -diff); + + if (rc) + vf_vlan_rules_cnt(vf) = new; + else + DP(BNX2X_MSG_IOV, "vf[%d] - Failed to configure vlan filter credits change\n", + vf->abs_vfid); +} + /* must be called after the number of PF queues and the number of VFs are * both known */ @@ -854,9 +880,11 @@ bnx2x_iov_static_resc(struct bnx2x *bp, struct bnx2x_virtf *vf) resc->num_mac_filters = 1; /* divvy up vlan rules */ + bnx2x_iov_re_set_vlan_filters(bp, vf, 0); vlan_count = bp->vlans_pool.check(&bp->vlans_pool); vlan_count = 1 << ilog2(vlan_count); - resc->num_vlan_filters = vlan_count / BNX2X_NR_VIRTFN(bp); + bnx2x_iov_re_set_vlan_filters(bp, vf, + vlan_count / BNX2X_NR_VIRTFN(bp)); /* no real limitation */ resc->num_mc_filters = 0; @@ -1478,10 +1506,6 @@ int bnx2x_iov_nic_init(struct bnx2x *bp) bnx2x_iov_static_resc(bp, vf); /* queues are initialized during VF-ACQUIRE */ - - /* reserve the vf vlan credit */ - bp->vlans_pool.get(&bp->vlans_pool, vf_vlan_rules_cnt(vf)); - vf->filter_state = 0; vf->sp_cl_id = bnx2x_fp(bp, 0, cl_id); @@ -1912,11 +1936,12 @@ int bnx2x_vf_chk_avail_resc(struct bnx2x *bp, struct bnx2x_virtf *vf, u8 rxq_cnt = vf_rxq_count(vf) ? : bnx2x_vf_max_queue_cnt(bp, vf); u8 txq_cnt = vf_txq_count(vf) ? : bnx2x_vf_max_queue_cnt(bp, vf); + /* Save a vlan filter for the Hypervisor */ return ((req_resc->num_rxqs <= rxq_cnt) && (req_resc->num_txqs <= txq_cnt) && (req_resc->num_sbs <= vf_sb_count(vf)) && (req_resc->num_mac_filters <= vf_mac_rules_cnt(vf)) && - (req_resc->num_vlan_filters <= vf_vlan_rules_cnt(vf))); + (req_resc->num_vlan_filters <= vf_vlan_rules_visible_cnt(vf))); } /* CORE VF API */ @@ -1972,14 +1997,14 @@ int bnx2x_vf_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf, vf_txq_count(vf) = resc->num_txqs ? : bnx2x_vf_max_queue_cnt(bp, vf); if (resc->num_mac_filters) vf_mac_rules_cnt(vf) = resc->num_mac_filters; - if (resc->num_vlan_filters) - vf_vlan_rules_cnt(vf) = resc->num_vlan_filters; + /* Add an additional vlan filter credit for the hypervisor */ + bnx2x_iov_re_set_vlan_filters(bp, vf, resc->num_vlan_filters + 1); DP(BNX2X_MSG_IOV, "Fulfilling vf request: sb count %d, tx_count %d, rx_count %d, mac_rules_count %d, vlan_rules_count %d\n", vf_sb_count(vf), vf_rxq_count(vf), vf_txq_count(vf), vf_mac_rules_cnt(vf), - vf_vlan_rules_cnt(vf)); + vf_vlan_rules_visible_cnt(vf)); /* Initialize the queues */ if (!vf->vfqs) { @@ -2896,6 +2921,14 @@ void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp) return bp->regview + PXP_VF_ADDR_DB_START; } +void bnx2x_vf_pci_dealloc(struct bnx2x *bp) +{ + BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->vf2pf_mbox_mapping, + sizeof(struct bnx2x_vf_mbx_msg)); + BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->pf2vf_bulletin_mapping, + sizeof(union pf_vf_bulletin)); +} + int bnx2x_vf_pci_alloc(struct bnx2x *bp) { mutex_init(&bp->vf2pf_mutex); @@ -2915,10 +2948,7 @@ int bnx2x_vf_pci_alloc(struct bnx2x *bp) return 0; alloc_mem_err: - BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->vf2pf_mbox_mapping, - sizeof(struct bnx2x_vf_mbx_msg)); - BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->pf2vf_bulletin_mapping, - sizeof(union pf_vf_bulletin)); + bnx2x_vf_pci_dealloc(bp); return -ENOMEM; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index 8bf764570eef..6929adba52f9 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h @@ -159,6 +159,8 @@ struct bnx2x_virtf { #define vf_mac_rules_cnt(vf) ((vf)->alloc_resc.num_mac_filters) #define vf_vlan_rules_cnt(vf) ((vf)->alloc_resc.num_vlan_filters) #define vf_mc_rules_cnt(vf) ((vf)->alloc_resc.num_mc_filters) + /* Hide a single vlan filter credit for the hypervisor */ +#define vf_vlan_rules_visible_cnt(vf) (vf_vlan_rules_cnt(vf) - 1) u8 sb_count; /* actual number of SBs */ u8 igu_base_id; /* base igu status block id */ @@ -502,6 +504,7 @@ static inline int bnx2x_vf_ustorm_prods_offset(struct bnx2x *bp, enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp); void bnx2x_timer_sriov(struct bnx2x *bp); void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp); +void bnx2x_vf_pci_dealloc(struct bnx2x *bp); int bnx2x_vf_pci_alloc(struct bnx2x *bp); int bnx2x_enable_sriov(struct bnx2x *bp); void bnx2x_disable_sriov(struct bnx2x *bp); @@ -568,6 +571,7 @@ static inline void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp) return NULL; } +static inline void bnx2x_vf_pci_dealloc(struct bnx2 *bp) {return 0; } static inline int bnx2x_vf_pci_alloc(struct bnx2x *bp) {return 0; } static inline void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp) {} static inline int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs) {return 0; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c index 0622884596b2..0c067e8564dd 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c @@ -1163,7 +1163,7 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf, bnx2x_vf_max_queue_cnt(bp, vf); resc->num_sbs = vf_sb_count(vf); resc->num_mac_filters = vf_mac_rules_cnt(vf); - resc->num_vlan_filters = vf_vlan_rules_cnt(vf); + resc->num_vlan_filters = vf_vlan_rules_visible_cnt(vf); resc->num_mc_filters = 0; if (status == PFVF_STATUS_SUCCESS) { diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig index 7e49c43b7af3..9e089d24466e 100644 --- a/drivers/net/ethernet/cadence/Kconfig +++ b/drivers/net/ethernet/cadence/Kconfig @@ -4,7 +4,7 @@ config NET_CADENCE bool "Cadence devices" - depends on HAS_IOMEM && (ARM || AVR32 || COMPILE_TEST) + depends on HAS_IOMEM && (ARM || AVR32 || MICROBLAZE || COMPILE_TEST) default y ---help--- If you have a network (Ethernet) card belonging to this class, say Y. @@ -30,7 +30,7 @@ config ARM_AT91_ETHER config MACB tristate "Cadence MACB/GEM support" - depends on HAS_DMA && (PLATFORM_AT32AP || ARCH_AT91 || ARCH_PICOXCELL || ARCH_ZYNQ || COMPILE_TEST) + depends on HAS_DMA && (PLATFORM_AT32AP || ARCH_AT91 || ARCH_PICOXCELL || ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST) select PHYLIB ---help--- The Cadence MACB ethernet interface is found on many Atmel AT32 and diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index ca97005e24b4..e9daa072ebb4 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -599,25 +599,16 @@ static void gem_rx_refill(struct macb *bp) { unsigned int entry; struct sk_buff *skb; - struct macb_dma_desc *desc; dma_addr_t paddr; while (CIRC_SPACE(bp->rx_prepared_head, bp->rx_tail, RX_RING_SIZE) > 0) { - u32 addr, ctrl; - entry = macb_rx_ring_wrap(bp->rx_prepared_head); - desc = &bp->rx_ring[entry]; /* Make hw descriptor updates visible to CPU */ rmb(); - addr = desc->addr; - ctrl = desc->ctrl; bp->rx_prepared_head++; - if ((addr & MACB_BIT(RX_USED))) - continue; - if (bp->rx_skbuff[entry] == NULL) { /* allocate sk_buff for this free entry in ring */ skb = netdev_alloc_skb(bp->dev, bp->rx_buffer_size); @@ -698,7 +689,6 @@ static int gem_rx(struct macb *bp, int budget) if (!(addr & MACB_BIT(RX_USED))) break; - desc->addr &= ~MACB_BIT(RX_USED); bp->rx_tail++; count++; @@ -891,16 +881,15 @@ static int macb_poll(struct napi_struct *napi, int budget) if (work_done < budget) { napi_complete(napi); - /* - * We've done what we can to clean the buffers. Make sure we - * get notified when new packets arrive. - */ - macb_writel(bp, IER, MACB_RX_INT_FLAGS); - /* Packets received while interrupts were disabled */ status = macb_readl(bp, RSR); - if (unlikely(status)) + if (status) { + if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) + macb_writel(bp, ISR, MACB_BIT(RCOMP)); napi_reschedule(napi); + } else { + macb_writel(bp, IER, MACB_RX_INT_FLAGS); + } } /* TODO: Handle errors */ @@ -951,6 +940,10 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) if (unlikely(status & (MACB_TX_ERR_FLAGS))) { macb_writel(bp, IDR, MACB_TX_INT_FLAGS); schedule_work(&bp->tx_error_task); + + if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) + macb_writel(bp, ISR, MACB_TX_ERR_FLAGS); + break; } @@ -968,6 +961,9 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) bp->hw_stats.gem.rx_overruns++; else bp->hw_stats.macb.rx_overruns++; + + if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) + macb_writel(bp, ISR, MACB_BIT(ISR_ROVR)); } if (status & MACB_BIT(HRESP)) { @@ -977,6 +973,9 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) * (work queue?) */ netdev_err(dev, "DMA bus error: HRESP not OK\n"); + + if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) + macb_writel(bp, ISR, MACB_BIT(HRESP)); } status = macb_readl(bp, ISR); @@ -1113,7 +1112,7 @@ static void gem_free_rx_buffers(struct macb *bp) desc = &bp->rx_ring[i]; addr = MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr)); - dma_unmap_single(&bp->pdev->dev, addr, skb->len, + dma_unmap_single(&bp->pdev->dev, addr, bp->rx_buffer_size, DMA_FROM_DEVICE); dev_kfree_skb_any(skb); skb = NULL; diff --git a/drivers/net/ethernet/chelsio/Kconfig b/drivers/net/ethernet/chelsio/Kconfig index d40c994a4f6a..570222c33410 100644 --- a/drivers/net/ethernet/chelsio/Kconfig +++ b/drivers/net/ethernet/chelsio/Kconfig @@ -67,13 +67,13 @@ config CHELSIO_T3 will be called cxgb3. config CHELSIO_T4 - tristate "Chelsio Communications T4 Ethernet support" + tristate "Chelsio Communications T4/T5 Ethernet support" depends on PCI select FW_LOADER select MDIO ---help--- - This driver supports Chelsio T4-based gigabit and 10Gb Ethernet - adapters. + This driver supports Chelsio T4 and T5 based gigabit, 10Gb Ethernet + adapter and T5 based 40Gb Ethernet adapter. For general information about Chelsio and our products, visit our website at <http://www.chelsio.com>. @@ -87,11 +87,12 @@ config CHELSIO_T4 will be called cxgb4. config CHELSIO_T4VF - tristate "Chelsio Communications T4 Virtual Function Ethernet support" + tristate "Chelsio Communications T4/T5 Virtual Function Ethernet support" depends on PCI ---help--- - This driver supports Chelsio T4-based gigabit and 10Gb Ethernet - adapters with PCI-E SR-IOV Virtual Functions. + This driver supports Chelsio T4 and T5 based gigabit, 10Gb Ethernet + adapters and T5 based 40Gb Ethernet adapters with PCI-E SR-IOV Virtual + Functions. For general information about Chelsio and our products, visit our website at <http://www.chelsio.com>. diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 6fe58913403a..24e16e3301e0 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -5870,6 +5870,8 @@ static void print_port_info(const struct net_device *dev) spd = " 2.5 GT/s"; else if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_5_0GB) spd = " 5 GT/s"; + else if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_8_0GB) + spd = " 8 GT/s"; if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_100M) bufp += sprintf(bufp, "100/"); diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 9125d9abf099..e2d42475b006 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -121,6 +121,7 @@ static irqreturn_t gfar_error(int irq, void *dev_id); static irqreturn_t gfar_transmit(int irq, void *dev_id); static irqreturn_t gfar_interrupt(int irq, void *dev_id); static void adjust_link(struct net_device *dev); +static noinline void gfar_update_link_state(struct gfar_private *priv); static int init_phy(struct net_device *dev); static int gfar_probe(struct platform_device *ofdev); static int gfar_remove(struct platform_device *ofdev); @@ -3076,41 +3077,6 @@ static irqreturn_t gfar_interrupt(int irq, void *grp_id) return IRQ_HANDLED; } -static u32 gfar_get_flowctrl_cfg(struct gfar_private *priv) -{ - struct phy_device *phydev = priv->phydev; - u32 val = 0; - - if (!phydev->duplex) - return val; - - if (!priv->pause_aneg_en) { - if (priv->tx_pause_en) - val |= MACCFG1_TX_FLOW; - if (priv->rx_pause_en) - val |= MACCFG1_RX_FLOW; - } else { - u16 lcl_adv, rmt_adv; - u8 flowctrl; - /* get link partner capabilities */ - rmt_adv = 0; - if (phydev->pause) - rmt_adv = LPA_PAUSE_CAP; - if (phydev->asym_pause) - rmt_adv |= LPA_PAUSE_ASYM; - - lcl_adv = mii_advertise_flowctrl(phydev->advertising); - - flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv); - if (flowctrl & FLOW_CTRL_TX) - val |= MACCFG1_TX_FLOW; - if (flowctrl & FLOW_CTRL_RX) - val |= MACCFG1_RX_FLOW; - } - - return val; -} - /* Called every time the controller might need to be made * aware of new link state. The PHY code conveys this * information through variables in the phydev structure, and this @@ -3120,83 +3086,12 @@ static u32 gfar_get_flowctrl_cfg(struct gfar_private *priv) static void adjust_link(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); - struct gfar __iomem *regs = priv->gfargrp[0].regs; struct phy_device *phydev = priv->phydev; - int new_state = 0; - if (test_bit(GFAR_RESETTING, &priv->state)) - return; - - if (phydev->link) { - u32 tempval1 = gfar_read(®s->maccfg1); - u32 tempval = gfar_read(®s->maccfg2); - u32 ecntrl = gfar_read(®s->ecntrl); - - /* Now we make sure that we can be in full duplex mode. - * If not, we operate in half-duplex mode. - */ - if (phydev->duplex != priv->oldduplex) { - new_state = 1; - if (!(phydev->duplex)) - tempval &= ~(MACCFG2_FULL_DUPLEX); - else - tempval |= MACCFG2_FULL_DUPLEX; - - priv->oldduplex = phydev->duplex; - } - - if (phydev->speed != priv->oldspeed) { - new_state = 1; - switch (phydev->speed) { - case 1000: - tempval = - ((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII); - - ecntrl &= ~(ECNTRL_R100); - break; - case 100: - case 10: - tempval = - ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII); - - /* Reduced mode distinguishes - * between 10 and 100 - */ - if (phydev->speed == SPEED_100) - ecntrl |= ECNTRL_R100; - else - ecntrl &= ~(ECNTRL_R100); - break; - default: - netif_warn(priv, link, dev, - "Ack! Speed (%d) is not 10/100/1000!\n", - phydev->speed); - break; - } - - priv->oldspeed = phydev->speed; - } - - tempval1 &= ~(MACCFG1_TX_FLOW | MACCFG1_RX_FLOW); - tempval1 |= gfar_get_flowctrl_cfg(priv); - - gfar_write(®s->maccfg1, tempval1); - gfar_write(®s->maccfg2, tempval); - gfar_write(®s->ecntrl, ecntrl); - - if (!priv->oldlink) { - new_state = 1; - priv->oldlink = 1; - } - } else if (priv->oldlink) { - new_state = 1; - priv->oldlink = 0; - priv->oldspeed = 0; - priv->oldduplex = -1; - } - - if (new_state && netif_msg_link(priv)) - phy_print_status(phydev); + if (unlikely(phydev->link != priv->oldlink || + phydev->duplex != priv->oldduplex || + phydev->speed != priv->oldspeed)) + gfar_update_link_state(priv); } /* Update the hash table based on the current list of multicast @@ -3442,6 +3337,114 @@ static irqreturn_t gfar_error(int irq, void *grp_id) return IRQ_HANDLED; } +static u32 gfar_get_flowctrl_cfg(struct gfar_private *priv) +{ + struct phy_device *phydev = priv->phydev; + u32 val = 0; + + if (!phydev->duplex) + return val; + + if (!priv->pause_aneg_en) { + if (priv->tx_pause_en) + val |= MACCFG1_TX_FLOW; + if (priv->rx_pause_en) + val |= MACCFG1_RX_FLOW; + } else { + u16 lcl_adv, rmt_adv; + u8 flowctrl; + /* get link partner capabilities */ + rmt_adv = 0; + if (phydev->pause) + rmt_adv = LPA_PAUSE_CAP; + if (phydev->asym_pause) + rmt_adv |= LPA_PAUSE_ASYM; + + lcl_adv = mii_advertise_flowctrl(phydev->advertising); + + flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv); + if (flowctrl & FLOW_CTRL_TX) + val |= MACCFG1_TX_FLOW; + if (flowctrl & FLOW_CTRL_RX) + val |= MACCFG1_RX_FLOW; + } + + return val; +} + +static noinline void gfar_update_link_state(struct gfar_private *priv) +{ + struct gfar __iomem *regs = priv->gfargrp[0].regs; + struct phy_device *phydev = priv->phydev; + + if (unlikely(test_bit(GFAR_RESETTING, &priv->state))) + return; + + if (phydev->link) { + u32 tempval1 = gfar_read(®s->maccfg1); + u32 tempval = gfar_read(®s->maccfg2); + u32 ecntrl = gfar_read(®s->ecntrl); + + if (phydev->duplex != priv->oldduplex) { + if (!(phydev->duplex)) + tempval &= ~(MACCFG2_FULL_DUPLEX); + else + tempval |= MACCFG2_FULL_DUPLEX; + + priv->oldduplex = phydev->duplex; + } + + if (phydev->speed != priv->oldspeed) { + switch (phydev->speed) { + case 1000: + tempval = + ((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII); + + ecntrl &= ~(ECNTRL_R100); + break; + case 100: + case 10: + tempval = + ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII); + + /* Reduced mode distinguishes + * between 10 and 100 + */ + if (phydev->speed == SPEED_100) + ecntrl |= ECNTRL_R100; + else + ecntrl &= ~(ECNTRL_R100); + break; + default: + netif_warn(priv, link, priv->ndev, + "Ack! Speed (%d) is not 10/100/1000!\n", + phydev->speed); + break; + } + + priv->oldspeed = phydev->speed; + } + + tempval1 &= ~(MACCFG1_TX_FLOW | MACCFG1_RX_FLOW); + tempval1 |= gfar_get_flowctrl_cfg(priv); + + gfar_write(®s->maccfg1, tempval1); + gfar_write(®s->maccfg2, tempval); + gfar_write(®s->ecntrl, ecntrl); + + if (!priv->oldlink) + priv->oldlink = 1; + + } else if (priv->oldlink) { + priv->oldlink = 0; + priv->oldspeed = 0; + priv->oldduplex = -1; + } + + if (netif_msg_link(priv)) + phy_print_status(phydev); +} + static struct of_device_id gfar_match[] = { { diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c index 891dbee6e6c1..76d70708f864 100644 --- a/drivers/net/ethernet/freescale/gianfar_ethtool.c +++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c @@ -533,6 +533,9 @@ static int gfar_spauseparam(struct net_device *dev, struct gfar __iomem *regs = priv->gfargrp[0].regs; u32 oldadv, newadv; + if (!phydev) + return -ENODEV; + if (!(phydev->supported & SUPPORTED_Pause) || (!(phydev->supported & SUPPORTED_Asym_Pause) && (epause->rx_pause != epause->tx_pause))) diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index 9866f264f55e..f0bbd4246d71 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -186,7 +186,7 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw) { u16 phy_reg = 0; u32 phy_id = 0; - s32 ret_val; + s32 ret_val = 0; u16 retry_count; u32 mac_reg = 0; @@ -217,11 +217,13 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw) /* In case the PHY needs to be in mdio slow mode, * set slow mode and try to get the PHY id again. */ - hw->phy.ops.release(hw); - ret_val = e1000_set_mdio_slow_mode_hv(hw); - if (!ret_val) - ret_val = e1000e_get_phy_id(hw); - hw->phy.ops.acquire(hw); + if (hw->mac.type < e1000_pch_lpt) { + hw->phy.ops.release(hw); + ret_val = e1000_set_mdio_slow_mode_hv(hw); + if (!ret_val) + ret_val = e1000e_get_phy_id(hw); + hw->phy.ops.acquire(hw); + } if (ret_val) return false; @@ -842,6 +844,17 @@ s32 e1000_set_eee_pchlan(struct e1000_hw *hw) } } + if (hw->phy.type == e1000_phy_82579) { + ret_val = e1000_read_emi_reg_locked(hw, I82579_LPI_PLL_SHUT, + &data); + if (ret_val) + goto release; + + data &= ~I82579_LPI_100_PLL_SHUT; + ret_val = e1000_write_emi_reg_locked(hw, I82579_LPI_PLL_SHUT, + data); + } + /* R/Clr IEEE MMD 3.1 bits 11:10 - Tx/Rx LPI Received */ ret_val = e1000_read_emi_reg_locked(hw, pcs_status, &data); if (ret_val) @@ -1314,14 +1327,17 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) return ret_val; } - /* When connected at 10Mbps half-duplex, 82579 parts are excessively + /* When connected at 10Mbps half-duplex, some parts are excessively * aggressive resulting in many collisions. To avoid this, increase * the IPG and reduce Rx latency in the PHY. */ - if ((hw->mac.type == e1000_pch2lan) && link) { + if (((hw->mac.type == e1000_pch2lan) || + (hw->mac.type == e1000_pch_lpt)) && link) { u32 reg; reg = er32(STATUS); if (!(reg & (E1000_STATUS_FD | E1000_STATUS_SPEED_MASK))) { + u16 emi_addr; + reg = er32(TIPG); reg &= ~E1000_TIPG_IPGT_MASK; reg |= 0xFF; @@ -1332,8 +1348,12 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) if (ret_val) return ret_val; - ret_val = - e1000_write_emi_reg_locked(hw, I82579_RX_CONFIG, 0); + if (hw->mac.type == e1000_pch2lan) + emi_addr = I82579_RX_CONFIG; + else + emi_addr = I217_RX_CONFIG; + + ret_val = e1000_write_emi_reg_locked(hw, emi_addr, 0); hw->phy.ops.release(hw); @@ -2493,51 +2513,44 @@ release: * e1000_k1_gig_workaround_lv - K1 Si workaround * @hw: pointer to the HW structure * - * Workaround to set the K1 beacon duration for 82579 parts + * Workaround to set the K1 beacon duration for 82579 parts in 10Mbps + * Disable K1 in 1000Mbps and 100Mbps **/ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw) { s32 ret_val = 0; u16 status_reg = 0; - u32 mac_reg; - u16 phy_reg; if (hw->mac.type != e1000_pch2lan) return 0; - /* Set K1 beacon duration based on 1Gbps speed or otherwise */ + /* Set K1 beacon duration based on 10Mbs speed */ ret_val = e1e_rphy(hw, HV_M_STATUS, &status_reg); if (ret_val) return ret_val; if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) { - mac_reg = er32(FEXTNVM4); - mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK; - - ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg); - if (ret_val) - return ret_val; - - if (status_reg & HV_M_STATUS_SPEED_1000) { + if (status_reg & + (HV_M_STATUS_SPEED_1000 | HV_M_STATUS_SPEED_100)) { u16 pm_phy_reg; - mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC; - phy_reg &= ~I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; - /* LV 1G Packet drop issue wa */ + /* LV 1G/100 Packet drop issue wa */ ret_val = e1e_rphy(hw, HV_PM_CTRL, &pm_phy_reg); if (ret_val) return ret_val; - pm_phy_reg &= ~HV_PM_CTRL_PLL_STOP_IN_K1_GIGA; + pm_phy_reg &= ~HV_PM_CTRL_K1_ENABLE; ret_val = e1e_wphy(hw, HV_PM_CTRL, pm_phy_reg); if (ret_val) return ret_val; } else { + u32 mac_reg; + + mac_reg = er32(FEXTNVM4); + mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK; mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC; - phy_reg |= I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; + ew32(FEXTNVM4, mac_reg); } - ew32(FEXTNVM4, mac_reg); - ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg); } return ret_val; diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.h b/drivers/net/ethernet/intel/e1000e/ich8lan.h index bead50f9187b..5515126c81c1 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.h +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.h @@ -232,16 +232,19 @@ #define I82577_MSE_THRESHOLD 0x0887 /* 82577 Mean Square Error Threshold */ #define I82579_MSE_LINK_DOWN 0x2411 /* MSE count before dropping link */ #define I82579_RX_CONFIG 0x3412 /* Receive configuration */ +#define I82579_LPI_PLL_SHUT 0x4412 /* LPI PLL Shut Enable */ #define I82579_EEE_PCS_STATUS 0x182E /* IEEE MMD Register 3.1 >> 8 */ #define I82579_EEE_CAPABILITY 0x0410 /* IEEE MMD Register 3.20 */ #define I82579_EEE_ADVERTISEMENT 0x040E /* IEEE MMD Register 7.60 */ #define I82579_EEE_LP_ABILITY 0x040F /* IEEE MMD Register 7.61 */ #define I82579_EEE_100_SUPPORTED (1 << 1) /* 100BaseTx EEE */ #define I82579_EEE_1000_SUPPORTED (1 << 2) /* 1000BaseTx EEE */ +#define I82579_LPI_100_PLL_SHUT (1 << 2) /* 100M LPI PLL Shut Enabled */ #define I217_EEE_PCS_STATUS 0x9401 /* IEEE MMD Register 3.1 */ #define I217_EEE_CAPABILITY 0x8000 /* IEEE MMD Register 3.20 */ #define I217_EEE_ADVERTISEMENT 0x8001 /* IEEE MMD Register 7.60 */ #define I217_EEE_LP_ABILITY 0x8002 /* IEEE MMD Register 7.61 */ +#define I217_RX_CONFIG 0xB20C /* Receive configuration */ #define E1000_EEE_RX_LPI_RCVD 0x0400 /* Tx LP idle received */ #define E1000_EEE_TX_LPI_RCVD 0x0800 /* Rx LP idle received */ diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index d50c91e50528..3e69386add04 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -1165,7 +1165,7 @@ static void e1000e_tx_hwtstamp_work(struct work_struct *work) dev_kfree_skb_any(adapter->tx_hwtstamp_skb); adapter->tx_hwtstamp_skb = NULL; adapter->tx_hwtstamp_timeouts++; - e_warn("clearing Tx timestamp hang"); + e_warn("clearing Tx timestamp hang\n"); } else { /* reschedule to check later */ schedule_work(&adapter->tx_hwtstamp_work); @@ -5687,7 +5687,7 @@ struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev, static int e1000_change_mtu(struct net_device *netdev, int new_mtu) { struct e1000_adapter *adapter = netdev_priv(netdev); - int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; + int max_frame = new_mtu + VLAN_HLEN + ETH_HLEN + ETH_FCS_LEN; /* Jumbo frame support */ if ((max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) && @@ -6235,6 +6235,7 @@ static int __e1000_resume(struct pci_dev *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP static int e1000e_pm_thaw(struct device *dev) { struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev)); @@ -6255,7 +6256,6 @@ static int e1000e_pm_thaw(struct device *dev) return 0; } -#ifdef CONFIG_PM_SLEEP static int e1000e_pm_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); diff --git a/drivers/net/ethernet/intel/e1000e/phy.h b/drivers/net/ethernet/intel/e1000e/phy.h index 3841bccf058c..537d2780b408 100644 --- a/drivers/net/ethernet/intel/e1000e/phy.h +++ b/drivers/net/ethernet/intel/e1000e/phy.h @@ -164,6 +164,7 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw); #define HV_M_STATUS_AUTONEG_COMPLETE 0x1000 #define HV_M_STATUS_SPEED_MASK 0x0300 #define HV_M_STATUS_SPEED_1000 0x0200 +#define HV_M_STATUS_SPEED_100 0x0100 #define HV_M_STATUS_LINK_UP 0x0040 #define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 861b722c2672..cf0761f08911 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -2897,12 +2897,9 @@ static irqreturn_t i40e_intr(int irq, void *data) u32 prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_0); if (prttsyn_stat & I40E_PRTTSYN_STAT_0_TXTIME_MASK) { - ena_mask &= ~I40E_PFINT_ICR0_ENA_TIMESYNC_MASK; + icr0 &= ~I40E_PFINT_ICR0_ENA_TIMESYNC_MASK; i40e_ptp_tx_hwtstamp(pf); - prttsyn_stat &= ~I40E_PRTTSYN_STAT_0_TXTIME_MASK; } - - wr32(hw, I40E_PRTTSYN_STAT_0, prttsyn_stat); } /* If a critical error is pending we have no choice but to reset the @@ -4271,6 +4268,14 @@ static int i40e_open(struct net_device *netdev) if (err) return err; + /* configure global TSO hardware offload settings */ + wr32(&pf->hw, I40E_GLLAN_TSOMSK_F, be32_to_cpu(TCP_FLAG_PSH | + TCP_FLAG_FIN) >> 16); + wr32(&pf->hw, I40E_GLLAN_TSOMSK_M, be32_to_cpu(TCP_FLAG_PSH | + TCP_FLAG_FIN | + TCP_FLAG_CWR) >> 16); + wr32(&pf->hw, I40E_GLLAN_TSOMSK_L, be32_to_cpu(TCP_FLAG_CWR) >> 16); + #ifdef CONFIG_I40E_VXLAN vxlan_get_rx_port(netdev); #endif @@ -6712,6 +6717,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_IPV6_CSUM | NETIF_F_TSO | + NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_RXCSUM | NETIF_F_NTUPLE | diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 262bdf11d221..81299189a47d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -160,7 +160,7 @@ static i40e_status i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw) udelay(5); } if (ret_code == I40E_ERR_TIMEOUT) - hw_dbg(hw, "Done bit in GLNVM_SRCTL not set"); + hw_dbg(hw, "Done bit in GLNVM_SRCTL not set\n"); return ret_code; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c index e33ec6c842b7..e61e63720800 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c @@ -239,7 +239,7 @@ static void i40e_ptp_tx_work(struct work_struct *work) dev_kfree_skb_any(pf->ptp_tx_skb); pf->ptp_tx_skb = NULL; pf->tx_hwtstamp_timeouts++; - dev_warn(&pf->pdev->dev, "clearing Tx timestamp hang"); + dev_warn(&pf->pdev->dev, "clearing Tx timestamp hang\n"); return; } @@ -321,7 +321,7 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi) pf->last_rx_ptp_check = jiffies; pf->rx_hwtstamp_cleared++; dev_warn(&vsi->back->pdev->dev, - "%s: clearing Rx timestamp hang", + "%s: clearing Rx timestamp hang\n", __func__); } } diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 0f5d96ad281d..9478ddc66caf 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -418,7 +418,7 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi, } break; default: - dev_info(&pf->pdev->dev, "Could not specify spec type %d", + dev_info(&pf->pdev->dev, "Could not specify spec type %d\n", input->flow_type); ret = -EINVAL; } @@ -478,7 +478,7 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring, pf->flags |= I40E_FLAG_FDIR_REQUIRES_REINIT; } } else { - dev_info(&pdev->dev, "FD filter programming error"); + dev_info(&pdev->dev, "FD filter programming error\n"); } } else if (error == (0x1 << I40E_RX_PROG_STATUS_DESC_NO_FD_ENTRY_SHIFT)) { @@ -1713,9 +1713,11 @@ static int i40e_tx_prepare_vlan_flags(struct sk_buff *skb, I40E_TX_FLAGS_VLAN_PRIO_SHIFT; if (tx_flags & I40E_TX_FLAGS_SW_VLAN) { struct vlan_ethhdr *vhdr; - if (skb_header_cloned(skb) && - pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) - return -ENOMEM; + int rc; + + rc = skb_cow_head(skb, 0); + if (rc < 0) + return rc; vhdr = (struct vlan_ethhdr *)skb->data; vhdr->h_vlan_TCI = htons(tx_flags >> I40E_TX_FLAGS_VLAN_SHIFT); @@ -1743,20 +1745,18 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, u64 *cd_type_cmd_tso_mss, u32 *cd_tunneling) { u32 cd_cmd, cd_tso_len, cd_mss; + struct ipv6hdr *ipv6h; struct tcphdr *tcph; struct iphdr *iph; u32 l4len; int err; - struct ipv6hdr *ipv6h; if (!skb_is_gso(skb)) return 0; - if (skb_header_cloned(skb)) { - err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); - if (err) - return err; - } + err = skb_cow_head(skb, 0); + if (err < 0) + return err; if (protocol == htons(ETH_P_IP)) { iph = skb->encapsulation ? inner_ip_hdr(skb) : ip_hdr(skb); diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.c b/drivers/net/ethernet/intel/igb/e1000_i210.c index db963397cc27..f67f8a170b90 100644 --- a/drivers/net/ethernet/intel/igb/e1000_i210.c +++ b/drivers/net/ethernet/intel/igb/e1000_i210.c @@ -365,7 +365,7 @@ static s32 igb_read_invm_word_i210(struct e1000_hw *hw, u8 address, u16 *data) word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword); if (word_address == address) { *data = INVM_DWORD_TO_WORD_DATA(invm_dword); - hw_dbg("Read INVM Word 0x%02x = %x", + hw_dbg("Read INVM Word 0x%02x = %x\n", address, *data); status = E1000_SUCCESS; break; diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c index 5910a932ea7c..1e0c404db81a 100644 --- a/drivers/net/ethernet/intel/igb/e1000_mac.c +++ b/drivers/net/ethernet/intel/igb/e1000_mac.c @@ -929,11 +929,10 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) */ if (hw->fc.requested_mode == e1000_fc_full) { hw->fc.current_mode = e1000_fc_full; - hw_dbg("Flow Control = FULL.\r\n"); + hw_dbg("Flow Control = FULL.\n"); } else { hw->fc.current_mode = e1000_fc_rx_pause; - hw_dbg("Flow Control = " - "RX PAUSE frames only.\r\n"); + hw_dbg("Flow Control = RX PAUSE frames only.\n"); } } /* For receiving PAUSE frames ONLY. @@ -948,7 +947,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { hw->fc.current_mode = e1000_fc_tx_pause; - hw_dbg("Flow Control = TX PAUSE frames only.\r\n"); + hw_dbg("Flow Control = TX PAUSE frames only.\n"); } /* For transmitting PAUSE frames ONLY. * @@ -962,7 +961,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { hw->fc.current_mode = e1000_fc_rx_pause; - hw_dbg("Flow Control = RX PAUSE frames only.\r\n"); + hw_dbg("Flow Control = RX PAUSE frames only.\n"); } /* Per the IEEE spec, at this point flow control should be * disabled. However, we want to consider that we could @@ -988,10 +987,10 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) (hw->fc.requested_mode == e1000_fc_tx_pause) || (hw->fc.strict_ieee)) { hw->fc.current_mode = e1000_fc_none; - hw_dbg("Flow Control = NONE.\r\n"); + hw_dbg("Flow Control = NONE.\n"); } else { hw->fc.current_mode = e1000_fc_rx_pause; - hw_dbg("Flow Control = RX PAUSE frames only.\r\n"); + hw_dbg("Flow Control = RX PAUSE frames only.\n"); } /* Now we need to do one last check... If we auto- diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index fb98d4602f9d..16430a8440fa 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -5193,8 +5193,10 @@ void igb_update_stats(struct igb_adapter *adapter, rcu_read_lock(); for (i = 0; i < adapter->num_rx_queues; i++) { - u32 rqdpc = rd32(E1000_RQDPC(i)); struct igb_ring *ring = adapter->rx_ring[i]; + u32 rqdpc = rd32(E1000_RQDPC(i)); + if (hw->mac.type >= e1000_i210) + wr32(E1000_RQDPC(i), 0); if (rqdpc) { ring->rx_stats.drops += rqdpc; diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index 9209d652e1c9..ab25e49365f7 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c @@ -389,7 +389,7 @@ static void igb_ptp_tx_work(struct work_struct *work) adapter->ptp_tx_skb = NULL; clear_bit_unlock(__IGB_PTP_TX_IN_PROGRESS, &adapter->state); adapter->tx_hwtstamp_timeouts++; - dev_warn(&adapter->pdev->dev, "clearing Tx timestamp hang"); + dev_warn(&adapter->pdev->dev, "clearing Tx timestamp hang\n"); return; } @@ -451,7 +451,7 @@ void igb_ptp_rx_hang(struct igb_adapter *adapter) rd32(E1000_RXSTMPH); adapter->last_rx_ptp_check = jiffies; adapter->rx_hwtstamp_cleared++; - dev_warn(&adapter->pdev->dev, "clearing Rx timestamp hang"); + dev_warn(&adapter->pdev->dev, "clearing Rx timestamp hang\n"); } } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 1a12c1dd7a27..c6c4ca7d68e6 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -256,7 +256,6 @@ struct ixgbe_ring { struct ixgbe_tx_buffer *tx_buffer_info; struct ixgbe_rx_buffer *rx_buffer_info; }; - unsigned long last_rx_timestamp; unsigned long state; u8 __iomem *tail; dma_addr_t dma; /* phys. address of descriptor ring */ @@ -770,6 +769,7 @@ struct ixgbe_adapter { unsigned long ptp_tx_start; unsigned long last_overflow_check; unsigned long last_rx_ptp_check; + unsigned long last_rx_timestamp; spinlock_t tmreg_lock; struct cyclecounter cc; struct timecounter tc; @@ -944,24 +944,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter); void ixgbe_ptp_stop(struct ixgbe_adapter *adapter); void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter); void ixgbe_ptp_rx_hang(struct ixgbe_adapter *adapter); -void __ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector, - struct sk_buff *skb); -static inline void ixgbe_ptp_rx_hwtstamp(struct ixgbe_ring *rx_ring, - union ixgbe_adv_rx_desc *rx_desc, - struct sk_buff *skb) -{ - if (unlikely(!ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_STAT_TS))) - return; - - __ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector, skb); - - /* - * Update the last_rx_timestamp timer in order to enable watchdog check - * for error case of latched timestamp on a dropped packet. - */ - rx_ring->last_rx_timestamp = jiffies; -} - +void ixgbe_ptp_rx_hwtstamp(struct ixgbe_adapter *adapter, struct sk_buff *skb); int ixgbe_ptp_set_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr); int ixgbe_ptp_get_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr); void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 24fba39e194e..981b8a7b100d 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -1195,7 +1195,7 @@ static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, */ hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX - data[0]; - hw_dbg(hw, "Detected EEPROM page size = %d words.", + hw_dbg(hw, "Detected EEPROM page size = %d words.\n", hw->eeprom.word_page_size); out: return status; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index c4c526b7f99f..d62e7a25cf97 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1664,7 +1664,8 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring, ixgbe_rx_checksum(rx_ring, rx_desc, skb); - ixgbe_ptp_rx_hwtstamp(rx_ring, rx_desc, skb); + if (unlikely(ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_STAT_TS))) + ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector->adapter, skb); if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) && ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index 23f765263f12..a76af8e28a04 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -536,7 +536,7 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw) if (time_out == max_time_out) { status = IXGBE_ERR_LINK_SETUP; - hw_dbg(hw, "ixgbe_setup_phy_link_generic: time out"); + hw_dbg(hw, "ixgbe_setup_phy_link_generic: time out\n"); } return status; @@ -745,7 +745,7 @@ s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw) if (time_out == max_time_out) { status = IXGBE_ERR_LINK_SETUP; - hw_dbg(hw, "ixgbe_setup_phy_link_tnx: time out"); + hw_dbg(hw, "ixgbe_setup_phy_link_tnx: time out\n"); } return status; @@ -1175,7 +1175,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) status = 0; } else { if (hw->allow_unsupported_sfp) { - e_warn(drv, "WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics. Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. Intel Corporation is not responsible for any harm caused by using untested modules."); + e_warn(drv, "WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics. Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. Intel Corporation is not responsible for any harm caused by using untested modules.\n"); status = 0; } else { hw_dbg(hw, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index 63515a6f67fa..8902ae683457 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -435,10 +435,8 @@ void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter) void ixgbe_ptp_rx_hang(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; - struct ixgbe_ring *rx_ring; u32 tsyncrxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); unsigned long rx_event; - int n; /* if we don't have a valid timestamp in the registers, just update the * timeout counter and exit @@ -450,18 +448,15 @@ void ixgbe_ptp_rx_hang(struct ixgbe_adapter *adapter) /* determine the most recent watchdog or rx_timestamp event */ rx_event = adapter->last_rx_ptp_check; - for (n = 0; n < adapter->num_rx_queues; n++) { - rx_ring = adapter->rx_ring[n]; - if (time_after(rx_ring->last_rx_timestamp, rx_event)) - rx_event = rx_ring->last_rx_timestamp; - } + if (time_after(adapter->last_rx_timestamp, rx_event)) + rx_event = adapter->last_rx_timestamp; /* only need to read the high RXSTMP register to clear the lock */ if (time_is_before_jiffies(rx_event + 5*HZ)) { IXGBE_READ_REG(hw, IXGBE_RXSTMPH); adapter->last_rx_ptp_check = jiffies; - e_warn(drv, "clearing RX Timestamp hang"); + e_warn(drv, "clearing RX Timestamp hang\n"); } } @@ -517,7 +512,7 @@ static void ixgbe_ptp_tx_hwtstamp_work(struct work_struct *work) dev_kfree_skb_any(adapter->ptp_tx_skb); adapter->ptp_tx_skb = NULL; clear_bit_unlock(__IXGBE_PTP_TX_IN_PROGRESS, &adapter->state); - e_warn(drv, "clearing Tx Timestamp hang"); + e_warn(drv, "clearing Tx Timestamp hang\n"); return; } @@ -530,35 +525,22 @@ static void ixgbe_ptp_tx_hwtstamp_work(struct work_struct *work) } /** - * __ixgbe_ptp_rx_hwtstamp - utility function which checks for RX time stamp - * @q_vector: structure containing interrupt and ring information + * ixgbe_ptp_rx_hwtstamp - utility function which checks for RX time stamp + * @adapter: pointer to adapter struct * @skb: particular skb to send timestamp with * * if the timestamp is valid, we convert it into the timecounter ns * value, then store that result into the shhwtstamps structure which * is passed up the network stack */ -void __ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector, - struct sk_buff *skb) +void ixgbe_ptp_rx_hwtstamp(struct ixgbe_adapter *adapter, struct sk_buff *skb) { - struct ixgbe_adapter *adapter; - struct ixgbe_hw *hw; + struct ixgbe_hw *hw = &adapter->hw; struct skb_shared_hwtstamps *shhwtstamps; u64 regval = 0, ns; u32 tsyncrxctl; unsigned long flags; - /* we cannot process timestamps on a ring without a q_vector */ - if (!q_vector || !q_vector->adapter) - return; - - adapter = q_vector->adapter; - hw = &adapter->hw; - - /* - * Read the tsyncrxctl register afterwards in order to prevent taking an - * I/O hit on every packet. - */ tsyncrxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); if (!(tsyncrxctl & IXGBE_TSYNCRXCTL_VALID)) return; @@ -566,13 +548,17 @@ void __ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector, regval |= (u64)IXGBE_READ_REG(hw, IXGBE_RXSTMPL); regval |= (u64)IXGBE_READ_REG(hw, IXGBE_RXSTMPH) << 32; - spin_lock_irqsave(&adapter->tmreg_lock, flags); ns = timecounter_cyc2time(&adapter->tc, regval); spin_unlock_irqrestore(&adapter->tmreg_lock, flags); shhwtstamps = skb_hwtstamps(skb); shhwtstamps->hwtstamp = ns_to_ktime(ns); + + /* Update the last_rx_timestamp timer in order to enable watchdog check + * for error case of latched timestamp on a dropped packet. + */ + adapter->last_rx_timestamp = jiffies; } int ixgbe_ptp_get_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr) diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c index b161a525fc5b..9d5ced263a5e 100644 --- a/drivers/net/ethernet/marvell/mvmdio.c +++ b/drivers/net/ethernet/marvell/mvmdio.c @@ -232,7 +232,7 @@ static int orion_mdio_probe(struct platform_device *pdev) clk_prepare_enable(dev->clk); dev->err_interrupt = platform_get_irq(pdev, 0); - if (dev->err_interrupt != -ENXIO) { + if (dev->err_interrupt > 0) { ret = devm_request_irq(&pdev->dev, dev->err_interrupt, orion_mdio_err_irq, IRQF_SHARED, pdev->name, dev); @@ -241,6 +241,9 @@ static int orion_mdio_probe(struct platform_device *pdev) writel(MVMDIO_ERR_INT_SMI_DONE, dev->regs + MVMDIO_ERR_INT_MASK); + + } else if (dev->err_interrupt == -EPROBE_DEFER) { + return -EPROBE_DEFER; } mutex_init(&dev->lock); diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index cef267e24f9c..7cf9dadcb471 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -754,10 +754,10 @@ static void mlx4_request_modules(struct mlx4_dev *dev) has_eth_port = true; } - if (has_ib_port || (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE)) - request_module_nowait(IB_DRV_NAME); if (has_eth_port) request_module_nowait(EN_DRV_NAME); + if (has_ib_port || (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE)) + request_module_nowait(IB_DRV_NAME); } /* @@ -2440,7 +2440,8 @@ slave_start: * No return code for this call, just warn the user in case of PCI * express device capabilities are under-satisfied by the bus. */ - mlx4_check_pcie_caps(dev); + if (!mlx4_is_slave(dev)) + mlx4_check_pcie_caps(dev); /* In master functions, the communication channel must be initialized * after obtaining its address from fw */ diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c index cfcad26ed40f..b5b3549b0c8d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/port.c +++ b/drivers/net/ethernet/mellanox/mlx4/port.c @@ -1106,6 +1106,9 @@ int mlx4_get_slave_from_roce_gid(struct mlx4_dev *dev, int port, u8 *gid, } if (found_ix >= 0) { + /* Calculate a slave_gid which is the slave number in the gid + * table and not a globally unique slave number. + */ if (found_ix < MLX4_ROCE_PF_GIDS) slave_gid = 0; else if (found_ix < MLX4_ROCE_PF_GIDS + (vf_gids % num_vfs) * @@ -1118,41 +1121,43 @@ int mlx4_get_slave_from_roce_gid(struct mlx4_dev *dev, int port, u8 *gid, ((vf_gids % num_vfs) * ((vf_gids / num_vfs + 1)))) / (vf_gids / num_vfs)) + vf_gids % num_vfs + 1; + /* Calculate the globally unique slave id */ if (slave_gid) { struct mlx4_active_ports exclusive_ports; struct mlx4_active_ports actv_ports; struct mlx4_slaves_pport slaves_pport_actv; unsigned max_port_p_one; - int num_slaves_before = 1; + int num_vfs_before = 0; + int candidate_slave_gid; + /* Calculate how many VFs are on the previous port, if exists */ for (i = 1; i < port; i++) { bitmap_zero(exclusive_ports.ports, dev->caps.num_ports); - set_bit(i, exclusive_ports.ports); + set_bit(i - 1, exclusive_ports.ports); slaves_pport_actv = mlx4_phys_to_slaves_pport_actv( dev, &exclusive_ports); - num_slaves_before += bitmap_weight( + num_vfs_before += bitmap_weight( slaves_pport_actv.slaves, dev->num_vfs + 1); } - if (slave_gid < num_slaves_before) { - bitmap_zero(exclusive_ports.ports, dev->caps.num_ports); - set_bit(port - 1, exclusive_ports.ports); - slaves_pport_actv = - mlx4_phys_to_slaves_pport_actv( - dev, &exclusive_ports); - slave_gid += bitmap_weight( - slaves_pport_actv.slaves, - dev->num_vfs + 1) - - num_slaves_before; - } - actv_ports = mlx4_get_active_ports(dev, slave_gid); + /* candidate_slave_gid isn't necessarily the correct slave, but + * it has the same number of ports and is assigned to the same + * ports as the real slave we're looking for. On dual port VF, + * slave_gid = [single port VFs on port <port>] + + * [offset of the current slave from the first dual port VF] + + * 1 (for the PF). + */ + candidate_slave_gid = slave_gid + num_vfs_before; + + actv_ports = mlx4_get_active_ports(dev, candidate_slave_gid); max_port_p_one = find_first_bit( actv_ports.ports, dev->caps.num_ports) + bitmap_weight(actv_ports.ports, dev->caps.num_ports) + 1; + /* Calculate the real slave number */ for (i = 1; i < max_port_p_one; i++) { if (i == port) continue; diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 3b5f53ef29b2..1c3fdd4a1f7d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -3733,6 +3733,25 @@ static int qp_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, } } +static int mlx4_adjust_port(struct mlx4_dev *dev, int slave, + u8 *gid, enum mlx4_protocol prot) +{ + int real_port; + + if (prot != MLX4_PROT_ETH) + return 0; + + if (dev->caps.steering_mode == MLX4_STEERING_MODE_B0 || + dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) { + real_port = mlx4_slave_convert_port(dev, slave, gid[5]); + if (real_port < 0) + return -EINVAL; + gid[5] = real_port; + } + + return 0; +} + int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, struct mlx4_cmd_mailbox *inbox, @@ -3768,6 +3787,10 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave, if (err) goto ex_detach; } else { + err = mlx4_adjust_port(dev, slave, gid, prot); + if (err) + goto ex_put; + err = rem_mcg_res(dev, slave, rqp, gid, prot, type, ®_id); if (err) goto ex_put; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index dbf75393f758..0bc914859e38 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -2374,6 +2374,14 @@ void qlcnic_set_drv_version(struct qlcnic_adapter *adapter) qlcnic_fw_cmd_set_drv_version(adapter, fw_cmd); } +/* Reset firmware API lock */ +static void qlcnic_reset_api_lock(struct qlcnic_adapter *adapter) +{ + qlcnic_api_lock(adapter); + qlcnic_api_unlock(adapter); +} + + static int qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -2476,6 +2484,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (qlcnic_82xx_check(adapter)) { qlcnic_check_vf(adapter, ent); adapter->portnum = adapter->ahw->pci_func; + qlcnic_reset_api_lock(adapter); err = qlcnic_start_firmware(adapter); if (err) { dev_err(&pdev->dev, "Loading fw failed.Please Reboot\n" diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index 0638c1810d54..6afe9c1f5ab9 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c @@ -1370,7 +1370,7 @@ static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter, rsp = qlcnic_sriov_alloc_bc_trans(&trans); if (rsp) - return rsp; + goto free_cmd; rsp = qlcnic_sriov_prepare_bc_hdr(trans, cmd, seq, QLC_BC_COMMAND); if (rsp) @@ -1425,6 +1425,13 @@ err_out: cleanup_transaction: qlcnic_sriov_cleanup_transaction(trans); + +free_cmd: + if (cmd->type == QLC_83XX_MBX_CMD_NO_WAIT) { + qlcnic_free_mbx_args(cmd); + kfree(cmd); + } + return rsp; } diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h index 6203c7d8550f..45019649bbbd 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h @@ -358,6 +358,8 @@ struct sxgbe_core_ops { /* Enable disable checksum offload operations */ void (*enable_rx_csum)(void __iomem *ioaddr); void (*disable_rx_csum)(void __iomem *ioaddr); + void (*enable_rxqueue)(void __iomem *ioaddr, int queue_num); + void (*disable_rxqueue)(void __iomem *ioaddr, int queue_num); }; const struct sxgbe_core_ops *sxgbe_get_core_ops(void); diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c index c4da7a2b002a..58c35692560e 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c @@ -165,6 +165,26 @@ static void sxgbe_core_set_speed(void __iomem *ioaddr, unsigned char speed) writel(tx_cfg, ioaddr + SXGBE_CORE_TX_CONFIG_REG); } +static void sxgbe_core_enable_rxqueue(void __iomem *ioaddr, int queue_num) +{ + u32 reg_val; + + reg_val = readl(ioaddr + SXGBE_CORE_RX_CTL0_REG); + reg_val &= ~(SXGBE_CORE_RXQ_ENABLE_MASK << queue_num); + reg_val |= SXGBE_CORE_RXQ_ENABLE; + writel(reg_val, ioaddr + SXGBE_CORE_RX_CTL0_REG); +} + +static void sxgbe_core_disable_rxqueue(void __iomem *ioaddr, int queue_num) +{ + u32 reg_val; + + reg_val = readl(ioaddr + SXGBE_CORE_RX_CTL0_REG); + reg_val &= ~(SXGBE_CORE_RXQ_ENABLE_MASK << queue_num); + reg_val |= SXGBE_CORE_RXQ_DISABLE; + writel(reg_val, ioaddr + SXGBE_CORE_RX_CTL0_REG); +} + static void sxgbe_set_eee_mode(void __iomem *ioaddr) { u32 ctrl; @@ -254,6 +274,8 @@ static const struct sxgbe_core_ops core_ops = { .set_eee_pls = sxgbe_set_eee_pls, .enable_rx_csum = sxgbe_enable_rx_csum, .disable_rx_csum = sxgbe_disable_rx_csum, + .enable_rxqueue = sxgbe_core_enable_rxqueue, + .disable_rxqueue = sxgbe_core_disable_rxqueue, }; const struct sxgbe_core_ops *sxgbe_get_core_ops(void) diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c index e896dbbd2e15..2686bb5b6765 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c @@ -45,10 +45,10 @@ static void sxgbe_prepare_tx_desc(struct sxgbe_tx_norm_desc *p, u8 is_fd, p->tdes23.tx_rd_des23.first_desc = is_fd; p->tdes23.tx_rd_des23.buf1_size = buf1_len; - p->tdes23.tx_rd_des23.tx_pkt_len.cksum_pktlen.total_pkt_len = pkt_len; + p->tdes23.tx_rd_des23.tx_pkt_len.pkt_len.total_pkt_len = pkt_len; if (cksum) - p->tdes23.tx_rd_des23.tx_pkt_len.cksum_pktlen.cksum_ctl = cic_full; + p->tdes23.tx_rd_des23.cksum_ctl = cic_full; } /* Set VLAN control information */ @@ -233,6 +233,12 @@ static void sxgbe_set_rx_owner(struct sxgbe_rx_norm_desc *p) p->rdes23.rx_rd_des23.own_bit = 1; } +/* Set Interrupt on completion bit */ +static void sxgbe_set_rx_int_on_com(struct sxgbe_rx_norm_desc *p) +{ + p->rdes23.rx_rd_des23.int_on_com = 1; +} + /* Get the receive frame size */ static int sxgbe_get_rx_frame_len(struct sxgbe_rx_norm_desc *p) { @@ -498,6 +504,7 @@ static const struct sxgbe_desc_ops desc_ops = { .init_rx_desc = sxgbe_init_rx_desc, .get_rx_owner = sxgbe_get_rx_owner, .set_rx_owner = sxgbe_set_rx_owner, + .set_rx_int_on_com = sxgbe_set_rx_int_on_com, .get_rx_frame_len = sxgbe_get_rx_frame_len, .get_rx_fd_status = sxgbe_get_rx_fd_status, .get_rx_ld_status = sxgbe_get_rx_ld_status, diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h index 838cb9fb0ea9..18609324db72 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h @@ -39,22 +39,22 @@ struct sxgbe_tx_norm_desc { u32 int_on_com:1; /* TDES3 */ union { - u32 tcp_payload_len:18; + u16 tcp_payload_len; struct { u32 total_pkt_len:15; u32 reserved1:1; - u32 cksum_ctl:2; - } cksum_pktlen; + } pkt_len; } tx_pkt_len; - u32 tse_bit:1; - u32 tcp_hdr_len:4; - u32 sa_insert_ctl:3; - u32 crc_pad_ctl:2; - u32 last_desc:1; - u32 first_desc:1; - u32 ctxt_bit:1; - u32 own_bit:1; + u16 cksum_ctl:2; + u16 tse_bit:1; + u16 tcp_hdr_len:4; + u16 sa_insert_ctl:3; + u16 crc_pad_ctl:2; + u16 last_desc:1; + u16 first_desc:1; + u16 ctxt_bit:1; + u16 own_bit:1; } tx_rd_des23; /* tx write back Desc 2,3 */ @@ -70,25 +70,20 @@ struct sxgbe_tx_norm_desc { struct sxgbe_rx_norm_desc { union { - u32 rdes0; /* buf1 address */ - struct { + u64 rdes01; /* buf1 address */ + union { u32 out_vlan_tag:16; u32 in_vlan_tag:16; - } wb_rx_des0; - } rd_wb_des0; - - union { - u32 rdes1; /* buf2 address or buf1[63:32] */ - u32 rss_hash; /* Write-back RX */ - } rd_wb_des1; + u32 rss_hash; + } rx_wb_des01; + } rdes01; union { /* RX Read format Desc 2,3 */ struct{ /* RDES2 */ - u32 buf2_addr; + u64 buf2_addr:62; /* RDES3 */ - u32 buf2_hi_addr:30; u32 int_on_com:1; u32 own_bit:1; } rx_rd_des23; @@ -263,6 +258,9 @@ struct sxgbe_desc_ops { /* Set own bit */ void (*set_rx_owner)(struct sxgbe_rx_norm_desc *p); + /* Set Interrupt on completion bit */ + void (*set_rx_int_on_com)(struct sxgbe_rx_norm_desc *p); + /* Get the receive frame size */ int (*get_rx_frame_len)(struct sxgbe_rx_norm_desc *p); diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c index 4d989ff6c978..bb9b5b8afc5f 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c @@ -23,21 +23,8 @@ /* DMA core initialization */ static int sxgbe_dma_init(void __iomem *ioaddr, int fix_burst, int burst_map) { - int retry_count = 10; u32 reg_val; - /* reset the DMA */ - writel(SXGBE_DMA_SOFT_RESET, ioaddr + SXGBE_DMA_MODE_REG); - while (retry_count--) { - if (!(readl(ioaddr + SXGBE_DMA_MODE_REG) & - SXGBE_DMA_SOFT_RESET)) - break; - mdelay(10); - } - - if (retry_count < 0) - return -EBUSY; - reg_val = readl(ioaddr + SXGBE_DMA_SYSBUS_MODE_REG); /* if fix_burst = 0, Set UNDEF = 1 of DMA_Sys_Mode Register. diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c index 27e8c824b204..82a9a983869f 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c @@ -1076,6 +1076,9 @@ static int sxgbe_open(struct net_device *dev) /* Initialize the MAC Core */ priv->hw->mac->core_init(priv->ioaddr); + SXGBE_FOR_EACH_QUEUE(SXGBE_RX_QUEUES, queue_num) { + priv->hw->mac->enable_rxqueue(priv->ioaddr, queue_num); + } /* Request the IRQ lines */ ret = devm_request_irq(priv->device, priv->irq, sxgbe_common_interrupt, @@ -1453,6 +1456,7 @@ static void sxgbe_rx_refill(struct sxgbe_priv_data *priv) /* Added memory barrier for RX descriptor modification */ wmb(); priv->hw->desc->set_rx_owner(p); + priv->hw->desc->set_rx_int_on_com(p); /* Added memory barrier for RX descriptor modification */ wmb(); } @@ -2070,6 +2074,24 @@ static int sxgbe_hw_init(struct sxgbe_priv_data * const priv) return 0; } +static int sxgbe_sw_reset(void __iomem *addr) +{ + int retry_count = 10; + + writel(SXGBE_DMA_SOFT_RESET, addr + SXGBE_DMA_MODE_REG); + while (retry_count--) { + if (!(readl(addr + SXGBE_DMA_MODE_REG) & + SXGBE_DMA_SOFT_RESET)) + break; + mdelay(10); + } + + if (retry_count < 0) + return -EBUSY; + + return 0; +} + /** * sxgbe_drv_probe * @device: device pointer @@ -2102,6 +2124,10 @@ struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device, priv->plat = plat_dat; priv->ioaddr = addr; + ret = sxgbe_sw_reset(priv->ioaddr); + if (ret) + goto error_free_netdev; + /* Verify driver arguments */ sxgbe_verify_args(); @@ -2218,9 +2244,14 @@ error_free_netdev: int sxgbe_drv_remove(struct net_device *ndev) { struct sxgbe_priv_data *priv = netdev_priv(ndev); + u8 queue_num; netdev_info(ndev, "%s: removing driver\n", __func__); + SXGBE_FOR_EACH_QUEUE(SXGBE_RX_QUEUES, queue_num) { + priv->hw->mac->disable_rxqueue(priv->ioaddr, queue_num); + } + priv->hw->dma->stop_rx(priv->ioaddr, SXGBE_RX_QUEUES); priv->hw->dma->stop_tx(priv->ioaddr, SXGBE_TX_QUEUES); diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c index 01af2cbb479d..43ccb4a6de15 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c @@ -27,7 +27,7 @@ #define SXGBE_SMA_PREAD_CMD 0x02 /* post read increament address */ #define SXGBE_SMA_READ_CMD 0x03 /* read command */ #define SXGBE_SMA_SKIP_ADDRFRM 0x00040000 /* skip the address frame */ -#define SXGBE_MII_BUSY 0x00800000 /* mii busy */ +#define SXGBE_MII_BUSY 0x00400000 /* mii busy */ static int sxgbe_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_data) { @@ -147,6 +147,7 @@ int sxgbe_mdio_register(struct net_device *ndev) struct sxgbe_mdio_bus_data *mdio_data = priv->plat->mdio_bus_data; int err, phy_addr; int *irqlist; + bool phy_found = false; bool act; /* allocate the new mdio bus */ @@ -162,7 +163,7 @@ int sxgbe_mdio_register(struct net_device *ndev) irqlist = priv->mii_irq; /* assign mii bus fields */ - mdio_bus->name = "samsxgbe"; + mdio_bus->name = "sxgbe"; mdio_bus->read = &sxgbe_mdio_read; mdio_bus->write = &sxgbe_mdio_write; snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%x", @@ -216,13 +217,22 @@ int sxgbe_mdio_register(struct net_device *ndev) netdev_info(ndev, "PHY ID %08x at %d IRQ %s (%s)%s\n", phy->phy_id, phy_addr, irq_str, dev_name(&phy->dev), act ? " active" : ""); + phy_found = true; } } + if (!phy_found) { + netdev_err(ndev, "PHY not found\n"); + goto phyfound_err; + } + priv->mii = mdio_bus; return 0; +phyfound_err: + err = -ENODEV; + mdiobus_unregister(mdio_bus); mdiobus_err: mdiobus_free(mdio_bus); return err; diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h index 5a89acb4c505..56f8bf5a3f1b 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h @@ -52,6 +52,10 @@ #define SXGBE_CORE_RX_CTL2_REG 0x00A8 #define SXGBE_CORE_RX_CTL3_REG 0x00AC +#define SXGBE_CORE_RXQ_ENABLE_MASK 0x0003 +#define SXGBE_CORE_RXQ_ENABLE 0x0002 +#define SXGBE_CORE_RXQ_DISABLE 0x0000 + /* Interrupt Registers */ #define SXGBE_CORE_INT_STATUS_REG 0x00B0 #define SXGBE_CORE_INT_ENABLE_REG 0x00B4 diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index d1b4dca53a9d..bcaa41af1e62 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c @@ -147,18 +147,19 @@ MODULE_ALIAS("platform:smc91x"); */ #define MII_DELAY 1 -#if SMC_DEBUG > 0 -#define DBG(n, dev, args...) \ - do { \ - if (SMC_DEBUG >= (n)) \ - netdev_dbg(dev, args); \ +#define DBG(n, dev, fmt, ...) \ + do { \ + if (SMC_DEBUG >= (n)) \ + netdev_dbg(dev, fmt, ##__VA_ARGS__); \ } while (0) -#define PRINTK(dev, args...) netdev_info(dev, args) -#else -#define DBG(n, dev, args...) do { } while (0) -#define PRINTK(dev, args...) netdev_dbg(dev, args) -#endif +#define PRINTK(dev, fmt, ...) \ + do { \ + if (SMC_DEBUG > 0) \ + netdev_info(dev, fmt, ##__VA_ARGS__); \ + else \ + netdev_dbg(dev, fmt, ##__VA_ARGS__); \ + } while (0) #if SMC_DEBUG > 3 static void PRINT_PKT(u_char *buf, int length) @@ -191,7 +192,7 @@ static void PRINT_PKT(u_char *buf, int length) pr_cont("\n"); } #else -#define PRINT_PKT(x...) do { } while (0) +static inline void PRINT_PKT(u_char *buf, int length) { } #endif @@ -1781,7 +1782,7 @@ static int smc_findirq(struct smc_local *lp) int timeout = 20; unsigned long cookie; - DBG(2, dev, "%s: %s\n", CARDNAME, __func__); + DBG(2, lp->dev, "%s: %s\n", CARDNAME, __func__); cookie = probe_irq_on(); diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 31e55fba7cad..7918d5132c1f 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -382,6 +382,10 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) if (skb_is_gso(skb)) goto do_lso; + if ((skb->ip_summed == CHECKSUM_NONE) || + (skb->ip_summed == CHECKSUM_UNNECESSARY)) + goto do_send; + rndis_msg_size += NDIS_CSUM_PPI_SIZE; ppi = init_ppi_data(rndis_msg, NDIS_CSUM_PPI_SIZE, TCPIP_CHKSUM_PKTINFO); diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 753a8c23d15d..b0e2865a6810 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -263,11 +263,9 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev) const struct macvlan_dev *vlan = netdev_priv(dev); const struct macvlan_port *port = vlan->port; const struct macvlan_dev *dest; - __u8 ip_summed = skb->ip_summed; if (vlan->mode == MACVLAN_MODE_BRIDGE) { const struct ethhdr *eth = (void *)skb->data; - skb->ip_summed = CHECKSUM_UNNECESSARY; /* send to other bridge ports directly */ if (is_multicast_ether_addr(eth->h_dest)) { @@ -285,7 +283,6 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev) } xmit_world: - skb->ip_summed = ip_summed; skb->dev = vlan->lowerdev; return dev_queue_xmit(skb); } diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index ff111a89e17f..3381c4f91a8c 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -322,6 +322,15 @@ static rx_handler_result_t macvtap_handle_frame(struct sk_buff **pskb) segs = nskb; } } else { + /* If we receive a partial checksum and the tap side + * doesn't support checksum offload, compute the checksum. + * Note: it doesn't matter which checksum feature to + * check, we either support them all or none. + */ + if (skb->ip_summed == CHECKSUM_PARTIAL && + !(features & NETIF_F_ALL_CSUM) && + skb_checksum_help(skb)) + goto drop; skb_queue_tail(&q->sk.sk_receive_queue, skb); } diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 5ad971a55c5d..d849684231c1 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -246,13 +246,13 @@ static int ksz9021_load_values_from_of(struct phy_device *phydev, if (val1 != -1) newval = ((newval & 0xfff0) | ((val1 / PS_TO_REG) & 0xf) << 0); - if (val2 != -1) + if (val2 != -2) newval = ((newval & 0xff0f) | ((val2 / PS_TO_REG) & 0xf) << 4); - if (val3 != -1) + if (val3 != -3) newval = ((newval & 0xf0ff) | ((val3 / PS_TO_REG) & 0xf) << 8); - if (val4 != -1) + if (val4 != -4) newval = ((newval & 0x0fff) | ((val4 / PS_TO_REG) & 0xf) << 12); return kszphy_extended_write(phydev, reg, newval); diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 1b6d09aef427..a972056b2249 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -765,6 +765,17 @@ void phy_state_machine(struct work_struct *work) break; if (phydev->link) { + if (AUTONEG_ENABLE == phydev->autoneg) { + err = phy_aneg_done(phydev); + if (err < 0) + break; + + if (!err) { + phydev->state = PHY_AN; + phydev->link_timeout = PHY_AN_TIMEOUT; + break; + } + } phydev->state = PHY_RUNNING; netif_carrier_on(phydev->attached_dev); phydev->adjust_link(phydev->attached_dev); diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c index cc70ecfc7062..ad4a94e9ff57 100644 --- a/drivers/net/slip/slip.c +++ b/drivers/net/slip/slip.c @@ -429,13 +429,13 @@ static void slip_write_wakeup(struct tty_struct *tty) if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev)) return; - spin_lock(&sl->lock); + spin_lock_bh(&sl->lock); if (sl->xleft <= 0) { /* Now serial buffer is almost free & we can start * transmission of another packet */ sl->dev->stats.tx_packets++; clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - spin_unlock(&sl->lock); + spin_unlock_bh(&sl->lock); sl_unlock(sl); return; } @@ -443,7 +443,7 @@ static void slip_write_wakeup(struct tty_struct *tty) actual = tty->ops->write(tty, sl->xhead, sl->xleft); sl->xleft -= actual; sl->xhead += actual; - spin_unlock(&sl->lock); + spin_unlock_bh(&sl->lock); } static void sl_tx_timeout(struct net_device *dev) diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 33008c1d1d67..767fe61b5ac9 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -2834,8 +2834,10 @@ static int team_device_event(struct notifier_block *unused, case NETDEV_UP: if (netif_carrier_ok(dev)) team_port_change_check(port, true); + break; case NETDEV_DOWN: team_port_change_check(port, false); + break; case NETDEV_CHANGE: if (netif_running(port->dev)) team_port_change_check(port, diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 549dbac710ed..9a2bd11943eb 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -785,7 +785,7 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) skb_out->len > CDC_NCM_MIN_TX_PKT) memset(skb_put(skb_out, ctx->tx_max - skb_out->len), 0, ctx->tx_max - skb_out->len); - else if ((skb_out->len % dev->maxpacket) == 0) + else if (skb_out->len < ctx->tx_max && (skb_out->len % dev->maxpacket) == 0) *skb_put(skb_out, 1) = 0; /* force short packet */ /* set final frame length */ diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index e3458e3c44f1..83208d4fdc59 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -669,6 +669,22 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x05c6, 0x920d, 5)}, {QMI_FIXED_INTF(0x12d1, 0x140c, 1)}, /* Huawei E173 */ {QMI_FIXED_INTF(0x12d1, 0x14ac, 1)}, /* Huawei E1820 */ + {QMI_FIXED_INTF(0x16d8, 0x6003, 0)}, /* CMOTech 6003 */ + {QMI_FIXED_INTF(0x16d8, 0x6007, 0)}, /* CMOTech CHE-628S */ + {QMI_FIXED_INTF(0x16d8, 0x6008, 0)}, /* CMOTech CMU-301 */ + {QMI_FIXED_INTF(0x16d8, 0x6280, 0)}, /* CMOTech CHU-628 */ + {QMI_FIXED_INTF(0x16d8, 0x7001, 0)}, /* CMOTech CHU-720S */ + {QMI_FIXED_INTF(0x16d8, 0x7002, 0)}, /* CMOTech 7002 */ + {QMI_FIXED_INTF(0x16d8, 0x7003, 4)}, /* CMOTech CHU-629K */ + {QMI_FIXED_INTF(0x16d8, 0x7004, 3)}, /* CMOTech 7004 */ + {QMI_FIXED_INTF(0x16d8, 0x7006, 5)}, /* CMOTech CGU-629 */ + {QMI_FIXED_INTF(0x16d8, 0x700a, 4)}, /* CMOTech CHU-629S */ + {QMI_FIXED_INTF(0x16d8, 0x7211, 0)}, /* CMOTech CHU-720I */ + {QMI_FIXED_INTF(0x16d8, 0x7212, 0)}, /* CMOTech 7212 */ + {QMI_FIXED_INTF(0x16d8, 0x7213, 0)}, /* CMOTech 7213 */ + {QMI_FIXED_INTF(0x16d8, 0x7251, 1)}, /* CMOTech 7251 */ + {QMI_FIXED_INTF(0x16d8, 0x7252, 1)}, /* CMOTech 7252 */ + {QMI_FIXED_INTF(0x16d8, 0x7253, 1)}, /* CMOTech 7253 */ {QMI_FIXED_INTF(0x19d2, 0x0002, 1)}, {QMI_FIXED_INTF(0x19d2, 0x0012, 1)}, {QMI_FIXED_INTF(0x19d2, 0x0017, 3)}, @@ -730,16 +746,28 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */ {QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */ {QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */ + {QMI_FIXED_INTF(0x1199, 0x68c0, 8)}, /* Sierra Wireless MC73xx */ + {QMI_FIXED_INTF(0x1199, 0x68c0, 10)}, /* Sierra Wireless MC73xx */ + {QMI_FIXED_INTF(0x1199, 0x68c0, 11)}, /* Sierra Wireless MC73xx */ {QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */ + {QMI_FIXED_INTF(0x1199, 0x901f, 8)}, /* Sierra Wireless EM7355 */ + {QMI_FIXED_INTF(0x1199, 0x9041, 8)}, /* Sierra Wireless MC7305/MC7355 */ {QMI_FIXED_INTF(0x1199, 0x9051, 8)}, /* Netgear AirCard 340U */ {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ + {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)}, /* Alcatel L800MA */ {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ {QMI_FIXED_INTF(0x2357, 0x9000, 4)}, /* TP-LINK MA260 */ {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */ {QMI_FIXED_INTF(0x1bc7, 0x1201, 2)}, /* Telit LE920 */ {QMI_FIXED_INTF(0x0b3c, 0xc005, 6)}, /* Olivetti Olicard 200 */ + {QMI_FIXED_INTF(0x0b3c, 0xc00b, 4)}, /* Olivetti Olicard 500 */ {QMI_FIXED_INTF(0x1e2d, 0x0060, 4)}, /* Cinterion PLxx */ {QMI_FIXED_INTF(0x1e2d, 0x0053, 4)}, /* Cinterion PHxx,PXxx */ + {QMI_FIXED_INTF(0x413c, 0x81a2, 8)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */ + {QMI_FIXED_INTF(0x413c, 0x81a3, 8)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */ + {QMI_FIXED_INTF(0x413c, 0x81a4, 8)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */ + {QMI_FIXED_INTF(0x413c, 0x81a8, 8)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */ + {QMI_FIXED_INTF(0x413c, 0x81a9, 8)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */ /* 4. Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 7b687469199b..8a852b5f215f 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1285,7 +1285,7 @@ static int virtnet_set_channels(struct net_device *dev, if (channels->rx_count || channels->tx_count || channels->other_count) return -EINVAL; - if (queue_pairs > vi->max_queue_pairs) + if (queue_pairs > vi->max_queue_pairs || queue_pairs == 0) return -EINVAL; get_online_cpus(); diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 82355d5d155a..4dbb2ed85b97 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -389,8 +389,8 @@ static inline size_t vxlan_nlmsg_size(void) + nla_total_size(sizeof(struct nda_cacheinfo)); } -static void vxlan_fdb_notify(struct vxlan_dev *vxlan, - struct vxlan_fdb *fdb, int type) +static void vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb, + struct vxlan_rdst *rd, int type) { struct net *net = dev_net(vxlan->dev); struct sk_buff *skb; @@ -400,8 +400,7 @@ static void vxlan_fdb_notify(struct vxlan_dev *vxlan, if (skb == NULL) goto errout; - err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0, - first_remote_rtnl(fdb)); + err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0, rd); if (err < 0) { /* -EMSGSIZE implies BUG in vxlan_nlmsg_size() */ WARN_ON(err == -EMSGSIZE); @@ -427,10 +426,7 @@ static void vxlan_ip_miss(struct net_device *dev, union vxlan_addr *ipa) .remote_vni = VXLAN_N_VID, }; - INIT_LIST_HEAD(&f.remotes); - list_add_rcu(&remote.list, &f.remotes); - - vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH); + vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH); } static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN]) @@ -438,11 +434,11 @@ static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN]) struct vxlan_fdb f = { .state = NUD_STALE, }; + struct vxlan_rdst remote = { }; - INIT_LIST_HEAD(&f.remotes); memcpy(f.eth_addr, eth_addr, ETH_ALEN); - vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH); + vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH); } /* Hash Ethernet address */ @@ -533,7 +529,8 @@ static int vxlan_fdb_replace(struct vxlan_fdb *f, /* Add/update destinations for multicast */ static int vxlan_fdb_append(struct vxlan_fdb *f, - union vxlan_addr *ip, __be16 port, __u32 vni, __u32 ifindex) + union vxlan_addr *ip, __be16 port, __u32 vni, + __u32 ifindex, struct vxlan_rdst **rdp) { struct vxlan_rdst *rd; @@ -551,6 +548,7 @@ static int vxlan_fdb_append(struct vxlan_fdb *f, list_add_tail_rcu(&rd->list, &f->remotes); + *rdp = rd; return 1; } @@ -690,6 +688,7 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan, __be16 port, __u32 vni, __u32 ifindex, __u8 ndm_flags) { + struct vxlan_rdst *rd = NULL; struct vxlan_fdb *f; int notify = 0; @@ -726,7 +725,8 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan, if ((flags & NLM_F_APPEND) && (is_multicast_ether_addr(f->eth_addr) || is_zero_ether_addr(f->eth_addr))) { - int rc = vxlan_fdb_append(f, ip, port, vni, ifindex); + int rc = vxlan_fdb_append(f, ip, port, vni, ifindex, + &rd); if (rc < 0) return rc; @@ -756,15 +756,18 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan, INIT_LIST_HEAD(&f->remotes); memcpy(f->eth_addr, mac, ETH_ALEN); - vxlan_fdb_append(f, ip, port, vni, ifindex); + vxlan_fdb_append(f, ip, port, vni, ifindex, &rd); ++vxlan->addrcnt; hlist_add_head_rcu(&f->hlist, vxlan_fdb_head(vxlan, mac)); } - if (notify) - vxlan_fdb_notify(vxlan, f, RTM_NEWNEIGH); + if (notify) { + if (rd == NULL) + rd = first_remote_rtnl(f); + vxlan_fdb_notify(vxlan, f, rd, RTM_NEWNEIGH); + } return 0; } @@ -785,7 +788,7 @@ static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f) "delete %pM\n", f->eth_addr); --vxlan->addrcnt; - vxlan_fdb_notify(vxlan, f, RTM_DELNEIGH); + vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_DELNEIGH); hlist_del_rcu(&f->hlist); call_rcu(&f->rcu, vxlan_fdb_free); @@ -919,6 +922,7 @@ static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], */ if (rd && !list_is_singular(&f->remotes)) { list_del_rcu(&rd->list); + vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH); kfree_rcu(rd, rcu); goto out; } @@ -993,7 +997,7 @@ static bool vxlan_snoop(struct net_device *dev, rdst->remote_ip = *src_ip; f->updated = jiffies; - vxlan_fdb_notify(vxlan, f, RTM_NEWNEIGH); + vxlan_fdb_notify(vxlan, f, rdst, RTM_NEWNEIGH); } else { /* learned new entry */ spin_lock(&vxlan->hash_lock); diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index a0398fe3eb28..be3eb2a8d602 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -86,7 +86,6 @@ static int ath_ahb_probe(struct platform_device *pdev) int irq; int ret = 0; struct ath_hw *ah; - struct ath_common *common; char hw_name[64]; if (!dev_get_platdata(&pdev->dev)) { @@ -146,9 +145,6 @@ static int ath_ahb_probe(struct platform_device *pdev) wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n", hw_name, (unsigned long)mem, irq); - common = ath9k_hw_common(sc->sc_ah); - /* Will be cleared in ath9k_start() */ - set_bit(ATH_OP_INVALID, &common->op_flags); return 0; err_irq: diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 6d47783f2e5b..ba502a2d199b 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -155,6 +155,9 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel, ATH9K_ANI_RSSI_THR_LOW, ATH9K_ANI_RSSI_THR_HIGH); + if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_OFDM_DEF_LEVEL) + immunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL; + if (!scan) aniState->ofdmNoiseImmunityLevel = immunityLevel; @@ -235,6 +238,9 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel, BEACON_RSSI(ah), ATH9K_ANI_RSSI_THR_LOW, ATH9K_ANI_RSSI_THR_HIGH); + if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_CCK_DEF_LEVEL) + immunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; + if (ah->opmode == NL80211_IFTYPE_STATION && BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_LOW && immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 44d74495c4de..3ba03dde4215 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -251,7 +251,6 @@ struct ath_atx_tid { s8 bar_index; bool sched; - bool paused; bool active; }; diff --git a/drivers/net/wireless/ath/ath9k/debug_sta.c b/drivers/net/wireless/ath/ath9k/debug_sta.c index d76e6e0120d2..ffca918ff16a 100644 --- a/drivers/net/wireless/ath/ath9k/debug_sta.c +++ b/drivers/net/wireless/ath/ath9k/debug_sta.c @@ -72,7 +72,7 @@ static ssize_t read_file_node_aggr(struct file *file, char __user *user_buf, ath_txq_lock(sc, txq); if (tid->active) { len += scnprintf(buf + len, size - len, - "%3d%11d%10d%10d%10d%10d%9d%6d%8d\n", + "%3d%11d%10d%10d%10d%10d%9d%6d\n", tid->tidno, tid->seq_start, tid->seq_next, @@ -80,8 +80,7 @@ static ssize_t read_file_node_aggr(struct file *file, char __user *user_buf, tid->baw_head, tid->baw_tail, tid->bar_index, - tid->sched, - tid->paused); + tid->sched); } ath_txq_unlock(sc, txq); } diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index cbbb02a6b13b..36ae6490e554 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -783,6 +783,9 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, common = ath9k_hw_common(ah); ath9k_set_hw_capab(sc, hw); + /* Will be cleared in ath9k_start() */ + set_bit(ATH_OP_INVALID, &common->op_flags); + /* Initialize regulatory */ error = ath_regd_init(&common->regulatory, sc->hw->wiphy, ath9k_reg_notifier); diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 25304adece57..914dbc6b1720 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -784,7 +784,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct ath_softc *sc; struct ieee80211_hw *hw; - struct ath_common *common; u8 csz; u32 val; int ret = 0; @@ -877,10 +876,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n", hw_name, (unsigned long)sc->mem, pdev->irq); - /* Will be cleared in ath9k_start() */ - common = ath9k_hw_common(sc->sc_ah); - set_bit(ATH_OP_INVALID, &common->op_flags); - return 0; err_init: diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 6c9accdb52e4..19df969ec909 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -975,6 +975,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) u64 tsf = 0; unsigned long flags; dma_addr_t new_buf_addr; + unsigned int budget = 512; if (edma) dma_type = DMA_BIDIRECTIONAL; @@ -1113,15 +1114,17 @@ requeue_drop_frag: } requeue: list_add_tail(&bf->list, &sc->rx.rxbuf); - if (flush) - continue; if (edma) { ath_rx_edma_buf_link(sc, qtype); } else { ath_rx_buf_relink(sc, bf); - ath9k_hw_rxena(ah); + if (!flush) + ath9k_hw_rxena(ah); } + + if (!budget--) + break; } while (1); if (!(ah->imask & ATH9K_INT_RXEOL)) { diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 87cbec47fb48..66acb2cbd9df 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -107,9 +107,6 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid) { struct ath_atx_ac *ac = tid->ac; - if (tid->paused) - return; - if (tid->sched) return; @@ -1407,7 +1404,6 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, ath_tx_tid_change_state(sc, txtid); txtid->active = true; - txtid->paused = true; *ssn = txtid->seq_start = txtid->seq_next; txtid->bar_index = -1; @@ -1427,7 +1423,6 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) ath_txq_lock(sc, txq); txtid->active = false; - txtid->paused = false; ath_tx_flush_tid(sc, txtid); ath_tx_tid_change_state(sc, txtid); ath_txq_unlock_complete(sc, txq); @@ -1487,7 +1482,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) ath_txq_lock(sc, txq); ac->clear_ps_filter = true; - if (!tid->paused && ath_tid_has_buffered(tid)) { + if (ath_tid_has_buffered(tid)) { ath_tx_queue_tid(txq, tid); ath_txq_schedule(sc, txq); } @@ -1510,7 +1505,6 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, ath_txq_lock(sc, txq); tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; - tid->paused = false; if (ath_tid_has_buffered(tid)) { ath_tx_queue_tid(txq, tid); @@ -1544,8 +1538,6 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, continue; tid = ATH_AN_2_TID(an, i); - if (tid->paused) - continue; ath_txq_lock(sc, tid->ac->txq); while (nframes > 0) { @@ -1844,9 +1836,6 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) list_del(&tid->list); tid->sched = false; - if (tid->paused) - continue; - if (ath_tx_sched_aggr(sc, txq, tid, &stop)) sent = true; @@ -2698,7 +2687,6 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) tid->baw_size = WME_MAX_BA; tid->baw_head = tid->baw_tail = 0; tid->sched = false; - tid->paused = false; tid->active = false; __skb_queue_head_init(&tid->buf_q); __skb_queue_head_init(&tid->retry_q); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c index df130ef53d1c..c7c9f15c0fe0 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c @@ -303,10 +303,10 @@ static void brcmf_chip_ai_coredisable(struct brcmf_core_priv *core, ci = core->chip; - /* if core is already in reset, just return */ + /* if core is already in reset, skip reset */ regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL); if ((regdata & BCMA_RESET_CTL_RESET) != 0) - return; + goto in_reset_configure; /* configure reset */ ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL, @@ -322,6 +322,7 @@ static void brcmf_chip_ai_coredisable(struct brcmf_core_priv *core, SPINWAIT(ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) != BCMA_RESET_CTL_RESET, 300); +in_reset_configure: /* in-reset configure */ ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL, reset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK); diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index ddeb5a709aa3..a87ee9b6585a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -621,20 +621,18 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, bss_conf->bssid); /* - * Update the beacon. This is only required on USB devices. PCI - * devices fetch beacons periodically. - */ - if (changes & BSS_CHANGED_BEACON && rt2x00_is_usb(rt2x00dev)) - rt2x00queue_update_beacon(rt2x00dev, vif); - - /* * Start/stop beaconing. */ if (changes & BSS_CHANGED_BEACON_ENABLED) { if (!bss_conf->enable_beacon && intf->enable_beacon) { - rt2x00queue_clear_beacon(rt2x00dev, vif); rt2x00dev->intf_beaconing--; intf->enable_beacon = false; + /* + * Clear beacon in the H/W for this vif. This is needed + * to disable beaconing on this particular interface + * and keep it running on other interfaces. + */ + rt2x00queue_clear_beacon(rt2x00dev, vif); if (rt2x00dev->intf_beaconing == 0) { /* @@ -645,11 +643,15 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, rt2x00queue_stop_queue(rt2x00dev->bcn); mutex_unlock(&intf->beacon_skb_mutex); } - - } else if (bss_conf->enable_beacon && !intf->enable_beacon) { rt2x00dev->intf_beaconing++; intf->enable_beacon = true; + /* + * Upload beacon to the H/W. This is only required on + * USB devices. PCI devices fetch beacons periodically. + */ + if (rt2x00_is_usb(rt2x00dev)) + rt2x00queue_update_beacon(rt2x00dev, vif); if (rt2x00dev->intf_beaconing == 1) { /* diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c index 06ef47cd6203..5b4c225396f2 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c @@ -293,7 +293,7 @@ static void _rtl88ee_translate_rx_signal_stuff(struct ieee80211_hw *hw, u8 *psaddr; __le16 fc; u16 type, ufc; - bool match_bssid, packet_toself, packet_beacon, addr; + bool match_bssid, packet_toself, packet_beacon = false, addr; tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 68b5c7e92cfb..07cb06da6729 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c @@ -1001,7 +1001,7 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw) err = _rtl92cu_init_mac(hw); if (err) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "init mac failed!\n"); - return err; + goto exit; } err = rtl92c_download_fw(hw); if (err) { diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c index 36b48be8329c..2b3c78baa9f8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c @@ -49,6 +49,12 @@ static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 skb_queue) if (ieee80211_is_nullfunc(fc)) return QSLT_HIGH; + /* Kernel commit 1bf4bbb4024dcdab changed EAPOL packets to use + * queue V0 at priority 7; however, the RTL8192SE appears to have + * that queue at priority 6 + */ + if (skb->priority == 7) + return QSLT_VO; return skb->priority; } diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 9bcf2cf19357..5aeb89411350 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -364,7 +364,7 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) memset(r, 0, sizeof(*r)); /* - * Get optional "interrupts-names" property to add a name + * Get optional "interrupt-names" property to add a name * to the resource. */ of_property_read_string_index(dev, "interrupt-names", index, @@ -380,6 +380,32 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) EXPORT_SYMBOL_GPL(of_irq_to_resource); /** + * of_irq_get - Decode a node's IRQ and return it as a Linux irq number + * @dev: pointer to device tree node + * @index: zero-based index of the irq + * + * Returns Linux irq number on success, or -EPROBE_DEFER if the irq domain + * is not yet created. + * + */ +int of_irq_get(struct device_node *dev, int index) +{ + int rc; + struct of_phandle_args oirq; + struct irq_domain *domain; + + rc = of_irq_parse_one(dev, index, &oirq); + if (rc) + return rc; + + domain = irq_find_host(oirq.np); + if (!domain) + return -EPROBE_DEFER; + + return irq_create_of_mapping(&oirq); +} + +/** * of_irq_count - Count the number of IRQs a node uses * @dev: pointer to device tree node */ diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 404d1daebefa..bd47fbc53dc9 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -168,7 +168,9 @@ struct platform_device *of_device_alloc(struct device_node *np, rc = of_address_to_resource(np, i, res); WARN_ON(rc); } - WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq); + if (of_irq_to_resource_table(np, res, num_irq) != num_irq) + pr_debug("not all legacy IRQ resources mapped for %s\n", + np->name); } dev->dev.of_node = of_node_get(np); diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c index ae4450070503..fe70b86bcffb 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/selftest.c @@ -10,6 +10,7 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_irq.h> +#include <linux/of_platform.h> #include <linux/list.h> #include <linux/mutex.h> #include <linux/slab.h> @@ -427,6 +428,36 @@ static void __init of_selftest_match_node(void) } } +static void __init of_selftest_platform_populate(void) +{ + int irq; + struct device_node *np; + struct platform_device *pdev; + + np = of_find_node_by_path("/testcase-data"); + of_platform_populate(np, of_default_bus_match_table, NULL, NULL); + + /* Test that a missing irq domain returns -EPROBE_DEFER */ + np = of_find_node_by_path("/testcase-data/testcase-device1"); + pdev = of_find_device_by_node(np); + if (!pdev) + selftest(0, "device 1 creation failed\n"); + irq = platform_get_irq(pdev, 0); + if (irq != -EPROBE_DEFER) + selftest(0, "device deferred probe failed - %d\n", irq); + + /* Test that a parsing failure does not return -EPROBE_DEFER */ + np = of_find_node_by_path("/testcase-data/testcase-device2"); + pdev = of_find_device_by_node(np); + if (!pdev) + selftest(0, "device 2 creation failed\n"); + irq = platform_get_irq(pdev, 0); + if (irq >= 0 || irq == -EPROBE_DEFER) + selftest(0, "device parsing error failed - %d\n", irq); + + selftest(1, "passed"); +} + static int __init of_selftest(void) { struct device_node *np; @@ -445,6 +476,7 @@ static int __init of_selftest(void) of_selftest_parse_interrupts(); of_selftest_parse_interrupts_extended(); of_selftest_match_node(); + of_selftest_platform_populate(); pr_info("end of selftest - %i passed, %i failed\n", selftest_results.passed, selftest_results.failed); return 0; diff --git a/drivers/of/testcase-data/tests-interrupts.dtsi b/drivers/of/testcase-data/tests-interrupts.dtsi index c843720bd3e5..da4695f60351 100644 --- a/drivers/of/testcase-data/tests-interrupts.dtsi +++ b/drivers/of/testcase-data/tests-interrupts.dtsi @@ -54,5 +54,18 @@ <&test_intmap1 1 2>; }; }; + + testcase-device1 { + compatible = "testcase-device"; + interrupt-parent = <&test_intc0>; + interrupts = <1>; + }; + + testcase-device2 { + compatible = "testcase-device"; + interrupt-parent = <&test_intc2>; + interrupts = <1>; /* invalid specifier - too short */ + }; }; + }; diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index d3d1cfd51e09..e384e2534594 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c @@ -293,6 +293,58 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port, return PCIBIOS_SUCCESSFUL; } +/* + * Remove windows, starting from the largest ones to the smallest + * ones. + */ +static void mvebu_pcie_del_windows(struct mvebu_pcie_port *port, + phys_addr_t base, size_t size) +{ + while (size) { + size_t sz = 1 << (fls(size) - 1); + + mvebu_mbus_del_window(base, sz); + base += sz; + size -= sz; + } +} + +/* + * MBus windows can only have a power of two size, but PCI BARs do not + * have this constraint. Therefore, we have to split the PCI BAR into + * areas each having a power of two size. We start from the largest + * one (i.e highest order bit set in the size). + */ +static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port, + unsigned int target, unsigned int attribute, + phys_addr_t base, size_t size, + phys_addr_t remap) +{ + size_t size_mapped = 0; + + while (size) { + size_t sz = 1 << (fls(size) - 1); + int ret; + + ret = mvebu_mbus_add_window_remap_by_id(target, attribute, base, + sz, remap); + if (ret) { + dev_err(&port->pcie->pdev->dev, + "Could not create MBus window at 0x%x, size 0x%x: %d\n", + base, sz, ret); + mvebu_pcie_del_windows(port, base - size_mapped, + size_mapped); + return; + } + + size -= sz; + size_mapped += sz; + base += sz; + if (remap != MVEBU_MBUS_NO_REMAP) + remap += sz; + } +} + static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) { phys_addr_t iobase; @@ -304,8 +356,8 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) /* If a window was configured, remove it */ if (port->iowin_base) { - mvebu_mbus_del_window(port->iowin_base, - port->iowin_size); + mvebu_pcie_del_windows(port, port->iowin_base, + port->iowin_size); port->iowin_base = 0; port->iowin_size = 0; } @@ -331,11 +383,11 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) port->iowin_base = port->pcie->io.start + iobase; port->iowin_size = ((0xFFF | ((port->bridge.iolimit & 0xF0) << 8) | (port->bridge.iolimitupper << 16)) - - iobase); + iobase) + 1; - mvebu_mbus_add_window_remap_by_id(port->io_target, port->io_attr, - port->iowin_base, port->iowin_size, - iobase); + mvebu_pcie_add_windows(port, port->io_target, port->io_attr, + port->iowin_base, port->iowin_size, + iobase); } static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) @@ -346,8 +398,8 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) /* If a window was configured, remove it */ if (port->memwin_base) { - mvebu_mbus_del_window(port->memwin_base, - port->memwin_size); + mvebu_pcie_del_windows(port, port->memwin_base, + port->memwin_size); port->memwin_base = 0; port->memwin_size = 0; } @@ -364,10 +416,11 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) port->memwin_base = ((port->bridge.membase & 0xFFF0) << 16); port->memwin_size = (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) - - port->memwin_base; + port->memwin_base + 1; - mvebu_mbus_add_window_by_id(port->mem_target, port->mem_attr, - port->memwin_base, port->memwin_size); + mvebu_pcie_add_windows(port, port->mem_target, port->mem_attr, + port->memwin_base, port->memwin_size, + MVEBU_MBUS_NO_REMAP); } /* @@ -743,14 +796,21 @@ static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev, /* * On the PCI-to-PCI bridge side, the I/O windows must have at - * least a 64 KB size and be aligned on their size, and the - * memory windows must have at least a 1 MB size and be - * aligned on their size + * least a 64 KB size and the memory windows must have at + * least a 1 MB size. Moreover, MBus windows need to have a + * base address aligned on their size, and their size must be + * a power of two. This means that if the BAR doesn't have a + * power of two size, several MBus windows will actually be + * created. We need to ensure that the biggest MBus window + * (which will be the first one) is aligned on its size, which + * explains the rounddown_pow_of_two() being done here. */ if (res->flags & IORESOURCE_IO) - return round_up(start, max_t(resource_size_t, SZ_64K, size)); + return round_up(start, max_t(resource_size_t, SZ_64K, + rounddown_pow_of_two(size))); else if (res->flags & IORESOURCE_MEM) - return round_up(start, max_t(resource_size_t, SZ_1M, size)); + return round_up(start, max_t(resource_size_t, SZ_1M, + rounddown_pow_of_two(size))); else return start; } diff --git a/drivers/pinctrl/pinctrl-as3722.c b/drivers/pinctrl/pinctrl-as3722.c index 92ed4b2e3c07..c862f9c0e9ce 100644 --- a/drivers/pinctrl/pinctrl-as3722.c +++ b/drivers/pinctrl/pinctrl-as3722.c @@ -64,7 +64,6 @@ struct as3722_pin_function { }; struct as3722_gpio_pin_control { - bool enable_gpio_invert; unsigned mode_prop; int io_function; }; @@ -320,10 +319,8 @@ static int as3722_pinctrl_gpio_set_direction(struct pinctrl_dev *pctldev, return mode; } - if (as_pci->gpio_control[offset].enable_gpio_invert) - mode |= AS3722_GPIO_INV; - - return as3722_write(as3722, AS3722_GPIOn_CONTROL_REG(offset), mode); + return as3722_update_bits(as3722, AS3722_GPIOn_CONTROL_REG(offset), + AS3722_GPIO_MODE_MASK, mode); } static const struct pinmux_ops as3722_pinmux_ops = { @@ -496,10 +493,18 @@ static void as3722_gpio_set(struct gpio_chip *chip, unsigned offset, { struct as3722_pctrl_info *as_pci = to_as_pci(chip); struct as3722 *as3722 = as_pci->as3722; - int en_invert = as_pci->gpio_control[offset].enable_gpio_invert; + int en_invert; u32 val; int ret; + ret = as3722_read(as3722, AS3722_GPIOn_CONTROL_REG(offset), &val); + if (ret < 0) { + dev_err(as_pci->dev, + "GPIO_CONTROL%d_REG read failed: %d\n", offset, ret); + return; + } + en_invert = !!(val & AS3722_GPIO_INV); + if (value) val = (en_invert) ? 0 : AS3722_GPIOn_SIGNAL(offset); else diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 81075f2a1d3f..2960557bfed9 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -810,6 +810,7 @@ static const struct pinconf_ops pcs_pinconf_ops = { static int pcs_add_pin(struct pcs_device *pcs, unsigned offset, unsigned pin_pos) { + struct pcs_soc_data *pcs_soc = &pcs->socdata; struct pinctrl_pin_desc *pin; struct pcs_name *pn; int i; @@ -821,6 +822,18 @@ static int pcs_add_pin(struct pcs_device *pcs, unsigned offset, return -ENOMEM; } + if (pcs_soc->irq_enable_mask) { + unsigned val; + + val = pcs->read(pcs->base + offset); + if (val & pcs_soc->irq_enable_mask) { + dev_dbg(pcs->dev, "irq enabled at boot for pin at %lx (%x), clearing\n", + (unsigned long)pcs->res->start + offset, val); + val &= ~pcs_soc->irq_enable_mask; + pcs->write(val, pcs->base + offset); + } + } + pin = &pcs->pins.pa[i]; pn = &pcs->names[i]; sprintf(pn->name, "%lx.%d", diff --git a/drivers/pinctrl/pinctrl-tb10x.c b/drivers/pinctrl/pinctrl-tb10x.c index c5e0f6973a3b..26ca6855f478 100644 --- a/drivers/pinctrl/pinctrl-tb10x.c +++ b/drivers/pinctrl/pinctrl-tb10x.c @@ -629,9 +629,8 @@ static int tb10x_gpio_request_enable(struct pinctrl_dev *pctl, */ for (i = 0; i < state->pinfuncgrpcnt; i++) { const struct tb10x_pinfuncgrp *pfg = &state->pingroups[i]; - unsigned int port = pfg->port; unsigned int mode = pfg->mode; - int j; + int j, port = pfg->port; /* * Skip pin groups which are always mapped and don't need diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c index 48093719167a..f5cd3f961808 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c @@ -4794,8 +4794,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_MSIOF0_SCK_B, 0, /* IP5_23_21 [3] */ FN_WE1_N, FN_IERX, FN_CAN1_RX, FN_VI1_G4, - FN_VI1_G4_B, FN_VI2_R6, FN_SCIFA0_CTS_N_B, - FN_IERX_C, 0, + FN_VI1_G4_B, FN_VI2_R6, FN_SCIFA0_CTS_N_B, FN_IERX_C, /* IP5_20_18 [3] */ FN_WE0_N, FN_IECLK, FN_CAN_CLK, FN_VI2_VSYNC_N, FN_SCIFA0_TXD_B, FN_VI2_VSYNC_N_B, 0, 0, diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c index 5186d70c49d4..7868bf3a0f91 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c @@ -5288,7 +5288,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { /* SEL_SCIF3 [2] */ FN_SEL_SCIF3_0, FN_SEL_SCIF3_1, FN_SEL_SCIF3_2, FN_SEL_SCIF3_3, /* SEL_IEB [2] */ - FN_SEL_IEB_0, FN_SEL_IEB_1, FN_SEL_IEB_2, + FN_SEL_IEB_0, FN_SEL_IEB_1, FN_SEL_IEB_2, 0, /* SEL_MMC [1] */ FN_SEL_MMC_0, FN_SEL_MMC_1, /* SEL_SCIF5 [1] */ diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 9f611cbbc294..c31aa07b3ba5 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -83,8 +83,7 @@ static int pnpacpi_set_resources(struct pnp_dev *dev) { struct acpi_device *acpi_dev; acpi_handle handle; - struct acpi_buffer buffer; - int ret; + int ret = 0; pnp_dbg(&dev->dev, "set resources\n"); @@ -97,19 +96,26 @@ static int pnpacpi_set_resources(struct pnp_dev *dev) if (WARN_ON_ONCE(acpi_dev != dev->data)) dev->data = acpi_dev; - ret = pnpacpi_build_resource_template(dev, &buffer); - if (ret) - return ret; - ret = pnpacpi_encode_resources(dev, &buffer); - if (ret) { + if (acpi_has_method(handle, METHOD_NAME__SRS)) { + struct acpi_buffer buffer; + + ret = pnpacpi_build_resource_template(dev, &buffer); + if (ret) + return ret; + + ret = pnpacpi_encode_resources(dev, &buffer); + if (!ret) { + acpi_status status; + + status = acpi_set_current_resources(handle, &buffer); + if (ACPI_FAILURE(status)) + ret = -EIO; + } kfree(buffer.pointer); - return ret; } - if (ACPI_FAILURE(acpi_set_current_resources(handle, &buffer))) - ret = -EINVAL; - else if (acpi_bus_power_manageable(handle)) + if (!ret && acpi_bus_power_manageable(handle)) ret = acpi_bus_set_power(handle, ACPI_STATE_D0); - kfree(buffer.pointer); + return ret; } @@ -117,7 +123,7 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev) { struct acpi_device *acpi_dev; acpi_handle handle; - int ret; + acpi_status status; dev_dbg(&dev->dev, "disable resources\n"); @@ -128,13 +134,15 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev) } /* acpi_unregister_gsi(pnp_irq(dev, 0)); */ - ret = 0; if (acpi_bus_power_manageable(handle)) acpi_bus_set_power(handle, ACPI_STATE_D3_COLD); - /* continue even if acpi_bus_set_power() fails */ - if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DIS", NULL, NULL))) - ret = -ENODEV; - return ret; + + /* continue even if acpi_bus_set_power() fails */ + status = acpi_evaluate_object(handle, "_DIS", NULL, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) + return -ENODEV; + + return 0; } #ifdef CONFIG_ACPI_SLEEP diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c index deb7f4bcdb7b..438d4c72c7b3 100644 --- a/drivers/pnp/pnpbios/bioscalls.c +++ b/drivers/pnp/pnpbios/bioscalls.c @@ -37,7 +37,7 @@ __visible struct { * kernel begins at offset 3GB... */ -asmlinkage void pnp_bios_callfunc(void); +asmlinkage __visible void pnp_bios_callfunc(void); __asm__(".text \n" __ALIGN_STR "\n" diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index 3736bc408adb..ebf0d6710b5a 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c @@ -335,7 +335,7 @@ static void quirk_amd_mmconfig_area(struct pnp_dev *dev) } #endif -#ifdef CONFIG_X86 +#ifdef CONFIG_PCI /* Device IDs of parts that have 32KB MCH space */ static const unsigned int mch_quirk_devices[] = { 0x0154, /* Ivy Bridge */ @@ -440,7 +440,7 @@ static struct pnp_fixup pnp_fixups[] = { #ifdef CONFIG_AMD_NB {"PNP0c01", quirk_amd_mmconfig_area}, #endif -#ifdef CONFIG_X86 +#ifdef CONFIG_PCI {"PNP0c02", quirk_intel_mch}, #endif {""} diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c index bd628a6f981d..e5f13c4310fe 100644 --- a/drivers/rtc/rtc-hym8563.c +++ b/drivers/rtc/rtc-hym8563.c @@ -569,6 +569,9 @@ static int hym8563_probe(struct i2c_client *client, if (IS_ERR(hym8563->rtc)) return PTR_ERR(hym8563->rtc); + /* the hym8563 alarm only supports a minute accuracy */ + hym8563->rtc->uie_unsupported = 1; + #ifdef CONFIG_COMMON_CLK hym8563_clkout_register_clk(hym8563); #endif diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c index 5c8f8226c848..4cdb64be061b 100644 --- a/drivers/rtc/rtc-pcf8523.c +++ b/drivers/rtc/rtc-pcf8523.c @@ -206,7 +206,7 @@ static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_hour = bcd2bin(regs[2] & 0x3f); tm->tm_mday = bcd2bin(regs[3] & 0x3f); tm->tm_wday = regs[4] & 0x7; - tm->tm_mon = bcd2bin(regs[5] & 0x1f); + tm->tm_mon = bcd2bin(regs[5] & 0x1f) - 1; tm->tm_year = bcd2bin(regs[6]) + 100; return rtc_valid_tm(tm); @@ -229,7 +229,7 @@ static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm) regs[3] = bin2bcd(tm->tm_hour); regs[4] = bin2bcd(tm->tm_mday); regs[5] = tm->tm_wday; - regs[6] = bin2bcd(tm->tm_mon); + regs[6] = bin2bcd(tm->tm_mon + 1); regs[7] = bin2bcd(tm->tm_year - 100); msg.addr = client->addr; diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 9f0ea6cb6922..e3bf885f4a6c 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -541,18 +541,27 @@ static void chsc_process_sei_nt0(struct chsc_sei_nt0_area *sei_area) static void chsc_process_event_information(struct chsc_sei *sei, u64 ntsm) { - do { + static int ntsm_unsupported; + + while (true) { memset(sei, 0, sizeof(*sei)); sei->request.length = 0x0010; sei->request.code = 0x000e; - sei->ntsm = ntsm; + if (!ntsm_unsupported) + sei->ntsm = ntsm; if (chsc(sei)) break; if (sei->response.code != 0x0001) { - CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n", - sei->response.code); + CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x, ntsm=%llx)\n", + sei->response.code, sei->ntsm); + + if (sei->response.code == 3 && sei->ntsm) { + /* Fallback for old firmware. */ + ntsm_unsupported = 1; + continue; + } break; } @@ -568,7 +577,10 @@ static void chsc_process_event_information(struct chsc_sei *sei, u64 ntsm) CIO_CRW_EVENT(2, "chsc: unhandled nt: %d\n", sei->nt); break; } - } while (sei->u.nt0_area.flags & 0x80); + + if (!(sei->u.nt0_area.flags & 0x80)) + break; + } } /* diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 7f0af4fcc001..6fd7d40b2c4d 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -8293,7 +8293,6 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state) mpt2sas_base_free_resources(ioc); pci_save_state(pdev); - pci_disable_device(pdev); pci_set_power_state(pdev, device_state); return 0; } diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c index fe30ea94ffe6..109802f776ed 100644 --- a/drivers/scsi/scsi_netlink.c +++ b/drivers/scsi/scsi_netlink.c @@ -77,7 +77,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb) goto next_msg; } - if (!capable(CAP_SYS_ADMIN)) { + if (!netlink_capable(skb, CAP_SYS_ADMIN)) { err = -EPERM; goto next_msg; } diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 16bfd50cd3fe..db3b494e5926 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -750,8 +750,12 @@ static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity) vscsi->affinity_hint_set = true; } else { - for (i = 0; i < vscsi->num_queues; i++) + for (i = 0; i < vscsi->num_queues; i++) { + if (!vscsi->req_vqs[i].vq) + continue; + virtqueue_set_affinity(vscsi->req_vqs[i].vq, -1); + } vscsi->affinity_hint_set = false; } diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c index e2b482045158..017d2f8379b7 100644 --- a/drivers/staging/iio/resolver/ad2s1200.c +++ b/drivers/staging/iio/resolver/ad2s1200.c @@ -107,7 +107,7 @@ static int ad2s1200_probe(struct spi_device *spi) int pn, ret = 0; unsigned short *pins = spi->dev.platform_data; - for (pn = 0; pn < AD2S1200_PN; pn++) + for (pn = 0; pn < AD2S1200_PN; pn++) { ret = devm_gpio_request_one(&spi->dev, pins[pn], GPIOF_DIR_OUT, DRV_NAME); if (ret) { @@ -115,6 +115,7 @@ static int ad2s1200_probe(struct spi_device *spi) pins[pn]); return ret; } + } indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c index 94f9e3a38412..0ff7fda0742f 100644 --- a/drivers/tty/hvc/hvc_console.c +++ b/drivers/tty/hvc/hvc_console.c @@ -190,7 +190,7 @@ static struct tty_driver *hvc_console_device(struct console *c, int *index) return hvc_driver; } -static int __init hvc_console_setup(struct console *co, char *options) +static int hvc_console_setup(struct console *co, char *options) { if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES) return -ENODEV; diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 41fe8a047d37..fe9d129c8735 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2353,8 +2353,12 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, if (tty->ops->flush_chars) tty->ops->flush_chars(tty); } else { + struct n_tty_data *ldata = tty->disc_data; + while (nr > 0) { + mutex_lock(&ldata->output_lock); c = tty->ops->write(tty, b, nr); + mutex_unlock(&ldata->output_lock); if (c < 0) { retval = c; goto break_out; diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 0e1bf8858431..2d4bd3929e50 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -555,7 +555,7 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) */ if ((p->port.type == PORT_XR17V35X) || (p->port.type == PORT_XR17D15X)) { - serial_out(p, UART_EXAR_SLEEP, 0xff); + serial_out(p, UART_EXAR_SLEEP, sleep ? 0xff : 0); return; } diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index f1d30f6945af..cf78d1985cd8 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -255,16 +255,15 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size, if (change || left < size) { /* This is the slow path - looking for new buffers to use */ if ((n = tty_buffer_alloc(port, size)) != NULL) { - unsigned long iflags; - n->flags = flags; buf->tail = n; - - spin_lock_irqsave(&buf->flush_lock, iflags); b->commit = b->used; + /* paired w/ barrier in flush_to_ldisc(); ensures the + * latest commit value can be read before the head is + * advanced to the next buffer + */ + smp_wmb(); b->next = n; - spin_unlock_irqrestore(&buf->flush_lock, iflags); - } else if (change) size = 0; else @@ -448,27 +447,28 @@ static void flush_to_ldisc(struct work_struct *work) mutex_lock(&buf->lock); while (1) { - unsigned long flags; struct tty_buffer *head = buf->head; + struct tty_buffer *next; int count; /* Ldisc or user is trying to gain exclusive access */ if (atomic_read(&buf->priority)) break; - spin_lock_irqsave(&buf->flush_lock, flags); + next = head->next; + /* paired w/ barrier in __tty_buffer_request_room(); + * ensures commit value read is not stale if the head + * is advancing to the next buffer + */ + smp_rmb(); count = head->commit - head->read; if (!count) { - if (head->next == NULL) { - spin_unlock_irqrestore(&buf->flush_lock, flags); + if (next == NULL) break; - } - buf->head = head->next; - spin_unlock_irqrestore(&buf->flush_lock, flags); + buf->head = next; tty_buffer_free(port, head); continue; } - spin_unlock_irqrestore(&buf->flush_lock, flags); count = receive_buf(tty, head, count); if (!count) @@ -523,7 +523,6 @@ void tty_buffer_init(struct tty_port *port) struct tty_bufhead *buf = &port->buf; mutex_init(&buf->lock); - spin_lock_init(&buf->flush_lock); tty_buffer_reset(&buf->sentinel, 0); buf->head = &buf->sentinel; buf->tail = &buf->sentinel; diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index f605ad8c1902..cfd18bcca723 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1709,16 +1709,6 @@ static int at91udc_probe(struct platform_device *pdev) return -ENODEV; } - if (pdev->num_resources != 2) { - DBG("invalid num_resources\n"); - return -ENODEV; - } - if ((pdev->resource[0].flags != IORESOURCE_MEM) - || (pdev->resource[1].flags != IORESOURCE_IRQ)) { - DBG("invalid resource type\n"); - return -ENODEV; - } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENXIO; diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 6f2c8d3899d2..cf2734b532a7 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -248,7 +248,8 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, break; } - if (pdata->have_sysif_regs && pdata->controller_ver && + if (pdata->have_sysif_regs && + pdata->controller_ver > FSL_USB_VER_1_6 && (phy_mode == FSL_USB2_PHY_ULPI)) { /* check PHY_CLK_VALID to get phy clk valid */ if (!(spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) & diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index c81c8721cc5a..cd871b895013 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -90,6 +90,24 @@ __acquires(ohci->lock) dl_done_list (ohci); finish_unlinks (ohci, ohci_frame_no(ohci)); + /* + * Some controllers don't handle "global" suspend properly if + * there are unsuspended ports. For these controllers, put all + * the enabled ports into suspend before suspending the root hub. + */ + if (ohci->flags & OHCI_QUIRK_GLOBAL_SUSPEND) { + __hc32 __iomem *portstat = ohci->regs->roothub.portstatus; + int i; + unsigned temp; + + for (i = 0; i < ohci->num_ports; (++i, ++portstat)) { + temp = ohci_readl(ohci, portstat); + if ((temp & (RH_PS_PES | RH_PS_PSS)) == + RH_PS_PES) + ohci_writel(ohci, RH_PS_PSS, portstat); + } + } + /* maybe resume can wake root hub */ if (ohci_to_hcd(ohci)->self.root_hub->do_remote_wakeup || autostop) { ohci->hc_control |= OHCI_CTRL_RWE; diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 90879e9ccbec..bb1509675727 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -160,6 +160,7 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd) ohci_dbg(ohci, "enabled AMD prefetch quirk\n"); } + ohci->flags |= OHCI_QUIRK_GLOBAL_SUSPEND; return 0; } diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 9250cada13f0..4550ce05af7f 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -405,6 +405,8 @@ struct ohci_hcd { #define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */ #define OHCI_QUIRK_AMD_PLL 0x200 /* AMD PLL quirk*/ #define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */ +#define OHCI_QUIRK_GLOBAL_SUSPEND 0x800 /* must suspend ports */ + // there are also chip quirks/bugs in init logic struct work_struct nec_work; /* Worker for NEC quirk */ diff --git a/drivers/usb/phy/phy-fsm-usb.c b/drivers/usb/phy/phy-fsm-usb.c index c47e5a6edde2..d03fadd2629f 100644 --- a/drivers/usb/phy/phy-fsm-usb.c +++ b/drivers/usb/phy/phy-fsm-usb.c @@ -303,17 +303,18 @@ int otg_statemachine(struct otg_fsm *fsm) otg_set_state(fsm, OTG_STATE_A_WAIT_VRISE); break; case OTG_STATE_A_WAIT_VRISE: - if (fsm->id || fsm->a_bus_drop || fsm->a_vbus_vld || - fsm->a_wait_vrise_tmout) { + if (fsm->a_vbus_vld) otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); - } + else if (fsm->id || fsm->a_bus_drop || + fsm->a_wait_vrise_tmout) + otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); break; case OTG_STATE_A_WAIT_BCON: if (!fsm->a_vbus_vld) otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); else if (fsm->b_conn) otg_set_state(fsm, OTG_STATE_A_HOST); - else if (fsm->id | fsm->a_bus_drop | fsm->a_wait_bcon_tmout) + else if (fsm->id || fsm->a_bus_drop || fsm->a_wait_bcon_tmout) otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); break; case OTG_STATE_A_HOST: diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 7ed681a714a5..6c0a542e8ec1 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -151,6 +151,21 @@ static const struct usb_device_id id_table[] = { {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9051, 0)}, /* Netgear AirCard 340U Device Management */ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9051, 2)}, /* Netgear AirCard 340U NMEA */ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9051, 3)}, /* Netgear AirCard 340U Modem */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a2, 0)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card Device Management */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a2, 2)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card NMEA */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a2, 3)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card Modem */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a3, 0)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card Device Management */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a3, 2)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card NMEA */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a3, 3)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card Modem */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a4, 0)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card Device Management */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a4, 2)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card NMEA */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a4, 3)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card Modem */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a8, 0)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card Device Management */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a8, 2)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card NMEA */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a8, 3)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card Modem */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a9, 0)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card Device Management */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a9, 2)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card NMEA */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a9, 3)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card Modem */ { } /* Terminating entry */ }; diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index 4ef2a80728f7..008d805c3d21 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -1851,7 +1851,7 @@ static int usbat_probe(struct usb_interface *intf, us->transport_name = "Shuttle USBAT"; us->transport = usbat_flash_transport; us->transport_reset = usb_stor_CB_reset; - us->max_lun = 1; + us->max_lun = 0; result = usb_stor_probe2(us); return result; diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index f4a82291894a..174a447868cd 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -234,6 +234,20 @@ UNUSUAL_DEV( 0x0421, 0x0495, 0x0370, 0x0370, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64 ), +/* Reported by Daniele Forsi <dforsi@gmail.com> */ +UNUSUAL_DEV( 0x0421, 0x04b9, 0x0350, 0x0350, + "Nokia", + "5300", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_MAX_SECTORS_64 ), + +/* Patch submitted by Victor A. Santos <victoraur.santos@gmail.com> */ +UNUSUAL_DEV( 0x0421, 0x05af, 0x0742, 0x0742, + "Nokia", + "305", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_MAX_SECTORS_64), + /* Patch submitted by Mikhail Zolotaryov <lebon@lebon.org.ua> */ UNUSUAL_DEV( 0x0421, 0x06aa, 0x1110, 0x1110, "Nokia", diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c index 96109a9972b6..84b4bfb84344 100644 --- a/drivers/xen/events/events_fifo.c +++ b/drivers/xen/events/events_fifo.c @@ -66,7 +66,22 @@ static DEFINE_PER_CPU(struct evtchn_fifo_queue, cpu_queue); static event_word_t *event_array[MAX_EVENT_ARRAY_PAGES] __read_mostly; static unsigned event_array_pages __read_mostly; +/* + * sync_set_bit() and friends must be unsigned long aligned on non-x86 + * platforms. + */ +#if !defined(CONFIG_X86) && BITS_PER_LONG > 32 + +#define BM(w) (unsigned long *)((unsigned long)w & ~0x7UL) +#define EVTCHN_FIFO_BIT(b, w) \ + (((unsigned long)w & 0x4UL) ? (EVTCHN_FIFO_ ##b + 32) : EVTCHN_FIFO_ ##b) + +#else + #define BM(w) ((unsigned long *)(w)) +#define EVTCHN_FIFO_BIT(b, w) EVTCHN_FIFO_ ##b + +#endif static inline event_word_t *event_word_from_port(unsigned port) { @@ -161,33 +176,38 @@ static void evtchn_fifo_bind_to_cpu(struct irq_info *info, unsigned cpu) static void evtchn_fifo_clear_pending(unsigned port) { event_word_t *word = event_word_from_port(port); - sync_clear_bit(EVTCHN_FIFO_PENDING, BM(word)); + sync_clear_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word)); } static void evtchn_fifo_set_pending(unsigned port) { event_word_t *word = event_word_from_port(port); - sync_set_bit(EVTCHN_FIFO_PENDING, BM(word)); + sync_set_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word)); } static bool evtchn_fifo_is_pending(unsigned port) { event_word_t *word = event_word_from_port(port); - return sync_test_bit(EVTCHN_FIFO_PENDING, BM(word)); + return sync_test_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word)); } static bool evtchn_fifo_test_and_set_mask(unsigned port) { event_word_t *word = event_word_from_port(port); - return sync_test_and_set_bit(EVTCHN_FIFO_MASKED, BM(word)); + return sync_test_and_set_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word)); } static void evtchn_fifo_mask(unsigned port) { event_word_t *word = event_word_from_port(port); - sync_set_bit(EVTCHN_FIFO_MASKED, BM(word)); + sync_set_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word)); } +static bool evtchn_fifo_is_masked(unsigned port) +{ + event_word_t *word = event_word_from_port(port); + return sync_test_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word)); +} /* * Clear MASKED, spinning if BUSY is set. */ @@ -211,7 +231,7 @@ static void evtchn_fifo_unmask(unsigned port) BUG_ON(!irqs_disabled()); clear_masked(word); - if (sync_test_bit(EVTCHN_FIFO_PENDING, BM(word))) { + if (evtchn_fifo_is_pending(port)) { struct evtchn_unmask unmask = { .port = port }; (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); } @@ -243,7 +263,7 @@ static void handle_irq_for_port(unsigned port) static void consume_one_event(unsigned cpu, struct evtchn_fifo_control_block *control_block, - unsigned priority, uint32_t *ready) + unsigned priority, unsigned long *ready) { struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu); uint32_t head; @@ -273,10 +293,9 @@ static void consume_one_event(unsigned cpu, * copy of the ready word. */ if (head == 0) - clear_bit(priority, BM(ready)); + clear_bit(priority, ready); - if (sync_test_bit(EVTCHN_FIFO_PENDING, BM(word)) - && !sync_test_bit(EVTCHN_FIFO_MASKED, BM(word))) + if (evtchn_fifo_is_pending(port) && !evtchn_fifo_is_masked(port)) handle_irq_for_port(port); q->head[priority] = head; @@ -285,7 +304,7 @@ static void consume_one_event(unsigned cpu, static void evtchn_fifo_handle_events(unsigned cpu) { struct evtchn_fifo_control_block *control_block; - uint32_t ready; + unsigned long ready; unsigned q; control_block = per_cpu(cpu_control_block, cpu); |