diff options
Diffstat (limited to 'drivers')
1691 files changed, 48153 insertions, 39270 deletions
diff --git a/drivers/accessibility/braille/braille_console.c b/drivers/accessibility/braille/braille_console.c index 359bead4b280..fdc6b593f500 100644 --- a/drivers/accessibility/braille/braille_console.c +++ b/drivers/accessibility/braille/braille_console.c @@ -225,6 +225,7 @@ static int keyboard_notifier_call(struct notifier_block *blk, case KBD_POST_KEYSYM: { unsigned char type = KTYP(param->value) - 0xf0; + if (type == KT_SPEC) { unsigned char val = KVAL(param->value); int on_off = -1; @@ -265,6 +266,7 @@ static int vt_notifier_call(struct notifier_block *blk, { struct vt_notifier_param *param = _param; struct vc_data *vc = param->vc; + switch (code) { case VT_ALLOCATE: break; @@ -273,6 +275,7 @@ static int vt_notifier_call(struct notifier_block *blk, case VT_WRITE: { unsigned char c = param->c; + if (vc->vc_num != fg_console) break; switch (c) { diff --git a/drivers/accessibility/speakup/i18n.c b/drivers/accessibility/speakup/i18n.c index 46bd50f3c3a4..bc7b47d1876f 100644 --- a/drivers/accessibility/speakup/i18n.c +++ b/drivers/accessibility/speakup/i18n.c @@ -90,6 +90,13 @@ static char *speakup_default_msgs[MSG_LAST_INDEX] = { [MSG_COLOR_YELLOW] = "yellow", [MSG_COLOR_WHITE] = "white", [MSG_COLOR_GREY] = "grey", + [MSG_COLOR_BRIGHTBLUE] "bright blue", + [MSG_COLOR_BRIGHTGREEN] "bright green", + [MSG_COLOR_BRIGHTCYAN] "bright cyan", + [MSG_COLOR_BRIGHTRED] "bright red", + [MSG_COLOR_BRIGHTMAGENTA] "bright magenta", + [MSG_COLOR_BRIGHTYELLOW] "bright yellow", + [MSG_COLOR_BRIGHTWHITE] "bright white", /* Names of key states. */ [MSG_STATE_DOUBLE] = "double", diff --git a/drivers/accessibility/speakup/i18n.h b/drivers/accessibility/speakup/i18n.h index 2a607d263234..51e3260995d9 100644 --- a/drivers/accessibility/speakup/i18n.h +++ b/drivers/accessibility/speakup/i18n.h @@ -99,7 +99,14 @@ enum msg_index_t { MSG_COLOR_YELLOW, MSG_COLOR_WHITE, MSG_COLOR_GREY, - MSG_COLORS_END = MSG_COLOR_GREY, + MSG_COLOR_BRIGHTBLUE, + MSG_COLOR_BRIGHTGREEN, + MSG_COLOR_BRIGHTCYAN, + MSG_COLOR_BRIGHTRED, + MSG_COLOR_BRIGHTMAGENTA, + MSG_COLOR_BRIGHTYELLOW, + MSG_COLOR_BRIGHTWHITE, + MSG_COLORS_END = MSG_COLOR_BRIGHTWHITE, MSG_STATES_START, MSG_STATE_DOUBLE = MSG_STATES_START, diff --git a/drivers/accessibility/speakup/main.c b/drivers/accessibility/speakup/main.c index 428fceaf9d50..d726537fa16c 100644 --- a/drivers/accessibility/speakup/main.c +++ b/drivers/accessibility/speakup/main.c @@ -389,10 +389,6 @@ static void say_attributes(struct vc_data *vc) int fg = spk_attr & 0x0f; int bg = spk_attr >> 4; - if (fg > 8) { - synth_printf("%s ", spk_msg_get(MSG_BRIGHT)); - fg -= 8; - } synth_printf("%s", spk_msg_get(MSG_COLORS_START + fg)); if (bg > 7) { synth_printf(" %s ", spk_msg_get(MSG_ON_BLINKING)); diff --git a/drivers/accessibility/speakup/spk_ttyio.c b/drivers/accessibility/speakup/spk_ttyio.c index 2e39fcf492d8..0d1f397cd896 100644 --- a/drivers/accessibility/speakup/spk_ttyio.c +++ b/drivers/accessibility/speakup/spk_ttyio.c @@ -72,7 +72,8 @@ static void spk_ttyio_ldisc_close(struct tty_struct *tty) } static int spk_ttyio_receive_buf2(struct tty_struct *tty, - const unsigned char *cp, char *fp, int count) + const unsigned char *cp, + const char *fp, int count) { struct spk_ldisc_data *ldisc_data = tty->disc_data; struct spk_synth *synth = ldisc_data->synth; @@ -104,6 +105,7 @@ static int spk_ttyio_receive_buf2(struct tty_struct *tty, static struct tty_ldisc_ops spk_ttyio_ldisc_ops = { .owner = THIS_MODULE, + .num = N_SPEAKUP, .name = "speakup_ldisc", .open = spk_ttyio_ldisc_open, .close = spk_ttyio_ldisc_close, @@ -211,14 +213,13 @@ static int spk_ttyio_initialise_ldisc(struct spk_synth *synth) void spk_ttyio_register_ldisc(void) { - if (tty_register_ldisc(N_SPEAKUP, &spk_ttyio_ldisc_ops)) + if (tty_register_ldisc(&spk_ttyio_ldisc_ops)) pr_warn("speakup: Error registering line discipline. Most synths won't work.\n"); } void spk_ttyio_unregister_ldisc(void) { - if (tty_unregister_ldisc(N_SPEAKUP)) - pr_warn("speakup: Couldn't unregister ldisc\n"); + tty_unregister_ldisc(&spk_ttyio_ldisc_ops); } static int spk_ttyio_out(struct spk_synth *in_synth, const char ch) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index fe0bb6277e4d..9d872ea477a6 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -551,3 +551,13 @@ config ACPI_PRMT bool "Platform Runtime Mechanism Support" depends on EFI && X86_64 default y + help + Platform Runtime Mechanism (PRM) is a firmware interface exposing a + set of binary executables that can be called from the AML interpreter + or directly from device drivers. + + Say Y to enable the AML interpreter to execute the PRM code. + + While this feature is optional in principle, leaving it out may + substantially increase computational overhead related to the + initialization of some server systems. diff --git a/drivers/acpi/acpi_amba.c b/drivers/acpi/acpi_amba.c index 49b781a9cd97..ab8a4e0191b1 100644 --- a/drivers/acpi/acpi_amba.c +++ b/drivers/acpi/acpi_amba.c @@ -76,6 +76,7 @@ static int amba_handler_attach(struct acpi_device *adev, case IORESOURCE_MEM: if (!address_found) { dev->res = *rentry->res; + dev->res.name = dev_name(&dev->dev); address_found = true; } break; diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index ffb4afc5aad9..42ede059728c 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -540,6 +540,15 @@ static const struct dmi_system_id video_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"), }, }, + { + .callback = video_set_report_key_events, + .driver_data = (void *)((uintptr_t)REPORT_BRIGHTNESS_KEY_EVENTS), + .ident = "Dell Vostro 3350", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3350"), + }, + }, /* * Some machines change the brightness themselves when a brightness * hotkey gets pressed, despite us telling them not to. In this case diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index ee24246d88fd..f854bcb8d010 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -304,7 +304,8 @@ static void acpi_bus_osc_negotiate_platform_control(void) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT; capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT; - capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PRM_SUPPORT; + if (IS_ENABLED(CONFIG_ACPI_PRMT)) + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PRM_SUPPORT; #ifdef CONFIG_ARM64 capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_GENERIC_INITIATOR_SUPPORT; diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c index 816bf2c34b7a..1c507804fb10 100644 --- a/drivers/acpi/x86/s2idle.c +++ b/drivers/acpi/x86/s2idle.c @@ -417,11 +417,15 @@ static int lps0_device_attach(struct acpi_device *adev, mem_sleep_current = PM_SUSPEND_TO_IDLE; /* - * Some LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U, require the - * EC GPE to be enabled while suspended for certain wakeup devices to - * work, so mark it as wakeup-capable. + * Some Intel based LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U don't + * use intel-hid or intel-vbtn but require the EC GPE to be enabled while + * suspended for certain wakeup devices to work, so mark it as wakeup-capable. + * + * Only enable on !AMD as enabling this universally causes problems for a number + * of AMD based systems. */ - acpi_ec_mark_gpe_for_wake(); + if (!acpi_s2idle_vendor_amd()) + acpi_ec_mark_gpe_for_wake(); return 0; } diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 8b93a7f291ec..ef8e44a7d288 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -30,3 +30,6 @@ obj-y += test/ ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG +# define_trace.h needs to know how to find our header +CFLAGS_trace.o := -I$(src) +obj-$(CONFIG_TRACING) += trace.o diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index c1179edc0f3b..921312a8d957 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -18,10 +18,11 @@ #include <linux/cpumask.h> #include <linux/init.h> #include <linux/percpu.h> +#include <linux/rcupdate.h> #include <linux/sched.h> #include <linux/smp.h> -static DEFINE_PER_CPU(struct scale_freq_data *, sft_data); +static DEFINE_PER_CPU(struct scale_freq_data __rcu *, sft_data); static struct cpumask scale_freq_counters_mask; static bool scale_freq_invariant; @@ -66,16 +67,20 @@ void topology_set_scale_freq_source(struct scale_freq_data *data, if (cpumask_empty(&scale_freq_counters_mask)) scale_freq_invariant = topology_scale_freq_invariant(); + rcu_read_lock(); + for_each_cpu(cpu, cpus) { - sfd = per_cpu(sft_data, cpu); + sfd = rcu_dereference(*per_cpu_ptr(&sft_data, cpu)); /* Use ARCH provided counters whenever possible */ if (!sfd || sfd->source != SCALE_FREQ_SOURCE_ARCH) { - per_cpu(sft_data, cpu) = data; + rcu_assign_pointer(per_cpu(sft_data, cpu), data); cpumask_set_cpu(cpu, &scale_freq_counters_mask); } } + rcu_read_unlock(); + update_scale_freq_invariant(true); } EXPORT_SYMBOL_GPL(topology_set_scale_freq_source); @@ -86,22 +91,32 @@ void topology_clear_scale_freq_source(enum scale_freq_source source, struct scale_freq_data *sfd; int cpu; + rcu_read_lock(); + for_each_cpu(cpu, cpus) { - sfd = per_cpu(sft_data, cpu); + sfd = rcu_dereference(*per_cpu_ptr(&sft_data, cpu)); if (sfd && sfd->source == source) { - per_cpu(sft_data, cpu) = NULL; + rcu_assign_pointer(per_cpu(sft_data, cpu), NULL); cpumask_clear_cpu(cpu, &scale_freq_counters_mask); } } + rcu_read_unlock(); + + /* + * Make sure all references to previous sft_data are dropped to avoid + * use-after-free races. + */ + synchronize_rcu(); + update_scale_freq_invariant(false); } EXPORT_SYMBOL_GPL(topology_clear_scale_freq_source); void topology_scale_freq_tick(void) { - struct scale_freq_data *sfd = *this_cpu_ptr(&sft_data); + struct scale_freq_data *sfd = rcu_dereference_sched(*this_cpu_ptr(&sft_data)); if (sfd) sfd->set_freq_scale(); diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c index 9c00d203d61e..01ef796c2055 100644 --- a/drivers/base/attribute_container.c +++ b/drivers/base/attribute_container.c @@ -284,8 +284,8 @@ fail: * matching classdev or fail all of them. * * @dev: The generic device to run the trigger for - * @fn the function to execute for each classdev. - * @undo A function to undo the work previously done in case of error + * @fn: the function to execute for each classdev. + * @undo: A function to undo the work previously done in case of error * * This function is a safe version of * attribute_container_device_trigger. It stops on the first error and @@ -343,7 +343,7 @@ attribute_container_device_trigger_safe(struct device *dev, * attribute_container_device_trigger - execute a trigger for each matching classdev * * @dev: The generic device to run the trigger for - * @fn the function to execute for each classdev. + * @fn: the function to execute for each classdev. * * This function is for executing a trigger when you need to know both * the container and the classdev. If you only care about the diff --git a/drivers/base/base.h b/drivers/base/base.h index e5f9b7e656c3..404db83ee5ec 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -152,7 +152,6 @@ extern int driver_add_groups(struct device_driver *drv, const struct attribute_group **groups); extern void driver_remove_groups(struct device_driver *drv, const struct attribute_group **groups); -int device_driver_attach(struct device_driver *drv, struct device *dev); void device_driver_detach(struct device *dev); extern char *make_class_name(const char *name, struct kobject *kobj); diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 36d0c654ea61..1f6b4bd61056 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -210,15 +210,11 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf, int err = -ENODEV; dev = bus_find_device_by_name(bus, NULL, buf); - if (dev && dev->driver == NULL && driver_match_device(drv, dev)) { + if (dev && driver_match_device(drv, dev)) { err = device_driver_attach(drv, dev); - - if (err > 0) { + if (!err) { /* success */ err = count; - } else if (err == 0) { - /* driver didn't accept device */ - err = -ENODEV; } } put_device(dev); diff --git a/drivers/base/component.c b/drivers/base/component.c index 272ba42392f0..5e79299f6c3f 100644 --- a/drivers/base/component.c +++ b/drivers/base/component.c @@ -63,7 +63,7 @@ struct master { bool bound; const struct component_master_ops *ops; - struct device *dev; + struct device *parent; struct component_match *match; }; @@ -95,7 +95,7 @@ static int component_devices_show(struct seq_file *s, void *data) seq_printf(s, "%-40s %20s\n", "master name", "status"); seq_puts(s, "-------------------------------------------------------------\n"); seq_printf(s, "%-40s %20s\n\n", - dev_name(m->dev), m->bound ? "bound" : "not bound"); + dev_name(m->parent), m->bound ? "bound" : "not bound"); seq_printf(s, "%-40s %20s\n", "device name", "status"); seq_puts(s, "-------------------------------------------------------------\n"); @@ -124,13 +124,13 @@ core_initcall(component_debug_init); static void component_master_debugfs_add(struct master *m) { - debugfs_create_file(dev_name(m->dev), 0444, component_debugfs_dir, m, + debugfs_create_file(dev_name(m->parent), 0444, component_debugfs_dir, m, &component_devices_fops); } static void component_master_debugfs_del(struct master *m) { - debugfs_remove(debugfs_lookup(dev_name(m->dev), component_debugfs_dir)); + debugfs_remove(debugfs_lookup(dev_name(m->parent), component_debugfs_dir)); } #else @@ -143,13 +143,13 @@ static void component_master_debugfs_del(struct master *m) #endif -static struct master *__master_find(struct device *dev, +static struct master *__master_find(struct device *parent, const struct component_master_ops *ops) { struct master *m; list_for_each_entry(m, &masters, node) - if (m->dev == dev && (!ops || m->ops == ops)) + if (m->parent == parent && (!ops || m->ops == ops)) return m; return NULL; @@ -189,7 +189,7 @@ static int find_components(struct master *master) struct component_match_array *mc = &match->compare[i]; struct component *c; - dev_dbg(master->dev, "Looking for component %zu\n", i); + dev_dbg(master->parent, "Looking for component %zu\n", i); if (match->compare[i].component) continue; @@ -200,7 +200,7 @@ static int find_components(struct master *master) break; } - dev_dbg(master->dev, "found component %s, duplicate %u\n", dev_name(c->dev), !!c->master); + dev_dbg(master->parent, "found component %s, duplicate %u\n", dev_name(c->dev), !!c->master); /* Attach this component to the master */ match->compare[i].duplicate = !!c->master; @@ -233,28 +233,28 @@ static int try_to_bring_up_master(struct master *master, { int ret; - dev_dbg(master->dev, "trying to bring up master\n"); + dev_dbg(master->parent, "trying to bring up master\n"); if (find_components(master)) { - dev_dbg(master->dev, "master has incomplete components\n"); + dev_dbg(master->parent, "master has incomplete components\n"); return 0; } if (component && component->master != master) { - dev_dbg(master->dev, "master is not for this component (%s)\n", + dev_dbg(master->parent, "master is not for this component (%s)\n", dev_name(component->dev)); return 0; } - if (!devres_open_group(master->dev, NULL, GFP_KERNEL)) + if (!devres_open_group(master->parent, NULL, GFP_KERNEL)) return -ENOMEM; /* Found all components */ - ret = master->ops->bind(master->dev); + ret = master->ops->bind(master->parent); if (ret < 0) { - devres_release_group(master->dev, NULL); + devres_release_group(master->parent, NULL); if (ret != -EPROBE_DEFER) - dev_info(master->dev, "master bind failed: %d\n", ret); + dev_info(master->parent, "master bind failed: %d\n", ret); return ret; } @@ -281,34 +281,28 @@ static int try_to_bring_up_masters(struct component *component) static void take_down_master(struct master *master) { if (master->bound) { - master->ops->unbind(master->dev); - devres_release_group(master->dev, NULL); + master->ops->unbind(master->parent); + devres_release_group(master->parent, NULL); master->bound = false; } } -static void component_match_release(struct device *master, - struct component_match *match) +static void devm_component_match_release(struct device *parent, void *res) { + struct component_match *match = res; unsigned int i; for (i = 0; i < match->num; i++) { struct component_match_array *mc = &match->compare[i]; if (mc->release) - mc->release(master, mc->data); + mc->release(parent, mc->data); } kfree(match->compare); } -static void devm_component_match_release(struct device *dev, void *res) -{ - component_match_release(dev, res); -} - -static int component_match_realloc(struct device *dev, - struct component_match *match, size_t num) +static int component_match_realloc(struct component_match *match, size_t num) { struct component_match_array *new; @@ -359,7 +353,7 @@ static void __component_match_add(struct device *master, size_t new_size = match->alloc + 16; int ret; - ret = component_match_realloc(master, match, new_size); + ret = component_match_realloc(match, new_size); if (ret) { *matchptr = ERR_PTR(ret); return; @@ -451,7 +445,7 @@ static void free_master(struct master *master) /** * component_master_add_with_match - register an aggregate driver - * @dev: device with the aggregate driver + * @parent: parent device of the aggregate driver * @ops: callbacks for the aggregate driver * @match: component match list for the aggregate driver * @@ -461,7 +455,7 @@ static void free_master(struct master *master) * &component_master_ops.bind from @ops. Must be unregistered by calling * component_master_del(). */ -int component_master_add_with_match(struct device *dev, +int component_master_add_with_match(struct device *parent, const struct component_master_ops *ops, struct component_match *match) { @@ -469,7 +463,7 @@ int component_master_add_with_match(struct device *dev, int ret; /* Reallocate the match array for its true size */ - ret = component_match_realloc(dev, match, match->num); + ret = component_match_realloc(match, match->num); if (ret) return ret; @@ -477,7 +471,7 @@ int component_master_add_with_match(struct device *dev, if (!master) return -ENOMEM; - master->dev = dev; + master->parent = parent; master->ops = ops; master->match = match; @@ -499,20 +493,20 @@ EXPORT_SYMBOL_GPL(component_master_add_with_match); /** * component_master_del - unregister an aggregate driver - * @dev: device with the aggregate driver + * @parent: parent device of the aggregate driver * @ops: callbacks for the aggregate driver * * Unregisters an aggregate driver registered with * component_master_add_with_match(). If necessary the aggregate driver is first * disassembled by calling &component_master_ops.unbind from @ops. */ -void component_master_del(struct device *dev, +void component_master_del(struct device *parent, const struct component_master_ops *ops) { struct master *master; mutex_lock(&component_mutex); - master = __master_find(dev, ops); + master = __master_find(parent, ops); if (master) { take_down_master(master); free_master(master); @@ -527,7 +521,7 @@ static void component_unbind(struct component *component, WARN_ON(!component->bound); if (component->ops && component->ops->unbind) - component->ops->unbind(component->dev, master->dev, data); + component->ops->unbind(component->dev, master->parent, data); component->bound = false; /* Release all resources claimed in the binding of this component */ @@ -536,14 +530,14 @@ static void component_unbind(struct component *component, /** * component_unbind_all - unbind all components of an aggregate driver - * @master_dev: device with the aggregate driver + * @parent: parent device of the aggregate driver * @data: opaque pointer, passed to all components * - * Unbinds all components of the aggregate @dev by passing @data to their + * Unbinds all components of the aggregate device by passing @data to their * &component_ops.unbind functions. Should be called from * &component_master_ops.unbind. */ -void component_unbind_all(struct device *master_dev, void *data) +void component_unbind_all(struct device *parent, void *data) { struct master *master; struct component *c; @@ -551,7 +545,7 @@ void component_unbind_all(struct device *master_dev, void *data) WARN_ON(!mutex_is_locked(&component_mutex)); - master = __master_find(master_dev, NULL); + master = __master_find(parent, NULL); if (!master) return; @@ -574,7 +568,7 @@ static int component_bind(struct component *component, struct master *master, * This allows us to roll-back a failed component without * affecting anything else. */ - if (!devres_open_group(master->dev, NULL, GFP_KERNEL)) + if (!devres_open_group(master->parent, NULL, GFP_KERNEL)) return -ENOMEM; /* @@ -583,14 +577,14 @@ static int component_bind(struct component *component, struct master *master, * at the appropriate moment. */ if (!devres_open_group(component->dev, component, GFP_KERNEL)) { - devres_release_group(master->dev, NULL); + devres_release_group(master->parent, NULL); return -ENOMEM; } - dev_dbg(master->dev, "binding %s (ops %ps)\n", + dev_dbg(master->parent, "binding %s (ops %ps)\n", dev_name(component->dev), component->ops); - ret = component->ops->bind(component->dev, master->dev, data); + ret = component->ops->bind(component->dev, master->parent, data); if (!ret) { component->bound = true; @@ -601,16 +595,16 @@ static int component_bind(struct component *component, struct master *master, * can clean those resources up independently. */ devres_close_group(component->dev, NULL); - devres_remove_group(master->dev, NULL); + devres_remove_group(master->parent, NULL); - dev_info(master->dev, "bound %s (ops %ps)\n", + dev_info(master->parent, "bound %s (ops %ps)\n", dev_name(component->dev), component->ops); } else { devres_release_group(component->dev, NULL); - devres_release_group(master->dev, NULL); + devres_release_group(master->parent, NULL); if (ret != -EPROBE_DEFER) - dev_err(master->dev, "failed to bind %s (ops %ps): %d\n", + dev_err(master->parent, "failed to bind %s (ops %ps): %d\n", dev_name(component->dev), component->ops, ret); } @@ -619,14 +613,14 @@ static int component_bind(struct component *component, struct master *master, /** * component_bind_all - bind all components of an aggregate driver - * @master_dev: device with the aggregate driver + * @parent: parent device of the aggregate driver * @data: opaque pointer, passed to all components * * Binds all components of the aggregate @dev by passing @data to their * &component_ops.bind functions. Should be called from * &component_master_ops.bind. */ -int component_bind_all(struct device *master_dev, void *data) +int component_bind_all(struct device *parent, void *data) { struct master *master; struct component *c; @@ -635,7 +629,7 @@ int component_bind_all(struct device *master_dev, void *data) WARN_ON(!mutex_is_locked(&component_mutex)); - master = __master_find(master_dev, NULL); + master = __master_find(parent, NULL); if (!master) return -EINVAL; diff --git a/drivers/base/core.c b/drivers/base/core.c index 2a61003ea2c1..cadcade65825 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2409,6 +2409,25 @@ static ssize_t online_store(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RW(online); +static ssize_t removable_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + const char *loc; + + switch (dev->removable) { + case DEVICE_REMOVABLE: + loc = "removable"; + break; + case DEVICE_FIXED: + loc = "fixed"; + break; + default: + loc = "unknown"; + } + return sysfs_emit(buf, "%s\n", loc); +} +static DEVICE_ATTR_RO(removable); + int device_add_groups(struct device *dev, const struct attribute_group **groups) { return sysfs_create_groups(&dev->kobj, groups); @@ -2586,8 +2605,16 @@ static int device_add_attrs(struct device *dev) goto err_remove_dev_online; } + if (dev_removable_is_valid(dev)) { + error = device_create_file(dev, &dev_attr_removable); + if (error) + goto err_remove_dev_waiting_for_supplier; + } + return 0; + err_remove_dev_waiting_for_supplier: + device_remove_file(dev, &dev_attr_waiting_for_supplier); err_remove_dev_online: device_remove_file(dev, &dev_attr_online); err_remove_dev_groups: @@ -2607,6 +2634,7 @@ static void device_remove_attrs(struct device *dev) struct class *class = dev->class; const struct device_type *type = dev->type; + device_remove_file(dev, &dev_attr_removable); device_remove_file(dev, &dev_attr_waiting_for_supplier); device_remove_file(dev, &dev_attr_online); device_remove_groups(dev, dev->groups); @@ -3442,7 +3470,7 @@ bool kill_device(struct device *dev) * to run while we are tearing out the bus/class/sysfs from * underneath the device. */ - lockdep_assert_held(&dev->mutex); + device_lock_assert(dev); if (dev->p->dead) return false; diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 2b9e41377a07..5ef14db97904 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -175,7 +175,7 @@ static struct attribute *crash_note_cpu_attrs[] = { NULL }; -static struct attribute_group crash_note_cpu_attr_group = { +static const struct attribute_group crash_note_cpu_attr_group = { .attrs = crash_note_cpu_attrs, }; #endif @@ -475,7 +475,7 @@ static struct attribute *cpu_root_attrs[] = { NULL }; -static struct attribute_group cpu_root_attr_group = { +static const struct attribute_group cpu_root_attr_group = { .attrs = cpu_root_attrs, }; diff --git a/drivers/base/dd.c b/drivers/base/dd.c index ecd7cf848daf..daeb9b5763ae 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -471,6 +471,8 @@ static void driver_sysfs_remove(struct device *dev) * (It is ok to call with no other effort from a driver's probe() method.) * * This function must be called with the device lock held. + * + * Callers should prefer to use device_driver_attach() instead. */ int device_bind_driver(struct device *dev) { @@ -491,15 +493,6 @@ EXPORT_SYMBOL_GPL(device_bind_driver); static atomic_t probe_count = ATOMIC_INIT(0); static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue); -static void driver_deferred_probe_add_trigger(struct device *dev, - int local_trigger_count) -{ - 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(); -} - static ssize_t state_synced_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -513,12 +506,43 @@ static ssize_t state_synced_show(struct device *dev, } static DEVICE_ATTR_RO(state_synced); + +static int call_driver_probe(struct device *dev, struct device_driver *drv) +{ + int ret = 0; + + if (dev->bus->probe) + ret = dev->bus->probe(dev); + else if (drv->probe) + ret = drv->probe(dev); + + switch (ret) { + case 0: + break; + case -EPROBE_DEFER: + /* Driver requested deferred probing */ + dev_dbg(dev, "Driver %s requests probe deferral\n", drv->name); + break; + case -ENODEV: + case -ENXIO: + pr_debug("%s: probe of %s rejects match %d\n", + drv->name, dev_name(dev), ret); + break; + default: + /* driver matched but the probe failed */ + pr_warn("%s: probe of %s failed with error %d\n", + drv->name, dev_name(dev), ret); + break; + } + + return ret; +} + static int really_probe(struct device *dev, struct device_driver *drv) { - int ret = -EPROBE_DEFER; - int local_trigger_count = atomic_read(&deferred_trigger_count); bool test_remove = IS_ENABLED(CONFIG_DEBUG_TEST_DRIVER_REMOVE) && !drv->suppress_bind_attrs; + int ret; if (defer_all_probes) { /* @@ -527,17 +551,13 @@ static int really_probe(struct device *dev, struct device_driver *drv) * wait_for_device_probe() right after that to avoid any races. */ dev_dbg(dev, "Driver %s force probe deferral\n", drv->name); - driver_deferred_probe_add(dev); - return ret; + return -EPROBE_DEFER; } ret = device_links_check_suppliers(dev); - if (ret == -EPROBE_DEFER) - driver_deferred_probe_add_trigger(dev, local_trigger_count); if (ret) return ret; - atomic_inc(&probe_count); pr_debug("bus: '%s': %s: probing driver %s with device %s\n", drv->bus->name, __func__, drv->name, dev_name(dev)); if (!list_empty(&dev->devres_head)) { @@ -572,14 +592,14 @@ re_probe: goto probe_failed; } - if (dev->bus->probe) { - ret = dev->bus->probe(dev); - if (ret) - goto probe_failed; - } else if (drv->probe) { - ret = drv->probe(dev); - if (ret) - goto probe_failed; + ret = call_driver_probe(dev, drv); + if (ret) { + /* + * Return probe errors as positive values so that the callers + * can distinguish them from other errors. + */ + ret = -ret; + goto probe_failed; } if (device_add_groups(dev, drv->dev_groups)) { @@ -621,7 +641,6 @@ re_probe: dev->pm_domain->sync(dev); driver_bound(dev); - ret = 1; pr_debug("bus: '%s': %s: bound device %s to driver %s\n", drv->bus->name, __func__, dev_name(dev), drv->name); goto done; @@ -650,31 +669,7 @@ pinctrl_bind_failed: dev->pm_domain->dismiss(dev); pm_runtime_reinit(dev); dev_pm_set_driver_flags(dev, 0); - - switch (ret) { - case -EPROBE_DEFER: - /* Driver requested deferred probing */ - dev_dbg(dev, "Driver %s requests probe deferral\n", drv->name); - driver_deferred_probe_add_trigger(dev, local_trigger_count); - break; - case -ENODEV: - case -ENXIO: - pr_debug("%s: probe of %s rejects match %d\n", - drv->name, dev_name(dev), ret); - break; - default: - /* driver matched but the probe failed */ - pr_warn("%s: probe of %s failed with error %d\n", - drv->name, dev_name(dev), ret); - } - /* - * Ignore errors returned by ->probe so that the next driver can try - * its luck. - */ - ret = 0; done: - atomic_dec(&probe_count); - wake_up_all(&probe_waitqueue); return ret; } @@ -728,25 +723,14 @@ void wait_for_device_probe(void) } EXPORT_SYMBOL_GPL(wait_for_device_probe); -/** - * driver_probe_device - attempt to bind device & driver together - * @drv: driver to bind a device to - * @dev: device to try to bind to the driver - * - * This function returns -ENODEV if the device is not registered, - * 1 if the device is bound successfully and 0 otherwise. - * - * This function must be called with @dev lock held. When called for a - * USB interface, @dev->parent lock must be held as well. - * - * If the device has a parent, runtime-resume the parent before driver probing. - */ -static int driver_probe_device(struct device_driver *drv, struct device *dev) +static int __driver_probe_device(struct device_driver *drv, struct device *dev) { int ret = 0; - if (!device_is_registered(dev)) + if (dev->p->dead || !device_is_registered(dev)) return -ENODEV; + if (dev->driver) + return -EBUSY; dev->can_match = true; pr_debug("bus: '%s': %s: matched device %s with driver %s\n", @@ -770,6 +754,42 @@ static int driver_probe_device(struct device_driver *drv, struct device *dev) return ret; } +/** + * driver_probe_device - attempt to bind device & driver together + * @drv: driver to bind a device to + * @dev: device to try to bind to the driver + * + * This function returns -ENODEV if the device is not registered, -EBUSY if it + * already has a driver, 0 if the device is bound successfully and a positive + * (inverted) error code for failures from the ->probe method. + * + * This function must be called with @dev lock held. When called for a + * USB interface, @dev->parent lock must be held as well. + * + * If the device has a parent, runtime-resume the parent before driver probing. + */ +static int driver_probe_device(struct device_driver *drv, struct device *dev) +{ + int trigger_count = atomic_read(&deferred_trigger_count); + int ret; + + atomic_inc(&probe_count); + ret = __driver_probe_device(drv, dev); + if (ret == -EPROBE_DEFER || ret == EPROBE_DEFER) { + driver_deferred_probe_add(dev); + + /* + * Did a trigger occur while probing? Need to re-trigger if yes + */ + if (trigger_count != atomic_read(&deferred_trigger_count) && + !defer_all_probes) + driver_deferred_probe_trigger(); + } + atomic_dec(&probe_count); + wake_up_all(&probe_waitqueue); + return ret; +} + static inline bool cmdline_requested_async_probing(const char *drv_name) { return parse_option_str(async_probe_drv_names, drv_name); @@ -867,7 +887,14 @@ static int __device_attach_driver(struct device_driver *drv, void *_data) if (data->check_async && async_allowed != data->want_async) return 0; - return driver_probe_device(drv, dev); + /* + * Ignore errors returned by ->probe so that the next driver can try + * its luck. + */ + ret = driver_probe_device(drv, dev); + if (ret < 0) + return ret; + return ret == 0; } static void __device_attach_async_helper(void *_dev, async_cookie_t cookie) @@ -1023,43 +1050,34 @@ static void __device_driver_unlock(struct device *dev, struct device *parent) * @dev: Device to attach it to * * Manually attach driver to a device. Will acquire both @dev lock and - * @dev->parent lock if needed. + * @dev->parent lock if needed. Returns 0 on success, -ERR on failure. */ int device_driver_attach(struct device_driver *drv, struct device *dev) { - int ret = 0; + int ret; __device_driver_lock(dev, dev->parent); - - /* - * If device has been removed or someone has already successfully - * bound a driver before us just skip the driver probe call. - */ - if (!dev->p->dead && !dev->driver) - ret = driver_probe_device(drv, dev); - + ret = __driver_probe_device(drv, dev); __device_driver_unlock(dev, dev->parent); + /* also return probe errors as normal negative errnos */ + if (ret > 0) + ret = -ret; + if (ret == -EPROBE_DEFER) + return -EAGAIN; return ret; } +EXPORT_SYMBOL_GPL(device_driver_attach); static void __driver_attach_async_helper(void *_dev, async_cookie_t cookie) { struct device *dev = _dev; struct device_driver *drv; - int ret = 0; + int ret; __device_driver_lock(dev, dev->parent); - drv = dev->p->async_driver; - - /* - * If device has been removed or someone has already successfully - * bound a driver before us just skip the driver probe call. - */ - if (!dev->p->dead && !dev->driver) - ret = driver_probe_device(drv, dev); - + ret = driver_probe_device(drv, dev); __device_driver_unlock(dev, dev->parent); dev_dbg(dev, "driver %s async attach completed: %d\n", drv->name, ret); @@ -1114,7 +1132,9 @@ static int __driver_attach(struct device *dev, void *data) return 0; } - device_driver_attach(drv, dev); + __device_driver_lock(dev, dev->parent); + driver_probe_device(drv, dev); + __device_driver_unlock(dev, dev->parent); return 0; } diff --git a/drivers/base/devcoredump.c b/drivers/base/devcoredump.c index 8eec0e0ddff7..f4d794d6bb85 100644 --- a/drivers/base/devcoredump.c +++ b/drivers/base/devcoredump.c @@ -3,10 +3,6 @@ * Copyright(c) 2014 Intel Mobile Communications GmbH * Copyright(c) 2015 Intel Deutschland GmbH * - * Contact Information: - * Intel Linux Wireless <ilw@linux.intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * * Author: Johannes Berg <johannes@sipsolutions.net> */ #include <linux/module.h> diff --git a/drivers/base/devres.c b/drivers/base/devres.c index 8746f2212781..eaa9a5cd1db9 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c @@ -14,14 +14,13 @@ #include <asm/sections.h> #include "base.h" +#include "trace.h" struct devres_node { struct list_head entry; dr_release_t release; -#ifdef CONFIG_DEBUG_DEVRES const char *name; size_t size; -#endif }; struct devres { @@ -43,10 +42,6 @@ struct devres_group { /* -- 8 pointers */ }; -#ifdef CONFIG_DEBUG_DEVRES -static int log_devres = 0; -module_param_named(log, log_devres, int, S_IRUGO | S_IWUSR); - static void set_node_dbginfo(struct devres_node *node, const char *name, size_t size) { @@ -54,7 +49,11 @@ static void set_node_dbginfo(struct devres_node *node, const char *name, node->size = size; } -static void devres_log(struct device *dev, struct devres_node *node, +#ifdef CONFIG_DEBUG_DEVRES +static int log_devres = 0; +module_param_named(log, log_devres, int, S_IRUGO | S_IWUSR); + +static void devres_dbg(struct device *dev, struct devres_node *node, const char *op) { if (unlikely(log_devres)) @@ -62,10 +61,16 @@ static void devres_log(struct device *dev, struct devres_node *node, op, node, node->name, node->size); } #else /* CONFIG_DEBUG_DEVRES */ -#define set_node_dbginfo(node, n, s) do {} while (0) -#define devres_log(dev, node, op) do {} while (0) +#define devres_dbg(dev, node, op) do {} while (0) #endif /* CONFIG_DEBUG_DEVRES */ +static void devres_log(struct device *dev, struct devres_node *node, + const char *op) +{ + trace_devres_log(dev, op, node, node->name, node->size); + devres_dbg(dev, node, op); +} + /* * Release functions for devres group. These callbacks are used only * for identification. @@ -134,26 +139,13 @@ static void replace_dr(struct device *dev, list_replace(&old->entry, &new->entry); } -#ifdef CONFIG_DEBUG_DEVRES -void * __devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp, int nid, - const char *name) -{ - struct devres *dr; - - dr = alloc_dr(release, size, gfp | __GFP_ZERO, nid); - if (unlikely(!dr)) - return NULL; - set_node_dbginfo(&dr->node, name, size); - return dr->data; -} -EXPORT_SYMBOL_GPL(__devres_alloc_node); -#else /** - * devres_alloc_node - Allocate device resource data + * __devres_alloc_node - Allocate device resource data * @release: Release function devres will be associated with * @size: Allocation size * @gfp: Allocation flags * @nid: NUMA node + * @name: Name of the resource * * Allocate devres of @size bytes. The allocated area is zeroed, then * associated with @release. The returned pointer can be passed to @@ -162,17 +154,18 @@ EXPORT_SYMBOL_GPL(__devres_alloc_node); * RETURNS: * Pointer to allocated devres on success, NULL on failure. */ -void * devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp, int nid) +void *__devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp, int nid, + const char *name) { struct devres *dr; dr = alloc_dr(release, size, gfp | __GFP_ZERO, nid); if (unlikely(!dr)) return NULL; + set_node_dbginfo(&dr->node, name, size); return dr->data; } -EXPORT_SYMBOL_GPL(devres_alloc_node); -#endif +EXPORT_SYMBOL_GPL(__devres_alloc_node); /** * devres_for_each_res - Resource iterator @@ -438,20 +431,16 @@ static int remove_nodes(struct device *dev, struct list_head *first, struct list_head *end, struct list_head *todo) { + struct devres_node *node, *n; int cnt = 0, nr_groups = 0; - struct list_head *cur; /* First pass - move normal devres entries to @todo and clear * devres_group colors. */ - cur = first; - while (cur != end) { - struct devres_node *node; + node = list_entry(first, struct devres_node, entry); + list_for_each_entry_safe_from(node, n, end, entry) { struct devres_group *grp; - node = list_entry(cur, struct devres_node, entry); - cur = cur->next; - grp = node_to_group(node); if (grp) { /* clear color of group markers in the first pass */ @@ -471,18 +460,14 @@ static int remove_nodes(struct device *dev, /* Second pass - Scan groups and color them. A group gets * color value of two iff the group is wholly contained in - * [cur, end). That is, for a closed group, both opening and - * closing markers should be in the range, while just the + * [current node, end). That is, for a closed group, both opening + * and closing markers should be in the range, while just the * opening marker is enough for an open group. */ - cur = first; - while (cur != end) { - struct devres_node *node; + node = list_entry(first, struct devres_node, entry); + list_for_each_entry_safe_from(node, n, end, entry) { struct devres_group *grp; - node = list_entry(cur, struct devres_node, entry); - cur = cur->next; - grp = node_to_group(node); BUG_ON(!grp || list_empty(&grp->node[0].entry)); @@ -492,7 +477,7 @@ static int remove_nodes(struct device *dev, BUG_ON(grp->color <= 0 || grp->color > 2); if (grp->color == 2) { - /* No need to update cur or end. The removed + /* No need to update current node or end. The removed * nodes are always before both. */ list_move_tail(&grp->node[0].entry, todo); @@ -503,28 +488,18 @@ static int remove_nodes(struct device *dev, return cnt; } -static int release_nodes(struct device *dev, struct list_head *first, - struct list_head *end, unsigned long flags) - __releases(&dev->devres_lock) +static void release_nodes(struct device *dev, struct list_head *todo) { - LIST_HEAD(todo); - int cnt; struct devres *dr, *tmp; - cnt = remove_nodes(dev, first, end, &todo); - - spin_unlock_irqrestore(&dev->devres_lock, flags); - /* Release. Note that both devres and devres_group are * handled as devres in the following loop. This is safe. */ - list_for_each_entry_safe_reverse(dr, tmp, &todo, node.entry) { + list_for_each_entry_safe_reverse(dr, tmp, todo, node.entry) { devres_log(dev, &dr->node, "REL"); dr->node.release(dev, dr->data); kfree(dr); } - - return cnt; } /** @@ -537,13 +512,23 @@ static int release_nodes(struct device *dev, struct list_head *first, int devres_release_all(struct device *dev) { unsigned long flags; + LIST_HEAD(todo); + int cnt; /* Looks like an uninitialized device structure */ if (WARN_ON(dev->devres_head.next == NULL)) return -ENODEV; + + /* Nothing to release if list is empty */ + if (list_empty(&dev->devres_head)) + return 0; + spin_lock_irqsave(&dev->devres_lock, flags); - return release_nodes(dev, dev->devres_head.next, &dev->devres_head, - flags); + cnt = remove_nodes(dev, dev->devres_head.next, &dev->devres_head, &todo); + spin_unlock_irqrestore(&dev->devres_lock, flags); + + release_nodes(dev, &todo); + return cnt; } /** @@ -679,6 +664,7 @@ int devres_release_group(struct device *dev, void *id) { struct devres_group *grp; unsigned long flags; + LIST_HEAD(todo); int cnt = 0; spin_lock_irqsave(&dev->devres_lock, flags); @@ -691,7 +677,10 @@ int devres_release_group(struct device *dev, void *id) if (!list_empty(&grp->node[1].entry)) end = grp->node[1].entry.next; - cnt = release_nodes(dev, first, end, flags); + cnt = remove_nodes(dev, first, end, &todo); + spin_unlock_irqrestore(&dev->devres_lock, flags); + + release_nodes(dev, &todo); } else { WARN_ON(1); spin_unlock_irqrestore(&dev->devres_lock, flags); diff --git a/drivers/base/firmware_loader/builtin/Makefile b/drivers/base/firmware_loader/builtin/Makefile index 5fa7ce3745a0..101754ad48d9 100644 --- a/drivers/base/firmware_loader/builtin/Makefile +++ b/drivers/base/firmware_loader/builtin/Makefile @@ -8,7 +8,6 @@ fwdir := $(addprefix $(srctree)/,$(filter-out /%,$(fwdir)))$(filter /%,$(fwdir)) obj-y := $(addsuffix .gen.o, $(subst $(quote),,$(CONFIG_EXTRA_FIRMWARE))) FWNAME = $(patsubst $(obj)/%.gen.S,%,$@) -comma := , FWSTR = $(subst $(comma),_,$(subst /,_,$(subst .,_,$(subst -,_,$(FWNAME))))) ASM_WORD = $(if $(CONFIG_64BIT),.quad,.long) ASM_ALIGN = $(if $(CONFIG_64BIT),3,2) diff --git a/drivers/base/memory.c b/drivers/base/memory.c index d5ffaab3cb61..aa31a21f33d7 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -596,7 +596,7 @@ static struct attribute *memory_memblk_attrs[] = { NULL }; -static struct attribute_group memory_memblk_attr_group = { +static const struct attribute_group memory_memblk_attr_group = { .attrs = memory_memblk_attrs, }; @@ -772,7 +772,7 @@ static struct attribute *memory_root_attrs[] = { NULL }; -static struct attribute_group memory_root_attr_group = { +static const struct attribute_group memory_root_attr_group = { .attrs = memory_root_attrs, }; diff --git a/drivers/base/node.c b/drivers/base/node.c index 9db297431b97..4a4ae868ad9f 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -233,7 +233,7 @@ static ssize_t name##_show(struct device *dev, \ return sysfs_emit(buf, fmt "\n", \ to_cache_info(dev)->cache_attrs.name); \ } \ -DEVICE_ATTR_RO(name); +static DEVICE_ATTR_RO(name); CACHE_ATTR(size, "%llu") CACHE_ATTR(line_size, "%u") @@ -1038,7 +1038,7 @@ static struct attribute *node_state_attrs[] = { NULL }; -static struct attribute_group memory_root_attr_group = { +static const struct attribute_group memory_root_attr_group = { .attrs = node_state_attrs, }; diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 9cd34def2237..8640578f45e9 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -125,26 +125,6 @@ void __iomem *devm_platform_ioremap_resource(struct platform_device *pdev, EXPORT_SYMBOL_GPL(devm_platform_ioremap_resource); /** - * devm_platform_ioremap_resource_wc - write-combined variant of - * devm_platform_ioremap_resource() - * - * @pdev: platform device to use both for memory resource lookup as well as - * resource management - * @index: resource index - * - * Return: a pointer to the remapped memory or an ERR_PTR() encoded error code - * on failure. - */ -void __iomem *devm_platform_ioremap_resource_wc(struct platform_device *pdev, - unsigned int index) -{ - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_MEM, index); - return devm_ioremap_resource_wc(&pdev->dev, res); -} - -/** * devm_platform_ioremap_resource_byname - call devm_ioremap_resource for * a platform device, retrieve the * resource by name @@ -1355,7 +1335,7 @@ static umode_t platform_dev_attrs_visible(struct kobject *kobj, struct attribute return a->mode; } -static struct attribute_group platform_dev_group = { +static const struct attribute_group platform_dev_group = { .attrs = platform_dev_attrs, .is_visible = platform_dev_attrs_visible, }; diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index ab0b740cc0f1..a934c679e6ce 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -2018,8 +2018,8 @@ int pm_genpd_init(struct generic_pm_domain *genpd, mutex_lock(&gpd_list_lock); list_add(&genpd->gpd_list_node, &gpd_list); - genpd_debug_add(genpd); mutex_unlock(&gpd_list_lock); + genpd_debug_add(genpd); return 0; } @@ -2206,12 +2206,19 @@ static int genpd_add_provider(struct device_node *np, genpd_xlate_t xlate, static bool genpd_present(const struct generic_pm_domain *genpd) { + bool ret = false; const struct generic_pm_domain *gpd; - list_for_each_entry(gpd, &gpd_list, gpd_list_node) - if (gpd == genpd) - return true; - return false; + mutex_lock(&gpd_list_lock); + list_for_each_entry(gpd, &gpd_list, gpd_list_node) { + if (gpd == genpd) { + ret = true; + break; + } + } + mutex_unlock(&gpd_list_lock); + + return ret; } /** @@ -2222,15 +2229,13 @@ static bool genpd_present(const struct generic_pm_domain *genpd) int of_genpd_add_provider_simple(struct device_node *np, struct generic_pm_domain *genpd) { - int ret = -EINVAL; + int ret; if (!np || !genpd) return -EINVAL; - mutex_lock(&gpd_list_lock); - if (!genpd_present(genpd)) - goto unlock; + return -EINVAL; genpd->dev.of_node = np; @@ -2241,7 +2246,7 @@ int of_genpd_add_provider_simple(struct device_node *np, if (ret != -EPROBE_DEFER) dev_err(&genpd->dev, "Failed to add OPP table: %d\n", ret); - goto unlock; + return ret; } /* @@ -2259,16 +2264,13 @@ int of_genpd_add_provider_simple(struct device_node *np, dev_pm_opp_of_remove_table(&genpd->dev); } - goto unlock; + return ret; } genpd->provider = &np->fwnode; genpd->has_provider = true; -unlock: - mutex_unlock(&gpd_list_lock); - - return ret; + return 0; } EXPORT_SYMBOL_GPL(of_genpd_add_provider_simple); @@ -2287,8 +2289,6 @@ int of_genpd_add_provider_onecell(struct device_node *np, if (!np || !data) return -EINVAL; - mutex_lock(&gpd_list_lock); - if (!data->xlate) data->xlate = genpd_xlate_onecell; @@ -2328,8 +2328,6 @@ int of_genpd_add_provider_onecell(struct device_node *np, if (ret < 0) goto error; - mutex_unlock(&gpd_list_lock); - return 0; error: @@ -2348,8 +2346,6 @@ error: } } - mutex_unlock(&gpd_list_lock); - return ret; } EXPORT_SYMBOL_GPL(of_genpd_add_provider_onecell); diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index f893c3c5af07..d568772152c2 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -220,16 +220,13 @@ static void initcall_debug_report(struct device *dev, ktime_t calltime, void *cb, int error) { ktime_t rettime; - s64 nsecs; if (!pm_print_times_enabled) return; rettime = ktime_get(); - nsecs = (s64) ktime_to_ns(ktime_sub(rettime, calltime)); - dev_info(dev, "%pS returned %d after %Ld usecs\n", cb, error, - (unsigned long long)nsecs >> 10); + (unsigned long long)ktime_us_delta(rettime, calltime)); } /** diff --git a/drivers/base/property.c b/drivers/base/property.c index 1f533b314efc..d0874f6c29bb 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -627,14 +627,15 @@ EXPORT_SYMBOL_GPL(fwnode_get_next_parent); */ struct device *fwnode_get_next_parent_dev(struct fwnode_handle *fwnode) { - struct device *dev = NULL; + struct device *dev; fwnode_handle_get(fwnode); do { fwnode = fwnode_get_next_parent(fwnode); - if (fwnode) - dev = get_dev_from_fwnode(fwnode); - } while (fwnode && !dev); + if (!fwnode) + return NULL; + dev = get_dev_from_fwnode(fwnode); + } while (!dev); fwnode_handle_put(fwnode); return dev; } @@ -742,10 +743,9 @@ fwnode_get_next_available_child_node(const struct fwnode_handle *fwnode, do { next_child = fwnode_get_next_child_node(fwnode, next_child); - - if (!next_child || fwnode_device_is_available(next_child)) - break; - } while (next_child); + if (!next_child) + return NULL; + } while (!fwnode_device_is_available(next_child)); return next_child; } diff --git a/drivers/base/trace.c b/drivers/base/trace.c new file mode 100644 index 000000000000..b24b0a309c4a --- /dev/null +++ b/drivers/base/trace.c @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Device core Trace Support + * Copyright (C) 2021, Intel Corporation + * + * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> + */ + +#define CREATE_TRACE_POINTS +#include "trace.h" diff --git a/drivers/base/trace.h b/drivers/base/trace.h new file mode 100644 index 000000000000..3192e18f877e --- /dev/null +++ b/drivers/base/trace.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Device core Trace Support + * Copyright (C) 2021, Intel Corporation + * + * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM dev + +#if !defined(__DEV_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define __DEV_TRACE_H + +#include <linux/device.h> +#include <linux/tracepoint.h> +#include <linux/types.h> + +DECLARE_EVENT_CLASS(devres, + TP_PROTO(struct device *dev, const char *op, void *node, const char *name, size_t size), + TP_ARGS(dev, op, node, name, size), + TP_STRUCT__entry( + __string(devname, dev_name(dev)) + __field(struct device *, dev) + __field(const char *, op) + __field(void *, node) + __field(const char *, name) + __field(size_t, size) + ), + TP_fast_assign( + __assign_str(devname, dev_name(dev)); + __entry->op = op; + __entry->node = node; + __entry->name = name; + __entry->size = size; + ), + TP_printk("%s %3s %p %s (%zu bytes)", __get_str(devname), + __entry->op, __entry->node, __entry->name, __entry->size) +); + +DEFINE_EVENT(devres, devres_log, + TP_PROTO(struct device *dev, const char *op, void *node, const char *name, size_t size), + TP_ARGS(dev, op, node, name, size) +); + +#endif /* __DEV_TRACE_H */ + +/* this part has to be here */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE trace + +#include <trace/define_trace.h> diff --git a/drivers/block/loop.c b/drivers/block/loop.c index cc0e8c39a48b..f37b9e3d833c 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1434,7 +1434,6 @@ static int loop_set_status(struct loop_device *lo, const struct loop_info64 *info) { int err; - struct block_device *bdev; kuid_t uid = current_uid(); int prev_lo_flags; bool partscan = false; @@ -1503,7 +1502,6 @@ out_unfreeze: if (!err && (lo->lo_flags & LO_FLAGS_PARTSCAN) && !(prev_lo_flags & LO_FLAGS_PARTSCAN)) { lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN; - bdev = lo->lo_device; partscan = true; } out_unlock: @@ -2237,7 +2235,7 @@ static const struct blk_mq_ops loop_mq_ops = { .complete = lo_complete_rq, }; -static int loop_add(struct loop_device **l, int i) +static int loop_add(int i) { struct loop_device *lo; struct gendisk *disk; @@ -2247,9 +2245,12 @@ static int loop_add(struct loop_device **l, int i) lo = kzalloc(sizeof(*lo), GFP_KERNEL); if (!lo) goto out; - lo->lo_state = Lo_unbound; + err = mutex_lock_killable(&loop_ctl_mutex); + if (err) + goto out_free_dev; + /* allocate id, if @id >= 0, we're requesting that specific id */ if (i >= 0) { err = idr_alloc(&loop_index_idr, lo, i, i + 1, GFP_KERNEL); @@ -2259,7 +2260,7 @@ static int loop_add(struct loop_device **l, int i) err = idr_alloc(&loop_index_idr, lo, 0, 0, GFP_KERNEL); } if (err < 0) - goto out_free_dev; + goto out_unlock; i = err; err = -ENOMEM; @@ -2326,13 +2327,15 @@ static int loop_add(struct loop_device **l, int i) disk->queue = lo->lo_queue; sprintf(disk->disk_name, "loop%d", i); add_disk(disk); - *l = lo; - return lo->lo_number; + mutex_unlock(&loop_ctl_mutex); + return i; out_cleanup_tags: blk_mq_free_tag_set(&lo->tag_set); out_free_idr: idr_remove(&loop_index_idr, i); +out_unlock: + mutex_unlock(&loop_ctl_mutex); out_free_dev: kfree(lo); out: @@ -2348,109 +2351,86 @@ static void loop_remove(struct loop_device *lo) kfree(lo); } -static int find_free_cb(int id, void *ptr, void *data) +static void loop_probe(dev_t dev) { - struct loop_device *lo = ptr; - struct loop_device **l = data; + int idx = MINOR(dev) >> part_shift; - if (lo->lo_state == Lo_unbound) { - *l = lo; - return 1; - } - return 0; + if (max_loop && idx >= max_loop) + return; + loop_add(idx); } -static int loop_lookup(struct loop_device **l, int i) +static int loop_control_remove(int idx) { struct loop_device *lo; - int ret = -ENODEV; + int ret; - if (i < 0) { - int err; + if (idx < 0) { + pr_warn("deleting an unspecified loop device is not supported.\n"); + return -EINVAL; + } + + ret = mutex_lock_killable(&loop_ctl_mutex); + if (ret) + return ret; - err = idr_for_each(&loop_index_idr, &find_free_cb, &lo); - if (err == 1) { - *l = lo; - ret = lo->lo_number; - } - goto out; + lo = idr_find(&loop_index_idr, idx); + if (!lo) { + ret = -ENODEV; + goto out_unlock_ctrl; } - /* lookup and return a specific i */ - lo = idr_find(&loop_index_idr, i); - if (lo) { - *l = lo; - ret = lo->lo_number; + ret = mutex_lock_killable(&lo->lo_mutex); + if (ret) + goto out_unlock_ctrl; + if (lo->lo_state != Lo_unbound || + atomic_read(&lo->lo_refcnt) > 0) { + mutex_unlock(&lo->lo_mutex); + ret = -EBUSY; + goto out_unlock_ctrl; } -out: + lo->lo_state = Lo_deleting; + mutex_unlock(&lo->lo_mutex); + + idr_remove(&loop_index_idr, lo->lo_number); + loop_remove(lo); +out_unlock_ctrl: + mutex_unlock(&loop_ctl_mutex); return ret; } -static void loop_probe(dev_t dev) +static int loop_control_get_free(int idx) { - int idx = MINOR(dev) >> part_shift; struct loop_device *lo; + int id, ret; - if (max_loop && idx >= max_loop) - return; - - mutex_lock(&loop_ctl_mutex); - if (loop_lookup(&lo, idx) < 0) - loop_add(&lo, idx); + ret = mutex_lock_killable(&loop_ctl_mutex); + if (ret) + return ret; + idr_for_each_entry(&loop_index_idr, lo, id) { + if (lo->lo_state == Lo_unbound) + goto found; + } mutex_unlock(&loop_ctl_mutex); + return loop_add(-1); +found: + mutex_unlock(&loop_ctl_mutex); + return id; } static long loop_control_ioctl(struct file *file, unsigned int cmd, unsigned long parm) { - struct loop_device *lo; - int ret; - - ret = mutex_lock_killable(&loop_ctl_mutex); - if (ret) - return ret; - - ret = -ENOSYS; switch (cmd) { case LOOP_CTL_ADD: - ret = loop_lookup(&lo, parm); - if (ret >= 0) { - ret = -EEXIST; - break; - } - ret = loop_add(&lo, parm); - break; + return loop_add(parm); case LOOP_CTL_REMOVE: - ret = loop_lookup(&lo, parm); - if (ret < 0) - break; - ret = mutex_lock_killable(&lo->lo_mutex); - if (ret) - break; - if (lo->lo_state != Lo_unbound) { - ret = -EBUSY; - mutex_unlock(&lo->lo_mutex); - break; - } - if (atomic_read(&lo->lo_refcnt) > 0) { - ret = -EBUSY; - mutex_unlock(&lo->lo_mutex); - break; - } - lo->lo_state = Lo_deleting; - mutex_unlock(&lo->lo_mutex); - idr_remove(&loop_index_idr, lo->lo_number); - loop_remove(lo); - break; + return loop_control_remove(parm); case LOOP_CTL_GET_FREE: - ret = loop_lookup(&lo, -1); - if (ret >= 0) - break; - ret = loop_add(&lo, -1); + return loop_control_get_free(parm); + default: + return -ENOSYS; } - mutex_unlock(&loop_ctl_mutex); - - return ret; } static const struct file_operations loop_ctl_fops = { @@ -2473,7 +2453,6 @@ MODULE_ALIAS("devname:loop-control"); static int __init loop_init(void) { int i, nr; - struct loop_device *lo; int err; part_shift = 0; @@ -2525,10 +2504,8 @@ static int __init loop_init(void) } /* pre-create number of devices given by config or max_loop */ - mutex_lock(&loop_ctl_mutex); for (i = 0; i < nr; i++) - loop_add(&lo, i); - mutex_unlock(&loop_ctl_mutex); + loop_add(i); printk(KERN_INFO "loop: module loaded\n"); return 0; @@ -2539,26 +2516,20 @@ err_out: return err; } -static int loop_exit_cb(int id, void *ptr, void *data) -{ - struct loop_device *lo = ptr; - - loop_remove(lo); - return 0; -} - static void __exit loop_exit(void) { - mutex_lock(&loop_ctl_mutex); - - idr_for_each(&loop_index_idr, &loop_exit_cb, NULL); - idr_destroy(&loop_index_idr); + struct loop_device *lo; + int id; unregister_blkdev(LOOP_MAJOR, "loop"); - misc_deregister(&loop_misc); + mutex_lock(&loop_ctl_mutex); + idr_for_each_entry(&loop_index_idr, lo, id) + loop_remove(lo); mutex_unlock(&loop_ctl_mutex); + + idr_destroy(&loop_index_idr); } module_init(loop_init); diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index ff3e7b3f5ad8..901855717cb5 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -2160,6 +2160,20 @@ static ssize_t mtip_hw_show_status(struct device *dev, static DEVICE_ATTR(status, 0444, mtip_hw_show_status, NULL); +static struct attribute *mtip_disk_attrs[] = { + &dev_attr_status.attr, + NULL, +}; + +static const struct attribute_group mtip_disk_attr_group = { + .attrs = mtip_disk_attrs, +}; + +static const struct attribute_group *mtip_disk_attr_groups[] = { + &mtip_disk_attr_group, + NULL, +}; + /* debugsfs entries */ static ssize_t show_device_status(struct device_driver *drv, char *buf) @@ -2374,47 +2388,6 @@ static const struct file_operations mtip_flags_fops = { .llseek = no_llseek, }; -/* - * Create the sysfs related attributes. - * - * @dd Pointer to the driver data structure. - * @kobj Pointer to the kobj for the block device. - * - * return value - * 0 Operation completed successfully. - * -EINVAL Invalid parameter. - */ -static int mtip_hw_sysfs_init(struct driver_data *dd, struct kobject *kobj) -{ - if (!kobj || !dd) - return -EINVAL; - - if (sysfs_create_file(kobj, &dev_attr_status.attr)) - dev_warn(&dd->pdev->dev, - "Error creating 'status' sysfs entry\n"); - return 0; -} - -/* - * Remove the sysfs related attributes. - * - * @dd Pointer to the driver data structure. - * @kobj Pointer to the kobj for the block device. - * - * return value - * 0 Operation completed successfully. - * -EINVAL Invalid parameter. - */ -static int mtip_hw_sysfs_exit(struct driver_data *dd, struct kobject *kobj) -{ - if (!kobj || !dd) - return -EINVAL; - - sysfs_remove_file(kobj, &dev_attr_status.attr); - - return 0; -} - static int mtip_hw_debugfs_init(struct driver_data *dd) { if (!dfs_parent) @@ -3566,7 +3539,6 @@ static int mtip_block_initialize(struct driver_data *dd) int rv = 0, wait_for_rebuild = 0; sector_t capacity; unsigned int index = 0; - struct kobject *kobj; if (dd->disk) goto skip_create_disk; /* hw init done, before rebuild */ @@ -3576,35 +3548,6 @@ static int mtip_block_initialize(struct driver_data *dd) goto protocol_init_error; } - dd->disk = alloc_disk_node(MTIP_MAX_MINORS, dd->numa_node); - if (dd->disk == NULL) { - dev_err(&dd->pdev->dev, - "Unable to allocate gendisk structure\n"); - rv = -EINVAL; - goto alloc_disk_error; - } - - rv = ida_alloc(&rssd_index_ida, GFP_KERNEL); - if (rv < 0) - goto ida_get_error; - index = rv; - - rv = rssd_disk_name_format("rssd", - index, - dd->disk->disk_name, - DISK_NAME_LEN); - if (rv) - goto disk_index_error; - - dd->disk->major = dd->major; - dd->disk->first_minor = index * MTIP_MAX_MINORS; - dd->disk->minors = MTIP_MAX_MINORS; - dd->disk->fops = &mtip_block_ops; - dd->disk->private_data = dd; - dd->index = index; - - mtip_hw_debugfs_init(dd); - memset(&dd->tags, 0, sizeof(dd->tags)); dd->tags.ops = &mtip_mq_ops; dd->tags.nr_hw_queues = 1; @@ -3623,17 +3566,35 @@ static int mtip_block_initialize(struct driver_data *dd) goto block_queue_alloc_tag_error; } - /* Allocate the request queue. */ - dd->queue = blk_mq_init_queue(&dd->tags); - if (IS_ERR(dd->queue)) { + dd->disk = blk_mq_alloc_disk(&dd->tags, dd); + if (IS_ERR(dd->disk)) { dev_err(&dd->pdev->dev, "Unable to allocate request queue\n"); rv = -ENOMEM; goto block_queue_alloc_init_error; } + dd->queue = dd->disk->queue; + + rv = ida_alloc(&rssd_index_ida, GFP_KERNEL); + if (rv < 0) + goto ida_get_error; + index = rv; + + rv = rssd_disk_name_format("rssd", + index, + dd->disk->disk_name, + DISK_NAME_LEN); + if (rv) + goto disk_index_error; + + dd->disk->major = dd->major; + dd->disk->first_minor = index * MTIP_MAX_MINORS; + dd->disk->minors = MTIP_MAX_MINORS; + dd->disk->fops = &mtip_block_ops; + dd->disk->private_data = dd; + dd->index = index; - dd->disk->queue = dd->queue; - dd->queue->queuedata = dd; + mtip_hw_debugfs_init(dd); skip_create_disk: /* Initialize the protocol layer. */ @@ -3672,17 +3633,7 @@ skip_create_disk: set_capacity(dd->disk, capacity); /* Enable the block device and add it to /dev */ - device_add_disk(&dd->pdev->dev, dd->disk, NULL); - - /* - * Now that the disk is active, initialize any sysfs attributes - * managed by the protocol layer. - */ - kobj = kobject_get(&disk_to_dev(dd->disk)->kobj); - if (kobj) { - mtip_hw_sysfs_init(dd, kobj); - kobject_put(kobj); - } + device_add_disk(&dd->pdev->dev, dd->disk, mtip_disk_attr_groups); if (dd->mtip_svc_handler) { set_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag); @@ -3709,23 +3660,17 @@ start_service_thread: kthread_run_error: /* Delete our gendisk. This also removes the device from /dev */ del_gendisk(dd->disk); - read_capacity_error: init_hw_cmds_error: - blk_cleanup_queue(dd->queue); -block_queue_alloc_init_error: - blk_mq_free_tag_set(&dd->tags); -block_queue_alloc_tag_error: mtip_hw_debugfs_exit(dd); disk_index_error: ida_free(&rssd_index_ida, index); - ida_get_error: - put_disk(dd->disk); - -alloc_disk_error: + blk_cleanup_disk(dd->disk); +block_queue_alloc_init_error: + blk_mq_free_tag_set(&dd->tags); +block_queue_alloc_tag_error: mtip_hw_exit(dd); /* De-initialize the protocol layer. */ - protocol_init_error: return rv; } @@ -3751,8 +3696,6 @@ static bool mtip_no_dev_cleanup(struct request *rq, void *data, bool reserv) */ static int mtip_block_remove(struct driver_data *dd) { - struct kobject *kobj; - mtip_hw_debugfs_exit(dd); if (dd->mtip_svc_handler) { @@ -3761,15 +3704,6 @@ static int mtip_block_remove(struct driver_data *dd) kthread_stop(dd->mtip_svc_handler); } - /* Clean up the sysfs attributes, if created */ - if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) { - kobj = kobject_get(&disk_to_dev(dd->disk)->kobj); - if (kobj) { - mtip_hw_sysfs_exit(dd, kobj); - kobject_put(kobj); - } - } - if (!dd->sr) { /* * Explicitly wait here for IOs to quiesce, diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 614d82e7fae4..b7d663736d35 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -79,6 +79,7 @@ struct link_dead_args { #define NBD_RT_HAS_CONFIG_REF 4 #define NBD_RT_BOUND 5 #define NBD_RT_DISCONNECT_ON_CLOSE 6 +#define NBD_RT_HAS_BACKEND_FILE 7 #define NBD_DESTROY_ON_DISCONNECT 0 #define NBD_DISCONNECT_REQUESTED 1 @@ -119,6 +120,8 @@ struct nbd_device { struct completion *destroy_complete; unsigned long flags; + + char *backend; }; #define NBD_CMD_REQUEUED 1 @@ -216,6 +219,20 @@ static const struct device_attribute pid_attr = { .show = pid_show, }; +static ssize_t backend_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gendisk *disk = dev_to_disk(dev); + struct nbd_device *nbd = (struct nbd_device *)disk->private_data; + + return sprintf(buf, "%s\n", nbd->backend ?: ""); +} + +static const struct device_attribute backend_attr = { + .attr = { .name = "backend", .mode = 0444}, + .show = backend_show, +}; + static void nbd_dev_remove(struct nbd_device *nbd) { struct gendisk *disk = nbd->disk; @@ -1211,6 +1228,12 @@ static void nbd_config_put(struct nbd_device *nbd) &config->runtime_flags)) device_remove_file(disk_to_dev(nbd->disk), &pid_attr); nbd->task_recv = NULL; + if (test_and_clear_bit(NBD_RT_HAS_BACKEND_FILE, + &config->runtime_flags)) { + device_remove_file(disk_to_dev(nbd->disk), &backend_attr); + kfree(nbd->backend); + nbd->backend = NULL; + } nbd_clear_sock(nbd); if (config->num_connections) { int i; @@ -1270,7 +1293,7 @@ static int nbd_start_device(struct nbd_device *nbd) error = device_create_file(disk_to_dev(nbd->disk), &pid_attr); if (error) { - dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n"); + dev_err(disk_to_dev(nbd->disk), "device_create_file failed for pid!\n"); return error; } set_bit(NBD_RT_HAS_PID_FILE, &config->runtime_flags); @@ -1657,6 +1680,7 @@ static int nbd_dev_add(int index) BLK_MQ_F_BLOCKING; nbd->tag_set.driver_data = nbd; nbd->destroy_complete = NULL; + nbd->backend = NULL; err = blk_mq_alloc_tag_set(&nbd->tag_set); if (err) @@ -1743,6 +1767,7 @@ static const struct nla_policy nbd_attr_policy[NBD_ATTR_MAX + 1] = { [NBD_ATTR_SOCKETS] = { .type = NLA_NESTED}, [NBD_ATTR_DEAD_CONN_TIMEOUT] = { .type = NLA_U64 }, [NBD_ATTR_DEVICE_LIST] = { .type = NLA_NESTED}, + [NBD_ATTR_BACKEND_IDENTIFIER] = { .type = NLA_STRING}, }; static const struct nla_policy nbd_sock_policy[NBD_SOCK_MAX + 1] = { @@ -1945,6 +1970,23 @@ again: } } ret = nbd_start_device(nbd); + if (ret) + goto out; + if (info->attrs[NBD_ATTR_BACKEND_IDENTIFIER]) { + nbd->backend = nla_strdup(info->attrs[NBD_ATTR_BACKEND_IDENTIFIER], + GFP_KERNEL); + if (!nbd->backend) { + ret = -ENOMEM; + goto out; + } + } + ret = device_create_file(disk_to_dev(nbd->disk), &backend_attr); + if (ret) { + dev_err(disk_to_dev(nbd->disk), + "device_create_file failed for backend!\n"); + goto out; + } + set_bit(NBD_RT_HAS_BACKEND_FILE, &config->runtime_flags); out: mutex_unlock(&nbd->config_lock); if (!ret) { @@ -2037,6 +2079,22 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info) index); return -EINVAL; } + if (nbd->backend) { + if (info->attrs[NBD_ATTR_BACKEND_IDENTIFIER]) { + if (nla_strcmp(info->attrs[NBD_ATTR_BACKEND_IDENTIFIER], + nbd->backend)) { + mutex_unlock(&nbd_index_mutex); + dev_err(nbd_to_dev(nbd), + "backend image doesn't match with %s\n", + nbd->backend); + return -EINVAL; + } + } else { + mutex_unlock(&nbd_index_mutex); + dev_err(nbd_to_dev(nbd), "must specify backend\n"); + return -EINVAL; + } + } if (!refcount_inc_not_zero(&nbd->refs)) { mutex_unlock(&nbd_index_mutex); printk(KERN_ERR "nbd: device at index %d is going down\n", diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c index 3b320b005aa8..d734e9ee1546 100644 --- a/drivers/block/null_blk/main.c +++ b/drivers/block/null_blk/main.c @@ -1849,7 +1849,6 @@ static int null_add_dev(struct nullb_device *dev) if (!null_setup_fault()) goto out_cleanup_tags; - rv = -ENOMEM; nullb->tag_set->timeout = 5 * HZ; nullb->disk = blk_mq_alloc_disk(nullb->tag_set, nullb); if (IS_ERR(nullb->disk)) { diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index f69b5c69c2a6..538446b652de 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -704,7 +704,7 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command * int ret = 0; rq = blk_get_request(q, (cgc->data_direction == CGC_DATA_WRITE) ? - REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, 0); + REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0); if (IS_ERR(rq)) return PTR_ERR(rq); diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index c4631e684386..4d4bb810c2ae 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c @@ -1050,7 +1050,7 @@ err_out_release_mdesc: return err; } -static int vdc_port_remove(struct vio_dev *vdev) +static void vdc_port_remove(struct vio_dev *vdev) { struct vdc_port *port = dev_get_drvdata(&vdev->dev); @@ -1072,7 +1072,6 @@ static int vdc_port_remove(struct vio_dev *vdev) kfree(port); } - return 0; } static void vdc_requeue_inflight(struct vdc_port *port) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index e4bd3b1fc3c2..4b49df2dfd23 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -21,6 +21,9 @@ #define VQ_NAME_LEN 16 #define MAX_DISCARD_SEGMENTS 256u +/* The maximum number of sg elements that fit into a virtqueue */ +#define VIRTIO_BLK_MAX_SG_ELEMS 32768 + static int major; static DEFINE_IDA(vd_index_ida); @@ -447,13 +450,6 @@ static void virtblk_update_capacity(struct virtio_blk *vblk, bool resize) /* Host must always specify the capacity. */ virtio_cread(vdev, struct virtio_blk_config, capacity, &capacity); - /* If capacity is too big, truncate with warning. */ - if ((sector_t)capacity != capacity) { - dev_warn(&vdev->dev, "Capacity %llu too large: truncating\n", - (unsigned long long)capacity); - capacity = (sector_t)-1; - } - nblocks = DIV_ROUND_UP_ULL(capacity, queue_logical_block_size(q) >> 9); string_get_size(nblocks, queue_logical_block_size(q), @@ -728,7 +724,10 @@ static int virtblk_probe(struct virtio_device *vdev) if (err || !sg_elems) sg_elems = 1; - /* We need an extra sg elements at head and tail. */ + /* Prevent integer overflows and honor max vq size */ + sg_elems = min_t(u32, sg_elems, VIRTIO_BLK_MAX_SG_ELEMS - 2); + + /* We need extra sg elements at head and tail. */ sg_elems += 2; vdev->priv = vblk = kmalloc(sizeof(*vblk), GFP_KERNEL); if (!vblk) { @@ -936,6 +935,8 @@ static int virtblk_freeze(struct virtio_device *vdev) blk_mq_quiesce_queue(vblk->disk->queue); vdev->config->del_vqs(vdev); + kfree(vblk->vqs); + return 0; } diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 71a4ca505e09..5ed2cfa7da1d 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -593,7 +593,7 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty) * Return Value: None */ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, - char *flags, int count) + const char *flags, int count) { struct hci_uart *hu = tty->disc_data; @@ -821,6 +821,7 @@ static __poll_t hci_uart_tty_poll(struct tty_struct *tty, static struct tty_ldisc_ops hci_uart_ldisc = { .owner = THIS_MODULE, + .num = N_HCI, .name = "n_hci", .open = hci_uart_tty_open, .close = hci_uart_tty_close, @@ -840,7 +841,7 @@ static int __init hci_uart_init(void) BT_INFO("HCI UART driver ver %s", VERSION); /* Register the tty discipline */ - err = tty_register_ldisc(N_HCI, &hci_uart_ldisc); + err = tty_register_ldisc(&hci_uart_ldisc); if (err) { BT_ERR("HCI line discipline registration failed. (%d)", err); return err; @@ -882,8 +883,6 @@ static int __init hci_uart_init(void) static void __exit hci_uart_exit(void) { - int err; - #ifdef CONFIG_BT_HCIUART_H4 h4_deinit(); #endif @@ -915,10 +914,7 @@ static void __exit hci_uart_exit(void) mrvl_deinit(); #endif - /* Release tty registration of line discipline */ - err = tty_unregister_ldisc(N_HCI); - if (err) - BT_ERR("Can't unregister HCI line discipline (%d)", err); + tty_unregister_ldisc(&hci_uart_ldisc); } module_init(hci_uart_init); diff --git a/drivers/bus/fsl-mc/dprc-driver.c b/drivers/bus/fsl-mc/dprc-driver.c index e3e2ae41c22b..315e830b6ecd 100644 --- a/drivers/bus/fsl-mc/dprc-driver.c +++ b/drivers/bus/fsl-mc/dprc-driver.c @@ -350,7 +350,8 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state * * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object - * + * @alloc_interrupts: if true the function allocates the interrupt pool, + * otherwise the interrupt allocation is delayed * Scans the physical DPRC and synchronizes the state of the Linux * bus driver with the actual state of the MC by adding and removing * devices as appropriate. @@ -373,10 +374,11 @@ int dprc_scan_container(struct fsl_mc_device *mc_bus_dev, return error; } EXPORT_SYMBOL_GPL(dprc_scan_container); + /** * dprc_irq0_handler - Regular ISR for DPRC interrupt 0 * - * @irq: IRQ number of the interrupt being handled + * @irq_num: IRQ number of the interrupt being handled * @arg: Pointer to device structure */ static irqreturn_t dprc_irq0_handler(int irq_num, void *arg) @@ -387,7 +389,7 @@ static irqreturn_t dprc_irq0_handler(int irq_num, void *arg) /** * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0 * - * @irq: IRQ number of the interrupt being handled + * @irq_num: IRQ number of the interrupt being handled * @arg: Pointer to device structure */ static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg) diff --git a/drivers/bus/fsl-mc/dprc.c b/drivers/bus/fsl-mc/dprc.c index 27b0a01bad9b..d129338b8bc0 100644 --- a/drivers/bus/fsl-mc/dprc.c +++ b/drivers/bus/fsl-mc/dprc.c @@ -334,7 +334,7 @@ int dprc_clear_irq_status(struct fsl_mc_io *mc_io, * @mc_io: Pointer to MC portal's I/O object * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' * @token: Token of DPRC object - * @attributes Returned container attributes + * @attr: Returned container attributes * * Return: '0' on Success; Error code otherwise. */ @@ -504,7 +504,7 @@ EXPORT_SYMBOL_GPL(dprc_set_obj_irq); * @mc_io: Pointer to MC portal's I/O object * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' * @token: Token of DPRC object - * @obj_type; Object type as returned in dprc_get_obj() + * @obj_type: Object type as returned in dprc_get_obj() * @obj_id: Unique object instance as returned in dprc_get_obj() * @region_index: The specific region to query * @region_desc: Returns the requested region descriptor diff --git a/drivers/bus/fsl-mc/fsl-mc-allocator.c b/drivers/bus/fsl-mc/fsl-mc-allocator.c index 2d7c764bb7dc..6c513556911e 100644 --- a/drivers/bus/fsl-mc/fsl-mc-allocator.c +++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c @@ -254,7 +254,7 @@ EXPORT_SYMBOL_GPL(fsl_mc_resource_free); * @mc_dev: fsl-mc device which is used in conjunction with the * allocated object * @pool_type: pool type - * @new_mc_dev: pointer to area where the pointer to the allocated device + * @new_mc_adev: pointer to area where the pointer to the allocated device * is to be returned * * Allocatable objects are always used in conjunction with some functional @@ -409,7 +409,7 @@ cleanup_msi_irqs: } EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool); -/** +/* * Teardown the interrupt pool associated with an fsl-mc bus. * It frees the IRQs that were allocated to the pool, back to the GIC-ITS. */ @@ -436,7 +436,7 @@ void fsl_mc_cleanup_irq_pool(struct fsl_mc_device *mc_bus_dev) } EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool); -/** +/* * Allocate the IRQs required by a given fsl-mc device. */ int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) @@ -578,7 +578,7 @@ void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type); } -/** +/* * fsl_mc_allocator_probe - callback invoked when an allocatable device is * being added to the system */ @@ -610,7 +610,7 @@ static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev) return 0; } -/** +/* * fsl_mc_allocator_remove - callback invoked when an allocatable device is * being removed from the system */ diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c index 380ad1fdb745..09c8ab5e0959 100644 --- a/drivers/bus/fsl-mc/fsl-mc-bus.c +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c @@ -24,7 +24,7 @@ #include "fsl-mc-private.h" -/** +/* * Default DMA mask for devices on a fsl-mc bus */ #define FSL_MC_DEFAULT_DMA_MASK (~0ULL) @@ -36,6 +36,7 @@ static struct fsl_mc_version mc_version; * @root_mc_bus_dev: fsl-mc device representing the root DPRC * @num_translation_ranges: number of entries in addr_translation_ranges * @translation_ranges: array of bus to system address translation ranges + * @fsl_mc_regs: base address of register bank */ struct fsl_mc { struct fsl_mc_device *root_mc_bus_dev; @@ -117,7 +118,7 @@ out: return found; } -/** +/* * fsl_mc_bus_uevent - callback invoked when a device is added */ static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) @@ -467,7 +468,7 @@ static void fsl_mc_driver_shutdown(struct device *dev) mc_drv->shutdown(mc_dev); } -/** +/* * __fsl_mc_driver_register - registers a child device driver with the * MC bus * @@ -503,7 +504,7 @@ int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver, } EXPORT_SYMBOL_GPL(__fsl_mc_driver_register); -/** +/* * fsl_mc_driver_unregister - unregisters a device driver from the * MC bus */ @@ -563,7 +564,7 @@ struct fsl_mc_version *fsl_mc_get_version(void) } EXPORT_SYMBOL_GPL(fsl_mc_get_version); -/** +/* * fsl_mc_get_root_dprc - function to traverse to the root dprc */ void fsl_mc_get_root_dprc(struct device *dev, @@ -732,7 +733,7 @@ error_cleanup_regions: return error; } -/** +/* * fsl_mc_is_root_dprc - function to check if a given device is a root dprc */ bool fsl_mc_is_root_dprc(struct device *dev) @@ -757,7 +758,7 @@ static void fsl_mc_device_release(struct device *dev) kfree(mc_dev); } -/** +/* * Add a newly discovered fsl-mc device to be visible in Linux */ int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc, @@ -1058,7 +1059,7 @@ static int get_mc_addr_translation_ranges(struct device *dev, return 0; } -/** +/* * fsl_mc_bus_probe - callback invoked when the root MC bus is being * added */ @@ -1182,7 +1183,7 @@ error_cleanup_mc_io: return error; } -/** +/* * fsl_mc_bus_remove - callback invoked when the root MC bus is being * removed */ diff --git a/drivers/bus/fsl-mc/fsl-mc-msi.c b/drivers/bus/fsl-mc/fsl-mc-msi.c index 8edadf05cbb7..cf974870ba55 100644 --- a/drivers/bus/fsl-mc/fsl-mc-msi.c +++ b/drivers/bus/fsl-mc/fsl-mc-msi.c @@ -148,7 +148,7 @@ static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info) /** * fsl_mc_msi_create_irq_domain - Create a fsl-mc MSI interrupt domain - * @np: Optional device-tree node of the interrupt controller + * @fwnode: Optional firmware node of the interrupt controller * @info: MSI domain info * @parent: Parent irq domain * diff --git a/drivers/bus/fsl-mc/mc-io.c b/drivers/bus/fsl-mc/mc-io.c index 305015486b91..95b10a6cf307 100644 --- a/drivers/bus/fsl-mc/mc-io.c +++ b/drivers/bus/fsl-mc/mc-io.c @@ -50,12 +50,12 @@ static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io) } /** - * Creates an MC I/O object + * fsl_create_mc_io() - Creates an MC I/O object * * @dev: device to be associated with the MC I/O object * @mc_portal_phys_addr: physical address of the MC portal to use * @mc_portal_size: size in bytes of the MC portal - * @dpmcp-dev: Pointer to the DPMCP object associated with this MC I/O + * @dpmcp_dev: Pointer to the DPMCP object associated with this MC I/O * object or NULL if none. * @flags: flags for the new MC I/O object * @new_mc_io: Area to return pointer to newly created MC I/O object @@ -123,7 +123,7 @@ error_destroy_mc_io: } /** - * Destroys an MC I/O object + * fsl_destroy_mc_io() - Destroys an MC I/O object * * @mc_io: MC I/O object to destroy */ diff --git a/drivers/bus/fsl-mc/mc-sys.c b/drivers/bus/fsl-mc/mc-sys.c index b291b35e3884..f2052cd0a051 100644 --- a/drivers/bus/fsl-mc/mc-sys.c +++ b/drivers/bus/fsl-mc/mc-sys.c @@ -16,7 +16,7 @@ #include "fsl-mc-private.h" -/** +/* * Timeout in milliseconds to wait for the completion of an MC command */ #define MC_CMD_COMPLETION_TIMEOUT_MS 500 @@ -148,9 +148,10 @@ static inline enum mc_cmd_status mc_read_response(struct fsl_mc_command __iomem } /** - * Waits for the completion of an MC command doing preemptible polling. - * uslepp_range() is called between polling iterations. - * + * mc_polling_wait_preemptible() - Waits for the completion of an MC + * command doing preemptible polling. + * uslepp_range() is called between + * polling iterations. * @mc_io: MC I/O object to be used * @cmd: command buffer to receive MC response * @mc_status: MC command completion status @@ -194,9 +195,9 @@ static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io, } /** - * Waits for the completion of an MC command doing atomic polling. - * udelay() is called between polling iterations. - * + * mc_polling_wait_atomic() - Waits for the completion of an MC command + * doing atomic polling. udelay() is called + * between polling iterations. * @mc_io: MC I/O object to be used * @cmd: command buffer to receive MC response * @mc_status: MC command completion status @@ -234,8 +235,8 @@ static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io, } /** - * Sends a command to the MC device using the given MC I/O object - * + * mc_send_command() - Sends a command to the MC device using the given + * MC I/O object * @mc_io: MC I/O object to be used * @cmd: command to be sent * diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c index e2e59a341fef..bbf6cd04861e 100644 --- a/drivers/bus/mhi/core/pm.c +++ b/drivers/bus/mhi/core/pm.c @@ -465,23 +465,15 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl) /* Trigger MHI RESET so that the device will not access host memory */ if (!MHI_PM_IN_FATAL_STATE(mhi_cntrl->pm_state)) { - u32 in_reset = -1; - unsigned long timeout = msecs_to_jiffies(mhi_cntrl->timeout_ms); - dev_dbg(dev, "Triggering MHI Reset in device\n"); mhi_set_mhi_state(mhi_cntrl, MHI_STATE_RESET); /* Wait for the reset bit to be cleared by the device */ - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_read_reg_field(mhi_cntrl, - mhi_cntrl->regs, - MHICTRL, - MHICTRL_RESET_MASK, - MHICTRL_RESET_SHIFT, - &in_reset) || - !in_reset, timeout); - if (!ret || in_reset) - dev_err(dev, "Device failed to exit MHI Reset state\n"); + ret = mhi_poll_reg_field(mhi_cntrl, mhi_cntrl->regs, MHICTRL, + MHICTRL_RESET_MASK, MHICTRL_RESET_SHIFT, 0, + 25000); + if (ret) + dev_err(dev, "Device failed to clear MHI Reset\n"); /* * Device will clear BHI_INTVEC as a part of RESET processing, @@ -934,6 +926,7 @@ int mhi_pm_resume(struct mhi_controller *mhi_cntrl) ret = wait_event_timeout(mhi_cntrl->state_event, mhi_cntrl->dev_state == MHI_STATE_M0 || + mhi_cntrl->dev_state == MHI_STATE_M2 || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), msecs_to_jiffies(mhi_cntrl->timeout_ms)); diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c index b3357a8a2fdb..ca3bc40427f8 100644 --- a/drivers/bus/mhi/pci_generic.c +++ b/drivers/bus/mhi/pci_generic.c @@ -665,7 +665,7 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) err = mhi_register_controller(mhi_cntrl, mhi_cntrl_config); if (err) - return err; + goto err_disable_reporting; /* MHI bus does not power up the controller by default */ err = mhi_prepare_for_power_up(mhi_cntrl); @@ -699,6 +699,8 @@ err_unprepare: mhi_unprepare_after_power_down(mhi_cntrl); err_unregister: mhi_unregister_controller(mhi_cntrl); +err_disable_reporting: + pci_disable_pcie_error_reporting(pdev); return err; } @@ -721,6 +723,7 @@ static void mhi_pci_remove(struct pci_dev *pdev) pm_runtime_get_noresume(&pdev->dev); mhi_unregister_controller(mhi_cntrl); + pci_disable_pcie_error_reporting(pdev); } static void mhi_pci_shutdown(struct pci_dev *pdev) diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 90ad34c6ef8e..feb827eefd1a 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -2186,7 +2186,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, len = nr * CD_FRAMESIZE_RAW; - rq = blk_get_request(q, REQ_OP_SCSI_IN, 0); + rq = blk_get_request(q, REQ_OP_DRV_IN, 0); if (IS_ERR(rq)) { ret = PTR_ERR(rq); break; diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index b151e0fcdeb5..ea3ead00f30f 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -218,19 +218,6 @@ config XILINX_HWICAP If unsure, say N. -config R3964 - tristate "Siemens R3964 line discipline" - depends on TTY && BROKEN - help - This driver allows synchronous communication with devices using the - Siemens R3964 packet protocol. Unless you are dealing with special - hardware like PLCs, you are unlikely to need this. - - To compile this driver as a module, choose M here: the - module will be called n_r3964. - - If unsure, say N. - config APPLICOM tristate "Applicom intelligent fieldbus card support" depends on PCI @@ -357,27 +344,6 @@ config NVRAM To compile this driver as a module, choose M here: the module will be called nvram. -config RAW_DRIVER - tristate "RAW driver (/dev/raw/rawN)" - depends on BLOCK - help - The raw driver permits block devices to be bound to /dev/raw/rawN. - Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. - See the raw(8) manpage for more details. - - Applications should preferably open the device (eg /dev/hda1) - with the O_DIRECT flag. - -config MAX_RAW_DEVS - int "Maximum number of RAW devices to support (1-65536)" - depends on RAW_DRIVER - range 1 65536 - default "256" - help - The maximum number of RAW devices that are supported. - Default is 256. Increase this number in case you need lots of - raw devices. - config DEVPORT bool "/dev/port character device" depends on ISA || PCI diff --git a/drivers/char/Makefile b/drivers/char/Makefile index ffce287ef415..264eb398fdd4 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -8,7 +8,6 @@ obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o obj-y += misc.o obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o -obj-$(CONFIG_RAW_DRIVER) += raw.o obj-$(CONFIG_MSPEC) += mspec.o obj-$(CONFIG_UV_MMTIMER) += uv_mmtimer.o obj-$(CONFIG_IBM_BSR) += bsr.o @@ -44,6 +43,6 @@ obj-$(CONFIG_TCG_TPM) += tpm/ obj-$(CONFIG_PS3_FLASH) += ps3flash.o -obj-$(CONFIG_XILLYBUS) += xillybus/ +obj-$(CONFIG_XILLYBUS_CLASS) += xillybus/ obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o obj-$(CONFIG_ADI) += adi.o diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 8b55085650ad..4e5431f01450 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -156,12 +156,12 @@ static irqreturn_t hpet_interrupt(int irq, void *data) * This has the effect of treating non-periodic like periodic. */ if ((devp->hd_flags & (HPET_IE | HPET_PERIODIC)) == HPET_IE) { - unsigned long m, t, mc, base, k; + unsigned long t, mc, base, k; struct hpet __iomem *hpet = devp->hd_hpet; struct hpets *hpetp = devp->hd_hpets; t = devp->hd_ireqfreq; - m = read_counter(&devp->hd_timer->hpet_compare); + read_counter(&devp->hd_timer->hpet_compare); mc = read_counter(&hpet->hpet_mc); /* The time for the next interrupt would logically be t + m, * however, if we are very unlucky and the interrupt is delayed diff --git a/drivers/char/hw_random/pseries-rng.c b/drivers/char/hw_random/pseries-rng.c index f4949b689bd5..62bdd5af1339 100644 --- a/drivers/char/hw_random/pseries-rng.c +++ b/drivers/char/hw_random/pseries-rng.c @@ -29,7 +29,7 @@ static int pseries_rng_read(struct hwrng *rng, void *data, size_t max, bool wait return 8; } -/** +/* * pseries_rng_get_desired_dma - Return desired DMA allocate for CMO operations * * This is a required function for a driver to operate in a CMO environment diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 15dc54fa1d47..1c596b5cdb27 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -16,7 +16,6 @@ #include <linux/mman.h> #include <linux/random.h> #include <linux/init.h> -#include <linux/raw.h> #include <linux/tty.h> #include <linux/capability.h> #include <linux/ptrace.h> diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 89681f07bc78..8f1bce0b4fe5 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -544,6 +544,10 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq) io_read_num_rec_bytes(iobase, &num_bytes_read); if (num_bytes_read >= 4) { DEBUGP(2, dev, "NumRecBytes = %i\n", num_bytes_read); + if (num_bytes_read > 4) { + rc = -EIO; + goto exit_setprotocol; + } break; } usleep_range(10000, 11000); @@ -1050,7 +1054,6 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf, struct cm4000_dev *dev = filp->private_data; unsigned int iobase = dev->p_dev->resource[0]->start; unsigned short s; - unsigned char tmp; unsigned char infolen; unsigned char sendT0; unsigned short nsend; @@ -1148,7 +1151,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf, set_cardparameter(dev); /* dummy read, reset flag procedure received */ - tmp = inb(REG_FLAGS1(iobase)); + inb(REG_FLAGS1(iobase)); dev->flags1 = 0x20 /* T_Active */ | (sendT0) diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index d5e43606339c..827711911da4 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -221,7 +221,6 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf, unsigned long i; size_t min_bytes_to_read; int rc; - unsigned char uc; DEBUGP(2, dev, "-> cm4040_read(%s,%d)\n", current->comm, current->pid); @@ -308,7 +307,7 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf, return -EIO; } - uc = xinb(iobase + REG_OFFSET_BULK_IN); + xinb(iobase + REG_OFFSET_BULK_IN); DEBUGP(2, dev, "<- cm4040_read (successfully)\n"); return min_bytes_to_read; diff --git a/drivers/char/pcmcia/scr24x_cs.c b/drivers/char/pcmcia/scr24x_cs.c index 47feb39af34c..1bdce08fae3d 100644 --- a/drivers/char/pcmcia/scr24x_cs.c +++ b/drivers/char/pcmcia/scr24x_cs.c @@ -265,7 +265,6 @@ static int scr24x_probe(struct pcmcia_device *link) cdev_init(&dev->c_dev, &scr24x_fops); dev->c_dev.owner = THIS_MODULE; - dev->c_dev.ops = &scr24x_fops; ret = cdev_add(&dev->c_dev, MKDEV(MAJOR(scr24x_devt), dev->devno), 1); if (ret < 0) goto err; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 3287a7627ed0..6eaefea0520e 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -985,7 +985,7 @@ static void tx_done(MGSLPC_INFO *info, struct tty_struct *tty) else #endif { - if (tty && (tty->stopped || tty->hw_stopped)) { + if (tty && (tty->flow.stopped || tty->hw_stopped)) { tx_stop(info); return; } @@ -1005,7 +1005,7 @@ static void tx_ready(MGSLPC_INFO *info, struct tty_struct *tty) if (!info->tx_active) return; } else { - if (tty && (tty->stopped || tty->hw_stopped)) { + if (tty && (tty->flow.stopped || tty->hw_stopped)) { tx_stop(info); return; } @@ -1419,13 +1419,7 @@ static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty) /* byte size and parity */ - switch (cflag & CSIZE) { - case CS5: info->params.data_bits = 5; break; - case CS6: info->params.data_bits = 6; break; - case CS7: info->params.data_bits = 7; break; - case CS8: info->params.data_bits = 8; break; - default: info->params.data_bits = 7; break; - } + info->params.data_bits = tty_get_char_size(cflag); if (cflag & CSTOPB) info->params.stop_bits = 2; @@ -1525,7 +1519,7 @@ static void mgslpc_flush_chars(struct tty_struct *tty) if (mgslpc_paranoia_check(info, tty->name, "mgslpc_flush_chars")) return; - if (info->tx_count <= 0 || tty->stopped || + if (info->tx_count <= 0 || tty->flow.stopped || tty->hw_stopped || !info->tx_buf) return; @@ -1594,7 +1588,7 @@ static int mgslpc_write(struct tty_struct * tty, ret += c; } start: - if (info->tx_count && !tty->stopped && !tty->hw_stopped) { + if (info->tx_count && !tty->flow.stopped && !tty->hw_stopped) { spin_lock_irqsave(&info->lock, flags); if (!info->tx_active) tx_start(info, tty); @@ -1609,7 +1603,7 @@ cleanup: /* Return the count of free bytes in transmit buffer */ -static int mgslpc_write_room(struct tty_struct *tty) +static unsigned int mgslpc_write_room(struct tty_struct *tty) { MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; int ret; @@ -1637,10 +1631,10 @@ static int mgslpc_write_room(struct tty_struct *tty) /* Return the count of bytes in transmit buffer */ -static int mgslpc_chars_in_buffer(struct tty_struct *tty) +static unsigned int mgslpc_chars_in_buffer(struct tty_struct *tty) { MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; - int rc; + unsigned int rc; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_chars_in_buffer(%s)\n", @@ -1655,7 +1649,7 @@ static int mgslpc_chars_in_buffer(struct tty_struct *tty) rc = info->tx_count; if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgslpc_chars_in_buffer(%s)=%d\n", + printk("%s(%d):mgslpc_chars_in_buffer(%s)=%u\n", __FILE__, __LINE__, info->device_name, rc); return rc; diff --git a/drivers/char/raw.c b/drivers/char/raw.c deleted file mode 100644 index 5d52a1f4738c..000000000000 --- a/drivers/char/raw.c +++ /dev/null @@ -1,362 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * linux/drivers/char/raw.c - * - * Front-end raw character devices. These can be bound to any block - * devices to provide genuine Unix raw character device semantics. - * - * We reserve minor number 0 for a control interface. ioctl()s on this - * device are used to bind the other minor numbers to block devices. - */ - -#include <linux/init.h> -#include <linux/fs.h> -#include <linux/major.h> -#include <linux/blkdev.h> -#include <linux/backing-dev.h> -#include <linux/module.h> -#include <linux/raw.h> -#include <linux/capability.h> -#include <linux/uio.h> -#include <linux/cdev.h> -#include <linux/device.h> -#include <linux/mutex.h> -#include <linux/gfp.h> -#include <linux/compat.h> -#include <linux/vmalloc.h> - -#include <linux/uaccess.h> - -struct raw_device_data { - dev_t binding; - struct block_device *bdev; - int inuse; -}; - -static struct class *raw_class; -static struct raw_device_data *raw_devices; -static DEFINE_MUTEX(raw_mutex); -static const struct file_operations raw_ctl_fops; /* forward declaration */ - -static int max_raw_minors = CONFIG_MAX_RAW_DEVS; - -module_param(max_raw_minors, int, 0); -MODULE_PARM_DESC(max_raw_minors, "Maximum number of raw devices (1-65536)"); - -/* - * Open/close code for raw IO. - * - * We just rewrite the i_mapping for the /dev/raw/rawN file descriptor to - * point at the blockdev's address_space and set the file handle to use - * O_DIRECT. - * - * Set the device's soft blocksize to the minimum possible. This gives the - * finest possible alignment and has no adverse impact on performance. - */ -static int raw_open(struct inode *inode, struct file *filp) -{ - const int minor = iminor(inode); - struct block_device *bdev; - int err; - - if (minor == 0) { /* It is the control device */ - filp->f_op = &raw_ctl_fops; - return 0; - } - - pr_warn_ratelimited( - "process %s (pid %d) is using the deprecated raw device\n" - "support will be removed in Linux 5.14.\n", - current->comm, current->pid); - - mutex_lock(&raw_mutex); - - /* - * All we need to do on open is check that the device is bound. - */ - err = -ENODEV; - if (!raw_devices[minor].binding) - goto out; - bdev = blkdev_get_by_dev(raw_devices[minor].binding, - filp->f_mode | FMODE_EXCL, raw_open); - if (IS_ERR(bdev)) { - err = PTR_ERR(bdev); - goto out; - } - err = set_blocksize(bdev, bdev_logical_block_size(bdev)); - if (err) - goto out1; - filp->f_flags |= O_DIRECT; - filp->f_mapping = bdev->bd_inode->i_mapping; - if (++raw_devices[minor].inuse == 1) - file_inode(filp)->i_mapping = - bdev->bd_inode->i_mapping; - filp->private_data = bdev; - raw_devices[minor].bdev = bdev; - mutex_unlock(&raw_mutex); - return 0; - -out1: - blkdev_put(bdev, filp->f_mode | FMODE_EXCL); -out: - mutex_unlock(&raw_mutex); - return err; -} - -/* - * When the final fd which refers to this character-special node is closed, we - * make its ->mapping point back at its own i_data. - */ -static int raw_release(struct inode *inode, struct file *filp) -{ - const int minor= iminor(inode); - struct block_device *bdev; - - mutex_lock(&raw_mutex); - bdev = raw_devices[minor].bdev; - if (--raw_devices[minor].inuse == 0) - /* Here inode->i_mapping == bdev->bd_inode->i_mapping */ - inode->i_mapping = &inode->i_data; - mutex_unlock(&raw_mutex); - - blkdev_put(bdev, filp->f_mode | FMODE_EXCL); - return 0; -} - -/* - * Forward ioctls to the underlying block device. - */ -static long -raw_ioctl(struct file *filp, unsigned int command, unsigned long arg) -{ - struct block_device *bdev = filp->private_data; - return blkdev_ioctl(bdev, 0, command, arg); -} - -static int bind_set(int number, u64 major, u64 minor) -{ - dev_t dev = MKDEV(major, minor); - dev_t raw = MKDEV(RAW_MAJOR, number); - struct raw_device_data *rawdev; - int err = 0; - - if (number <= 0 || number >= max_raw_minors) - return -EINVAL; - - if (MAJOR(dev) != major || MINOR(dev) != minor) - return -EINVAL; - - rawdev = &raw_devices[number]; - - /* - * This is like making block devices, so demand the - * same capability - */ - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - /* - * For now, we don't need to check that the underlying - * block device is present or not: we can do that when - * the raw device is opened. Just check that the - * major/minor numbers make sense. - */ - - if (MAJOR(dev) == 0 && dev != 0) - return -EINVAL; - - mutex_lock(&raw_mutex); - if (rawdev->inuse) { - mutex_unlock(&raw_mutex); - return -EBUSY; - } - if (rawdev->binding) - module_put(THIS_MODULE); - - rawdev->binding = dev; - if (!dev) { - /* unbind */ - device_destroy(raw_class, raw); - } else { - __module_get(THIS_MODULE); - device_destroy(raw_class, raw); - device_create(raw_class, NULL, raw, NULL, "raw%d", number); - } - mutex_unlock(&raw_mutex); - return err; -} - -static int bind_get(int number, dev_t *dev) -{ - if (number <= 0 || number >= max_raw_minors) - return -EINVAL; - *dev = raw_devices[number].binding; - return 0; -} - -/* - * Deal with ioctls against the raw-device control interface, to bind - * and unbind other raw devices. - */ -static long raw_ctl_ioctl(struct file *filp, unsigned int command, - unsigned long arg) -{ - struct raw_config_request rq; - dev_t dev; - int err; - - switch (command) { - case RAW_SETBIND: - if (copy_from_user(&rq, (void __user *) arg, sizeof(rq))) - return -EFAULT; - - return bind_set(rq.raw_minor, rq.block_major, rq.block_minor); - - case RAW_GETBIND: - if (copy_from_user(&rq, (void __user *) arg, sizeof(rq))) - return -EFAULT; - - err = bind_get(rq.raw_minor, &dev); - if (err) - return err; - - rq.block_major = MAJOR(dev); - rq.block_minor = MINOR(dev); - - if (copy_to_user((void __user *)arg, &rq, sizeof(rq))) - return -EFAULT; - - return 0; - } - - return -EINVAL; -} - -#ifdef CONFIG_COMPAT -struct raw32_config_request { - compat_int_t raw_minor; - compat_u64 block_major; - compat_u64 block_minor; -}; - -static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct raw32_config_request __user *user_req = compat_ptr(arg); - struct raw32_config_request rq; - dev_t dev; - int err = 0; - - switch (cmd) { - case RAW_SETBIND: - if (copy_from_user(&rq, user_req, sizeof(rq))) - return -EFAULT; - - return bind_set(rq.raw_minor, rq.block_major, rq.block_minor); - - case RAW_GETBIND: - if (copy_from_user(&rq, user_req, sizeof(rq))) - return -EFAULT; - - err = bind_get(rq.raw_minor, &dev); - if (err) - return err; - - rq.block_major = MAJOR(dev); - rq.block_minor = MINOR(dev); - - if (copy_to_user(user_req, &rq, sizeof(rq))) - return -EFAULT; - - return 0; - } - - return -EINVAL; -} -#endif - -static const struct file_operations raw_fops = { - .read_iter = blkdev_read_iter, - .write_iter = blkdev_write_iter, - .fsync = blkdev_fsync, - .open = raw_open, - .release = raw_release, - .unlocked_ioctl = raw_ioctl, - .llseek = default_llseek, - .owner = THIS_MODULE, -}; - -static const struct file_operations raw_ctl_fops = { - .unlocked_ioctl = raw_ctl_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = raw_ctl_compat_ioctl, -#endif - .open = raw_open, - .owner = THIS_MODULE, - .llseek = noop_llseek, -}; - -static struct cdev raw_cdev; - -static char *raw_devnode(struct device *dev, umode_t *mode) -{ - return kasprintf(GFP_KERNEL, "raw/%s", dev_name(dev)); -} - -static int __init raw_init(void) -{ - dev_t dev = MKDEV(RAW_MAJOR, 0); - int ret; - - if (max_raw_minors < 1 || max_raw_minors > 65536) { - pr_warn("raw: invalid max_raw_minors (must be between 1 and 65536), using %d\n", - CONFIG_MAX_RAW_DEVS); - max_raw_minors = CONFIG_MAX_RAW_DEVS; - } - - raw_devices = vzalloc(array_size(max_raw_minors, - sizeof(struct raw_device_data))); - if (!raw_devices) { - printk(KERN_ERR "Not enough memory for raw device structures\n"); - ret = -ENOMEM; - goto error; - } - - ret = register_chrdev_region(dev, max_raw_minors, "raw"); - if (ret) - goto error; - - cdev_init(&raw_cdev, &raw_fops); - ret = cdev_add(&raw_cdev, dev, max_raw_minors); - if (ret) - goto error_region; - raw_class = class_create(THIS_MODULE, "raw"); - if (IS_ERR(raw_class)) { - printk(KERN_ERR "Error creating raw class.\n"); - cdev_del(&raw_cdev); - ret = PTR_ERR(raw_class); - goto error_region; - } - raw_class->devnode = raw_devnode; - device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl"); - - return 0; - -error_region: - unregister_chrdev_region(dev, max_raw_minors); -error: - vfree(raw_devices); - return ret; -} - -static void __exit raw_exit(void) -{ - device_destroy(raw_class, MKDEV(RAW_MAJOR, 0)); - class_destroy(raw_class); - cdev_del(&raw_cdev); - unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), max_raw_minors); -} - -module_init(raw_init); -module_exit(raw_exit); -MODULE_LICENSE("GPL"); diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c index 93f5d11c830b..230b2c9b3e3c 100644 --- a/drivers/char/ttyprintk.c +++ b/drivers/char/ttyprintk.c @@ -52,12 +52,7 @@ static void tpk_flush(void) static int tpk_printk(const unsigned char *buf, int count) { - int i = tpk_curr; - - if (buf == NULL) { - tpk_flush(); - return i; - } + int i; for (i = 0; i < count; i++) { if (tpk_curr >= TPK_STR_SIZE) { @@ -100,12 +95,6 @@ static int tpk_open(struct tty_struct *tty, struct file *filp) static void tpk_close(struct tty_struct *tty, struct file *filp) { struct ttyprintk_port *tpkp = tty->driver_data; - unsigned long flags; - - spin_lock_irqsave(&tpkp->spinlock, flags); - /* flush tpk_printk buffer */ - tpk_printk(NULL, 0); - spin_unlock_irqrestore(&tpkp->spinlock, flags); tty_port_close(&tpkp->port, tty, filp); } @@ -120,7 +109,6 @@ static int tpk_write(struct tty_struct *tty, unsigned long flags; int ret; - /* exclusive use of tpk_printk within this tty */ spin_lock_irqsave(&tpkp->spinlock, flags); ret = tpk_printk(buf, count); @@ -132,40 +120,33 @@ static int tpk_write(struct tty_struct *tty, /* * TTY operations write_room function. */ -static int tpk_write_room(struct tty_struct *tty) +static unsigned int tpk_write_room(struct tty_struct *tty) { return TPK_MAX_ROOM; } /* - * TTY operations ioctl function. + * TTY operations hangup function. */ -static int tpk_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) +static void tpk_hangup(struct tty_struct *tty) { struct ttyprintk_port *tpkp = tty->driver_data; - if (!tpkp) - return -EINVAL; - - switch (cmd) { - /* Stop TIOCCONS */ - case TIOCCONS: - return -EOPNOTSUPP; - default: - return -ENOIOCTLCMD; - } - return 0; + tty_port_hangup(&tpkp->port); } /* - * TTY operations hangup function. + * TTY port operations shutdown function. */ -static void tpk_hangup(struct tty_struct *tty) +static void tpk_port_shutdown(struct tty_port *tport) { - struct ttyprintk_port *tpkp = tty->driver_data; + struct ttyprintk_port *tpkp = + container_of(tport, struct ttyprintk_port, port); + unsigned long flags; - tty_port_hangup(&tpkp->port); + spin_lock_irqsave(&tpkp->spinlock, flags); + tpk_flush(); + spin_unlock_irqrestore(&tpkp->spinlock, flags); } static const struct tty_operations ttyprintk_ops = { @@ -173,11 +154,12 @@ static const struct tty_operations ttyprintk_ops = { .close = tpk_close, .write = tpk_write, .write_room = tpk_write_room, - .ioctl = tpk_ioctl, .hangup = tpk_hangup, }; -static const struct tty_port_operations null_ops = { }; +static const struct tty_port_operations tpk_port_ops = { + .shutdown = tpk_port_shutdown, +}; static struct tty_driver *ttyprintk_driver; @@ -195,7 +177,7 @@ static int __init ttyprintk_init(void) return PTR_ERR(ttyprintk_driver); tty_port_init(&tpk_port.port); - tpk_port.port.ops = &null_ops; + tpk_port.port.ops = &tpk_port_ops; ttyprintk_driver->driver_name = "ttyprintk"; ttyprintk_driver->name = "ttyprintk"; diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 59dfd9c421a1..7eaf303a7a86 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -475,7 +475,7 @@ static struct port_buffer *get_inbuf(struct port *port) buf = virtqueue_get_buf(port->in_vq, &len); if (buf) { - buf->len = len; + buf->len = min_t(size_t, len, buf->size); buf->offset = 0; port->stats.bytes_received += len; } @@ -1709,7 +1709,7 @@ static void control_work_handler(struct work_struct *work) while ((buf = virtqueue_get_buf(vq, &len))) { spin_unlock(&portdev->c_ivq_lock); - buf->len = len; + buf->len = min_t(size_t, len, buf->size); buf->offset = 0; handle_control_message(vq->vdev, portdev, buf); diff --git a/drivers/char/xillybus/Kconfig b/drivers/char/xillybus/Kconfig index 130dbdce858f..a8036dad437e 100644 --- a/drivers/char/xillybus/Kconfig +++ b/drivers/char/xillybus/Kconfig @@ -3,10 +3,14 @@ # Xillybus devices # +config XILLYBUS_CLASS + tristate + config XILLYBUS tristate "Xillybus generic FPGA interface" depends on PCI || OF select CRC32 + select XILLYBUS_CLASS help Xillybus is a generic interface for peripherals designed on programmable logic (FPGA). The driver probes the hardware for @@ -21,7 +25,7 @@ config XILLYBUS_PCIE depends on PCI_MSI help Set to M if you want Xillybus to use PCI Express for communicating - with the FPGA. + with the FPGA. The module will be called xillybus_pcie. config XILLYBUS_OF tristate "Xillybus over Device Tree" @@ -29,6 +33,20 @@ config XILLYBUS_OF help Set to M if you want Xillybus to find its resources from the Open Firmware Flattened Device Tree. If the target is an embedded - system, say M. + system, say M. The module will be called xillybus_of. endif # if XILLYBUS + +# XILLYUSB doesn't depend on XILLYBUS + +config XILLYUSB + tristate "XillyUSB: Xillybus generic FPGA interface for USB" + depends on USB + select CRC32 + select XILLYBUS_CLASS + help + XillyUSB is the Xillybus variant which uses USB for communicating + with the FPGA. + + Set to M if you want Xillybus to use USB for communicating with + the FPGA. The module will be called xillyusb. diff --git a/drivers/char/xillybus/Makefile b/drivers/char/xillybus/Makefile index 099e9a3585fc..16f31d03209d 100644 --- a/drivers/char/xillybus/Makefile +++ b/drivers/char/xillybus/Makefile @@ -3,6 +3,8 @@ # Makefile for Xillybus driver # +obj-$(CONFIG_XILLYBUS_CLASS) += xillybus_class.o obj-$(CONFIG_XILLYBUS) += xillybus_core.o obj-$(CONFIG_XILLYBUS_PCIE) += xillybus_pcie.o obj-$(CONFIG_XILLYBUS_OF) += xillybus_of.o +obj-$(CONFIG_XILLYUSB) += xillyusb.o diff --git a/drivers/char/xillybus/xillybus.h b/drivers/char/xillybus/xillybus.h index 8e3ed4d1bb7f..c63ffc56637c 100644 --- a/drivers/char/xillybus/xillybus.h +++ b/drivers/char/xillybus/xillybus.h @@ -30,7 +30,8 @@ struct xilly_buffer { struct xilly_idt_handle { unsigned char *chandesc; - unsigned char *idt; + unsigned char *names; + int names_len; int entries; }; @@ -94,7 +95,6 @@ struct xilly_endpoint { struct device *dev; struct xilly_endpoint_hardware *ephw; - struct list_head ep_list; int dma_using_dac; /* =1 if 64-bit DMA is used, =0 otherwise. */ __iomem void *registers; int fatal_error; @@ -102,12 +102,6 @@ struct xilly_endpoint { struct mutex register_mutex; wait_queue_head_t ep_wait; - /* Channels and message handling */ - struct cdev cdev; - - int major; - int lowest_minor; /* Highest minor = lowest_minor + num_channels - 1 */ - int num_channels; /* EXCLUDING message buffer */ struct xilly_channel **channels; int msg_counter; diff --git a/drivers/char/xillybus/xillybus_class.c b/drivers/char/xillybus/xillybus_class.c new file mode 100644 index 000000000000..5046486011c8 --- /dev/null +++ b/drivers/char/xillybus/xillybus_class.c @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2021 Xillybus Ltd, http://xillybus.com + * + * Driver for the Xillybus class + */ + +#include <linux/types.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/fs.h> +#include <linux/cdev.h> +#include <linux/slab.h> +#include <linux/list.h> +#include <linux/mutex.h> + +#include "xillybus_class.h" + +MODULE_DESCRIPTION("Driver for Xillybus class"); +MODULE_AUTHOR("Eli Billauer, Xillybus Ltd."); +MODULE_ALIAS("xillybus_class"); +MODULE_LICENSE("GPL v2"); + +static DEFINE_MUTEX(unit_mutex); +static LIST_HEAD(unit_list); +static struct class *xillybus_class; + +#define UNITNAMELEN 16 + +struct xilly_unit { + struct list_head list_entry; + void *private_data; + + struct cdev *cdev; + char name[UNITNAMELEN]; + int major; + int lowest_minor; + int num_nodes; +}; + +int xillybus_init_chrdev(struct device *dev, + const struct file_operations *fops, + struct module *owner, + void *private_data, + unsigned char *idt, unsigned int len, + int num_nodes, + const char *prefix, bool enumerate) +{ + int rc; + dev_t mdev; + int i; + char devname[48]; + + struct device *device; + size_t namelen; + struct xilly_unit *unit, *u; + + unit = kzalloc(sizeof(*unit), GFP_KERNEL); + + if (!unit) + return -ENOMEM; + + mutex_lock(&unit_mutex); + + if (!enumerate) + snprintf(unit->name, UNITNAMELEN, "%s", prefix); + + for (i = 0; enumerate; i++) { + snprintf(unit->name, UNITNAMELEN, "%s_%02d", + prefix, i); + + enumerate = false; + list_for_each_entry(u, &unit_list, list_entry) + if (!strcmp(unit->name, u->name)) { + enumerate = true; + break; + } + } + + rc = alloc_chrdev_region(&mdev, 0, num_nodes, unit->name); + + if (rc) { + dev_warn(dev, "Failed to obtain major/minors"); + goto fail_obtain; + } + + unit->major = MAJOR(mdev); + unit->lowest_minor = MINOR(mdev); + unit->num_nodes = num_nodes; + unit->private_data = private_data; + + unit->cdev = cdev_alloc(); + if (!unit->cdev) { + rc = -ENOMEM; + goto unregister_chrdev; + } + unit->cdev->ops = fops; + unit->cdev->owner = owner; + + rc = cdev_add(unit->cdev, MKDEV(unit->major, unit->lowest_minor), + unit->num_nodes); + if (rc) { + dev_err(dev, "Failed to add cdev.\n"); + /* kobject_put() is normally done by cdev_del() */ + kobject_put(&unit->cdev->kobj); + goto unregister_chrdev; + } + + for (i = 0; i < num_nodes; i++) { + namelen = strnlen(idt, len); + + if (namelen == len) { + dev_err(dev, "IDT's list of names is too short. This is exceptionally weird, because its CRC is OK\n"); + rc = -ENODEV; + goto unroll_device_create; + } + + snprintf(devname, sizeof(devname), "%s_%s", + unit->name, idt); + + len -= namelen + 1; + idt += namelen + 1; + + device = device_create(xillybus_class, + NULL, + MKDEV(unit->major, + i + unit->lowest_minor), + NULL, + "%s", devname); + + if (IS_ERR(device)) { + dev_err(dev, "Failed to create %s device. Aborting.\n", + devname); + rc = -ENODEV; + goto unroll_device_create; + } + } + + if (len) { + dev_err(dev, "IDT's list of names is too long. This is exceptionally weird, because its CRC is OK\n"); + rc = -ENODEV; + goto unroll_device_create; + } + + list_add_tail(&unit->list_entry, &unit_list); + + dev_info(dev, "Created %d device files.\n", num_nodes); + + mutex_unlock(&unit_mutex); + + return 0; + +unroll_device_create: + for (i--; i >= 0; i--) + device_destroy(xillybus_class, MKDEV(unit->major, + i + unit->lowest_minor)); + + cdev_del(unit->cdev); + +unregister_chrdev: + unregister_chrdev_region(MKDEV(unit->major, unit->lowest_minor), + unit->num_nodes); + +fail_obtain: + mutex_unlock(&unit_mutex); + + kfree(unit); + + return rc; +} +EXPORT_SYMBOL(xillybus_init_chrdev); + +void xillybus_cleanup_chrdev(void *private_data, + struct device *dev) +{ + int minor; + struct xilly_unit *unit; + bool found = false; + + mutex_lock(&unit_mutex); + + list_for_each_entry(unit, &unit_list, list_entry) + if (unit->private_data == private_data) { + found = true; + break; + } + + if (!found) { + dev_err(dev, "Weird bug: Failed to find unit\n"); + mutex_unlock(&unit_mutex); + return; + } + + for (minor = unit->lowest_minor; + minor < (unit->lowest_minor + unit->num_nodes); + minor++) + device_destroy(xillybus_class, MKDEV(unit->major, minor)); + + cdev_del(unit->cdev); + + unregister_chrdev_region(MKDEV(unit->major, unit->lowest_minor), + unit->num_nodes); + + dev_info(dev, "Removed %d device files.\n", + unit->num_nodes); + + list_del(&unit->list_entry); + kfree(unit); + + mutex_unlock(&unit_mutex); +} +EXPORT_SYMBOL(xillybus_cleanup_chrdev); + +int xillybus_find_inode(struct inode *inode, + void **private_data, int *index) +{ + int minor = iminor(inode); + int major = imajor(inode); + struct xilly_unit *unit; + bool found = false; + + mutex_lock(&unit_mutex); + + list_for_each_entry(unit, &unit_list, list_entry) + if (unit->major == major && + minor >= unit->lowest_minor && + minor < (unit->lowest_minor + unit->num_nodes)) { + found = true; + break; + } + + mutex_unlock(&unit_mutex); + + if (!found) + return -ENODEV; + + *private_data = unit->private_data; + *index = minor - unit->lowest_minor; + + return 0; +} +EXPORT_SYMBOL(xillybus_find_inode); + +static int __init xillybus_class_init(void) +{ + xillybus_class = class_create(THIS_MODULE, "xillybus"); + + if (IS_ERR(xillybus_class)) { + pr_warn("Failed to register xillybus class\n"); + + return PTR_ERR(xillybus_class); + } + return 0; +} + +static void __exit xillybus_class_exit(void) +{ + class_destroy(xillybus_class); +} + +module_init(xillybus_class_init); +module_exit(xillybus_class_exit); diff --git a/drivers/char/xillybus/xillybus_class.h b/drivers/char/xillybus/xillybus_class.h new file mode 100644 index 000000000000..5dbfdfc95c65 --- /dev/null +++ b/drivers/char/xillybus/xillybus_class.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright 2021 Xillybus Ltd, http://www.xillybus.com + * + * Header file for the Xillybus class + */ + +#ifndef __XILLYBUS_CLASS_H +#define __XILLYBUS_CLASS_H + +#include <linux/types.h> +#include <linux/device.h> +#include <linux/fs.h> +#include <linux/module.h> + +int xillybus_init_chrdev(struct device *dev, + const struct file_operations *fops, + struct module *owner, + void *private_data, + unsigned char *idt, unsigned int len, + int num_nodes, + const char *prefix, bool enumerate); + +void xillybus_cleanup_chrdev(void *private_data, + struct device *dev); + +int xillybus_find_inode(struct inode *inode, + void **private_data, int *index); + +#endif /* __XILLYBUS_CLASS_H */ diff --git a/drivers/char/xillybus/xillybus_core.c b/drivers/char/xillybus/xillybus_core.c index 57fa68834981..931d0bf4cec6 100644 --- a/drivers/char/xillybus/xillybus_core.c +++ b/drivers/char/xillybus/xillybus_core.c @@ -21,7 +21,6 @@ #include <linux/interrupt.h> #include <linux/sched.h> #include <linux/fs.h> -#include <linux/cdev.h> #include <linux/spinlock.h> #include <linux/mutex.h> #include <linux/crc32.h> @@ -30,10 +29,10 @@ #include <linux/slab.h> #include <linux/workqueue.h> #include "xillybus.h" +#include "xillybus_class.h" MODULE_DESCRIPTION("Xillybus core functions"); MODULE_AUTHOR("Eli Billauer, Xillybus Ltd."); -MODULE_VERSION("1.07"); MODULE_ALIAS("xillybus_core"); MODULE_LICENSE("GPL v2"); @@ -58,16 +57,6 @@ MODULE_LICENSE("GPL v2"); static const char xillyname[] = "xillybus"; -static struct class *xillybus_class; - -/* - * ep_list_lock is the last lock to be taken; No other lock requests are - * allowed while holding it. It merely protects list_of_endpoints, and not - * the endpoints listed in it. - */ - -static LIST_HEAD(list_of_endpoints); -static struct mutex ep_list_lock; static struct workqueue_struct *xillybus_wq; /* @@ -570,10 +559,8 @@ static int xilly_scan_idt(struct xilly_endpoint *endpoint, unsigned char *scan; int len; - scan = idt; - idt_handle->idt = idt; - - scan++; /* Skip version number */ + scan = idt + 1; + idt_handle->names = scan; while ((scan <= end_of_idt) && *scan) { while ((scan <= end_of_idt) && *scan++) @@ -581,6 +568,8 @@ static int xilly_scan_idt(struct xilly_endpoint *endpoint, count++; } + idt_handle->names_len = scan - idt_handle->names; + scan++; if (scan > end_of_idt) { @@ -1407,36 +1396,20 @@ static ssize_t xillybus_write(struct file *filp, const char __user *userbuf, static int xillybus_open(struct inode *inode, struct file *filp) { - int rc = 0; + int rc; unsigned long flags; - int minor = iminor(inode); - int major = imajor(inode); - struct xilly_endpoint *ep_iter, *endpoint = NULL; + struct xilly_endpoint *endpoint; struct xilly_channel *channel; + int index; - mutex_lock(&ep_list_lock); - - list_for_each_entry(ep_iter, &list_of_endpoints, ep_list) { - if ((ep_iter->major == major) && - (minor >= ep_iter->lowest_minor) && - (minor < (ep_iter->lowest_minor + - ep_iter->num_channels))) { - endpoint = ep_iter; - break; - } - } - mutex_unlock(&ep_list_lock); - - if (!endpoint) { - pr_err("xillybus: open() failed to find a device for major=%d and minor=%d\n", - major, minor); - return -ENODEV; - } + rc = xillybus_find_inode(inode, (void **)&endpoint, &index); + if (rc) + return rc; if (endpoint->fatal_error) return -EIO; - channel = endpoint->channels[1 + minor - endpoint->lowest_minor]; + channel = endpoint->channels[1 + index]; filp->private_data = channel; /* @@ -1799,95 +1772,6 @@ static const struct file_operations xillybus_fops = { .poll = xillybus_poll, }; -static int xillybus_init_chrdev(struct xilly_endpoint *endpoint, - const unsigned char *idt) -{ - int rc; - dev_t dev; - int devnum, i, minor, major; - char devname[48]; - struct device *device; - - rc = alloc_chrdev_region(&dev, 0, /* minor start */ - endpoint->num_channels, - xillyname); - if (rc) { - dev_warn(endpoint->dev, "Failed to obtain major/minors"); - return rc; - } - - endpoint->major = major = MAJOR(dev); - endpoint->lowest_minor = minor = MINOR(dev); - - cdev_init(&endpoint->cdev, &xillybus_fops); - endpoint->cdev.owner = endpoint->ephw->owner; - rc = cdev_add(&endpoint->cdev, MKDEV(major, minor), - endpoint->num_channels); - if (rc) { - dev_warn(endpoint->dev, "Failed to add cdev. Aborting.\n"); - goto unregister_chrdev; - } - - idt++; - - for (i = minor, devnum = 0; - devnum < endpoint->num_channels; - devnum++, i++) { - snprintf(devname, sizeof(devname)-1, "xillybus_%s", idt); - - devname[sizeof(devname)-1] = 0; /* Should never matter */ - - while (*idt++) - /* Skip to next */; - - device = device_create(xillybus_class, - NULL, - MKDEV(major, i), - NULL, - "%s", devname); - - if (IS_ERR(device)) { - dev_warn(endpoint->dev, - "Failed to create %s device. Aborting.\n", - devname); - rc = -ENODEV; - goto unroll_device_create; - } - } - - dev_info(endpoint->dev, "Created %d device files.\n", - endpoint->num_channels); - return 0; /* succeed */ - -unroll_device_create: - devnum--; i--; - for (; devnum >= 0; devnum--, i--) - device_destroy(xillybus_class, MKDEV(major, i)); - - cdev_del(&endpoint->cdev); -unregister_chrdev: - unregister_chrdev_region(MKDEV(major, minor), endpoint->num_channels); - - return rc; -} - -static void xillybus_cleanup_chrdev(struct xilly_endpoint *endpoint) -{ - int minor; - - for (minor = endpoint->lowest_minor; - minor < (endpoint->lowest_minor + endpoint->num_channels); - minor++) - device_destroy(xillybus_class, MKDEV(endpoint->major, minor)); - cdev_del(&endpoint->cdev); - unregister_chrdev_region(MKDEV(endpoint->major, - endpoint->lowest_minor), - endpoint->num_channels); - - dev_info(endpoint->dev, "Removed %d device files.\n", - endpoint->num_channels); -} - struct xilly_endpoint *xillybus_init_endpoint(struct pci_dev *pdev, struct device *dev, struct xilly_endpoint_hardware @@ -2027,28 +1911,20 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint) if (rc) goto failed_idt; - /* - * endpoint is now completely configured. We put it on the list - * available to open() before registering the char device(s) - */ - - mutex_lock(&ep_list_lock); - list_add_tail(&endpoint->ep_list, &list_of_endpoints); - mutex_unlock(&ep_list_lock); + rc = xillybus_init_chrdev(dev, &xillybus_fops, + endpoint->ephw->owner, endpoint, + idt_handle.names, + idt_handle.names_len, + endpoint->num_channels, + xillyname, false); - rc = xillybus_init_chrdev(endpoint, idt_handle.idt); if (rc) - goto failed_chrdevs; + goto failed_idt; devres_release_group(dev, bootstrap_resources); return 0; -failed_chrdevs: - mutex_lock(&ep_list_lock); - list_del(&endpoint->ep_list); - mutex_unlock(&ep_list_lock); - failed_idt: xilly_quiesce(endpoint); flush_workqueue(xillybus_wq); @@ -2059,11 +1935,7 @@ EXPORT_SYMBOL(xillybus_endpoint_discovery); void xillybus_endpoint_remove(struct xilly_endpoint *endpoint) { - xillybus_cleanup_chrdev(endpoint); - - mutex_lock(&ep_list_lock); - list_del(&endpoint->ep_list); - mutex_unlock(&ep_list_lock); + xillybus_cleanup_chrdev(endpoint, endpoint->dev); xilly_quiesce(endpoint); @@ -2077,17 +1949,9 @@ EXPORT_SYMBOL(xillybus_endpoint_remove); static int __init xillybus_init(void) { - mutex_init(&ep_list_lock); - - xillybus_class = class_create(THIS_MODULE, xillyname); - if (IS_ERR(xillybus_class)) - return PTR_ERR(xillybus_class); - xillybus_wq = alloc_workqueue(xillyname, 0, 0); - if (!xillybus_wq) { - class_destroy(xillybus_class); + if (!xillybus_wq) return -ENOMEM; - } return 0; } @@ -2096,8 +1960,6 @@ static void __exit xillybus_exit(void) { /* flush_workqueue() was called for each endpoint released */ destroy_workqueue(xillybus_wq); - - class_destroy(xillybus_class); } module_init(xillybus_init); diff --git a/drivers/char/xillybus/xillybus_of.c b/drivers/char/xillybus/xillybus_of.c index 96b6de8a30e5..1a20b286fd1d 100644 --- a/drivers/char/xillybus/xillybus_of.c +++ b/drivers/char/xillybus/xillybus_of.c @@ -17,7 +17,6 @@ MODULE_DESCRIPTION("Xillybus driver for Open Firmware"); MODULE_AUTHOR("Eli Billauer, Xillybus Ltd."); -MODULE_VERSION("1.06"); MODULE_ALIAS("xillybus_of"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/char/xillybus/xillybus_pcie.c b/drivers/char/xillybus/xillybus_pcie.c index 18b0c392bc93..bdf1c366b4fc 100644 --- a/drivers/char/xillybus/xillybus_pcie.c +++ b/drivers/char/xillybus/xillybus_pcie.c @@ -14,7 +14,6 @@ MODULE_DESCRIPTION("Xillybus driver for PCIe"); MODULE_AUTHOR("Eli Billauer, Xillybus Ltd."); -MODULE_VERSION("1.06"); MODULE_ALIAS("xillybus_pcie"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/char/xillybus/xillyusb.c b/drivers/char/xillybus/xillyusb.c new file mode 100644 index 000000000000..e7f88f35c702 --- /dev/null +++ b/drivers/char/xillybus/xillyusb.c @@ -0,0 +1,2259 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2020 Xillybus Ltd, http://xillybus.com + * + * Driver for the XillyUSB FPGA/host framework. + * + * This driver interfaces with a special IP core in an FPGA, setting up + * a pipe between a hardware FIFO in the programmable logic and a device + * file in the host. The number of such pipes and their attributes are + * set up on the logic. This driver detects these automatically and + * creates the device files accordingly. + */ + +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/list.h> +#include <linux/device.h> +#include <linux/module.h> +#include <asm/byteorder.h> +#include <linux/io.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include <linux/fs.h> +#include <linux/spinlock.h> +#include <linux/mutex.h> +#include <linux/workqueue.h> +#include <linux/crc32.h> +#include <linux/poll.h> +#include <linux/delay.h> +#include <linux/usb.h> + +#include "xillybus_class.h" + +MODULE_DESCRIPTION("Driver for XillyUSB FPGA IP Core"); +MODULE_AUTHOR("Eli Billauer, Xillybus Ltd."); +MODULE_ALIAS("xillyusb"); +MODULE_LICENSE("GPL v2"); + +#define XILLY_RX_TIMEOUT (10 * HZ / 1000) +#define XILLY_RESPONSE_TIMEOUT (500 * HZ / 1000) + +#define BUF_SIZE_ORDER 4 +#define BUFNUM 8 +#define LOG2_IDT_FIFO_SIZE 16 +#define LOG2_INITIAL_FIFO_BUF_SIZE 16 + +#define MSG_EP_NUM 1 +#define IN_EP_NUM 1 + +static const char xillyname[] = "xillyusb"; + +static unsigned int fifo_buf_order; + +#define USB_VENDOR_ID_XILINX 0x03fd +#define USB_VENDOR_ID_ALTERA 0x09fb + +#define USB_PRODUCT_ID_XILLYUSB 0xebbe + +static const struct usb_device_id xillyusb_table[] = { + { USB_DEVICE(USB_VENDOR_ID_XILINX, USB_PRODUCT_ID_XILLYUSB) }, + { USB_DEVICE(USB_VENDOR_ID_ALTERA, USB_PRODUCT_ID_XILLYUSB) }, + { } +}; + +MODULE_DEVICE_TABLE(usb, xillyusb_table); + +struct xillyusb_dev; + +struct xillyfifo { + unsigned int bufsize; /* In bytes, always a power of 2 */ + unsigned int bufnum; + unsigned int size; /* Lazy: Equals bufsize * bufnum */ + unsigned int buf_order; + + int fill; /* Number of bytes in the FIFO */ + spinlock_t lock; + wait_queue_head_t waitq; + + unsigned int readpos; + unsigned int readbuf; + unsigned int writepos; + unsigned int writebuf; + char **mem; +}; + +struct xillyusb_channel; + +struct xillyusb_endpoint { + struct xillyusb_dev *xdev; + + struct mutex ep_mutex; /* serialize operations on endpoint */ + + struct list_head buffers; + struct list_head filled_buffers; + spinlock_t buffers_lock; /* protect these two lists */ + + unsigned int order; + unsigned int buffer_size; + + unsigned int fill_mask; + + int outstanding_urbs; + + struct usb_anchor anchor; + + struct xillyfifo fifo; + + struct work_struct workitem; + + bool shutting_down; + bool drained; + bool wake_on_drain; + + u8 ep_num; +}; + +struct xillyusb_channel { + struct xillyusb_dev *xdev; + + struct xillyfifo *in_fifo; + struct xillyusb_endpoint *out_ep; + struct mutex lock; /* protect @out_ep, @in_fifo, bit fields below */ + + struct mutex in_mutex; /* serialize fops on FPGA to host stream */ + struct mutex out_mutex; /* serialize fops on host to FPGA stream */ + wait_queue_head_t flushq; + + int chan_idx; + + u32 in_consumed_bytes; + u32 in_current_checkpoint; + u32 out_bytes; + + unsigned int in_log2_element_size; + unsigned int out_log2_element_size; + unsigned int in_log2_fifo_size; + unsigned int out_log2_fifo_size; + + unsigned int read_data_ok; /* EOF not arrived (yet) */ + unsigned int poll_used; + unsigned int flushing; + unsigned int flushed; + unsigned int canceled; + + /* Bit fields protected by @lock except for initialization */ + unsigned readable:1; + unsigned writable:1; + unsigned open_for_read:1; + unsigned open_for_write:1; + unsigned in_synchronous:1; + unsigned out_synchronous:1; + unsigned in_seekable:1; + unsigned out_seekable:1; +}; + +struct xillybuffer { + struct list_head entry; + struct xillyusb_endpoint *ep; + void *buf; + unsigned int len; +}; + +struct xillyusb_dev { + struct xillyusb_channel *channels; + + struct usb_device *udev; + struct device *dev; /* For dev_err() and such */ + struct kref kref; + struct workqueue_struct *workq; + + int error; + spinlock_t error_lock; /* protect @error */ + struct work_struct wakeup_workitem; + + int num_channels; + + struct xillyusb_endpoint *msg_ep; + struct xillyusb_endpoint *in_ep; + + struct mutex msg_mutex; /* serialize opcode transmission */ + int in_bytes_left; + int leftover_chan_num; + unsigned int in_counter; + struct mutex process_in_mutex; /* synchronize wakeup_all() */ +}; + +/* FPGA to host opcodes */ +enum { + OPCODE_DATA = 0, + OPCODE_QUIESCE_ACK = 1, + OPCODE_EOF = 2, + OPCODE_REACHED_CHECKPOINT = 3, + OPCODE_CANCELED_CHECKPOINT = 4, +}; + +/* Host to FPGA opcodes */ +enum { + OPCODE_QUIESCE = 0, + OPCODE_REQ_IDT = 1, + OPCODE_SET_CHECKPOINT = 2, + OPCODE_CLOSE = 3, + OPCODE_SET_PUSH = 4, + OPCODE_UPDATE_PUSH = 5, + OPCODE_CANCEL_CHECKPOINT = 6, + OPCODE_SET_ADDR = 7, +}; + +/* + * fifo_write() and fifo_read() are NOT reentrant (i.e. concurrent multiple + * calls to each on the same FIFO is not allowed) however it's OK to have + * threads calling each of the two functions once on the same FIFO, and + * at the same time. + */ + +static int fifo_write(struct xillyfifo *fifo, + const void *data, unsigned int len, + int (*copier)(void *, const void *, int)) +{ + unsigned int done = 0; + unsigned int todo = len; + unsigned int nmax; + unsigned int writepos = fifo->writepos; + unsigned int writebuf = fifo->writebuf; + unsigned long flags; + int rc; + + nmax = fifo->size - READ_ONCE(fifo->fill); + + while (1) { + unsigned int nrail = fifo->bufsize - writepos; + unsigned int n = min(todo, nmax); + + if (n == 0) { + spin_lock_irqsave(&fifo->lock, flags); + fifo->fill += done; + spin_unlock_irqrestore(&fifo->lock, flags); + + fifo->writepos = writepos; + fifo->writebuf = writebuf; + + return done; + } + + if (n > nrail) + n = nrail; + + rc = (*copier)(fifo->mem[writebuf] + writepos, data + done, n); + + if (rc) + return rc; + + done += n; + todo -= n; + + writepos += n; + nmax -= n; + + if (writepos == fifo->bufsize) { + writepos = 0; + writebuf++; + + if (writebuf == fifo->bufnum) + writebuf = 0; + } + } +} + +static int fifo_read(struct xillyfifo *fifo, + void *data, unsigned int len, + int (*copier)(void *, const void *, int)) +{ + unsigned int done = 0; + unsigned int todo = len; + unsigned int fill; + unsigned int readpos = fifo->readpos; + unsigned int readbuf = fifo->readbuf; + unsigned long flags; + int rc; + + /* + * The spinlock here is necessary, because otherwise fifo->fill + * could have been increased by fifo_write() after writing data + * to the buffer, but this data would potentially not have been + * visible on this thread at the time the updated fifo->fill was. + * That could lead to reading invalid data. + */ + + spin_lock_irqsave(&fifo->lock, flags); + fill = fifo->fill; + spin_unlock_irqrestore(&fifo->lock, flags); + + while (1) { + unsigned int nrail = fifo->bufsize - readpos; + unsigned int n = min(todo, fill); + + if (n == 0) { + spin_lock_irqsave(&fifo->lock, flags); + fifo->fill -= done; + spin_unlock_irqrestore(&fifo->lock, flags); + + fifo->readpos = readpos; + fifo->readbuf = readbuf; + + return done; + } + + if (n > nrail) + n = nrail; + + rc = (*copier)(data + done, fifo->mem[readbuf] + readpos, n); + + if (rc) + return rc; + + done += n; + todo -= n; + + readpos += n; + fill -= n; + + if (readpos == fifo->bufsize) { + readpos = 0; + readbuf++; + + if (readbuf == fifo->bufnum) + readbuf = 0; + } + } +} + +/* + * These three wrapper functions are used as the @copier argument to + * fifo_write() and fifo_read(), so that they can work directly with + * user memory as well. + */ + +static int xilly_copy_from_user(void *dst, const void *src, int n) +{ + if (copy_from_user(dst, (const void __user *)src, n)) + return -EFAULT; + + return 0; +} + +static int xilly_copy_to_user(void *dst, const void *src, int n) +{ + if (copy_to_user((void __user *)dst, src, n)) + return -EFAULT; + + return 0; +} + +static int xilly_memcpy(void *dst, const void *src, int n) +{ + memcpy(dst, src, n); + + return 0; +} + +static int fifo_init(struct xillyfifo *fifo, + unsigned int log2_size) +{ + unsigned int log2_bufnum; + unsigned int buf_order; + int i; + + unsigned int log2_fifo_buf_size; + +retry: + log2_fifo_buf_size = fifo_buf_order + PAGE_SHIFT; + + if (log2_size > log2_fifo_buf_size) { + log2_bufnum = log2_size - log2_fifo_buf_size; + buf_order = fifo_buf_order; + fifo->bufsize = 1 << log2_fifo_buf_size; + } else { + log2_bufnum = 0; + buf_order = (log2_size > PAGE_SHIFT) ? + log2_size - PAGE_SHIFT : 0; + fifo->bufsize = 1 << log2_size; + } + + fifo->bufnum = 1 << log2_bufnum; + fifo->size = fifo->bufnum * fifo->bufsize; + fifo->buf_order = buf_order; + + fifo->mem = kmalloc_array(fifo->bufnum, sizeof(void *), GFP_KERNEL); + + if (!fifo->mem) + return -ENOMEM; + + for (i = 0; i < fifo->bufnum; i++) { + fifo->mem[i] = (void *) + __get_free_pages(GFP_KERNEL, buf_order); + + if (!fifo->mem[i]) + goto memfail; + } + + fifo->fill = 0; + fifo->readpos = 0; + fifo->readbuf = 0; + fifo->writepos = 0; + fifo->writebuf = 0; + spin_lock_init(&fifo->lock); + init_waitqueue_head(&fifo->waitq); + return 0; + +memfail: + for (i--; i >= 0; i--) + free_pages((unsigned long)fifo->mem[i], buf_order); + + kfree(fifo->mem); + fifo->mem = NULL; + + if (fifo_buf_order) { + fifo_buf_order--; + goto retry; + } else { + return -ENOMEM; + } +} + +static void fifo_mem_release(struct xillyfifo *fifo) +{ + int i; + + if (!fifo->mem) + return; + + for (i = 0; i < fifo->bufnum; i++) + free_pages((unsigned long)fifo->mem[i], fifo->buf_order); + + kfree(fifo->mem); +} + +/* + * When endpoint_quiesce() returns, the endpoint has no URBs submitted, + * won't accept any new URB submissions, and its related work item doesn't + * and won't run anymore. + */ + +static void endpoint_quiesce(struct xillyusb_endpoint *ep) +{ + mutex_lock(&ep->ep_mutex); + ep->shutting_down = true; + mutex_unlock(&ep->ep_mutex); + + usb_kill_anchored_urbs(&ep->anchor); + cancel_work_sync(&ep->workitem); +} + +/* + * Note that endpoint_dealloc() also frees fifo memory (if allocated), even + * though endpoint_alloc doesn't allocate that memory. + */ + +static void endpoint_dealloc(struct xillyusb_endpoint *ep) +{ + struct list_head *this, *next; + + fifo_mem_release(&ep->fifo); + + /* Join @filled_buffers with @buffers to free these entries too */ + list_splice(&ep->filled_buffers, &ep->buffers); + + list_for_each_safe(this, next, &ep->buffers) { + struct xillybuffer *xb = + list_entry(this, struct xillybuffer, entry); + + free_pages((unsigned long)xb->buf, ep->order); + kfree(xb); + } + + kfree(ep); +} + +static struct xillyusb_endpoint +*endpoint_alloc(struct xillyusb_dev *xdev, + u8 ep_num, + void (*work)(struct work_struct *), + unsigned int order, + int bufnum) +{ + int i; + + struct xillyusb_endpoint *ep; + + ep = kzalloc(sizeof(*ep), GFP_KERNEL); + + if (!ep) + return NULL; + + INIT_LIST_HEAD(&ep->buffers); + INIT_LIST_HEAD(&ep->filled_buffers); + + spin_lock_init(&ep->buffers_lock); + mutex_init(&ep->ep_mutex); + + init_usb_anchor(&ep->anchor); + INIT_WORK(&ep->workitem, work); + + ep->order = order; + ep->buffer_size = 1 << (PAGE_SHIFT + order); + ep->outstanding_urbs = 0; + ep->drained = true; + ep->wake_on_drain = false; + ep->xdev = xdev; + ep->ep_num = ep_num; + ep->shutting_down = false; + + for (i = 0; i < bufnum; i++) { + struct xillybuffer *xb; + unsigned long addr; + + xb = kzalloc(sizeof(*xb), GFP_KERNEL); + + if (!xb) { + endpoint_dealloc(ep); + return NULL; + } + + addr = __get_free_pages(GFP_KERNEL, order); + + if (!addr) { + kfree(xb); + endpoint_dealloc(ep); + return NULL; + } + + xb->buf = (void *)addr; + xb->ep = ep; + list_add_tail(&xb->entry, &ep->buffers); + } + return ep; +} + +static void cleanup_dev(struct kref *kref) +{ + struct xillyusb_dev *xdev = + container_of(kref, struct xillyusb_dev, kref); + + if (xdev->in_ep) + endpoint_dealloc(xdev->in_ep); + + if (xdev->msg_ep) + endpoint_dealloc(xdev->msg_ep); + + if (xdev->workq) + destroy_workqueue(xdev->workq); + + kfree(xdev->channels); /* Argument may be NULL, and that's fine */ + kfree(xdev); +} + +/* + * @process_in_mutex is taken to ensure that bulk_in_work() won't call + * process_bulk_in() after wakeup_all()'s execution: The latter zeroes all + * @read_data_ok entries, which will make process_bulk_in() report false + * errors if executed. The mechanism relies on that xdev->error is assigned + * a non-zero value by report_io_error() prior to queueing wakeup_all(), + * which prevents bulk_in_work() from calling process_bulk_in(). + * + * The fact that wakeup_all() and bulk_in_work() are queued on the same + * workqueue makes their concurrent execution very unlikely, however the + * kernel's API doesn't seem to ensure this strictly. + */ + +static void wakeup_all(struct work_struct *work) +{ + int i; + struct xillyusb_dev *xdev = container_of(work, struct xillyusb_dev, + wakeup_workitem); + + mutex_lock(&xdev->process_in_mutex); + + for (i = 0; i < xdev->num_channels; i++) { + struct xillyusb_channel *chan = &xdev->channels[i]; + + mutex_lock(&chan->lock); + + if (chan->in_fifo) { + /* + * Fake an EOF: Even if such arrives, it won't be + * processed. + */ + chan->read_data_ok = 0; + wake_up_interruptible(&chan->in_fifo->waitq); + } + + if (chan->out_ep) + wake_up_interruptible(&chan->out_ep->fifo.waitq); + + mutex_unlock(&chan->lock); + + wake_up_interruptible(&chan->flushq); + } + + mutex_unlock(&xdev->process_in_mutex); + + wake_up_interruptible(&xdev->msg_ep->fifo.waitq); + + kref_put(&xdev->kref, cleanup_dev); +} + +static void report_io_error(struct xillyusb_dev *xdev, + int errcode) +{ + unsigned long flags; + bool do_once = false; + + spin_lock_irqsave(&xdev->error_lock, flags); + if (!xdev->error) { + xdev->error = errcode; + do_once = true; + } + spin_unlock_irqrestore(&xdev->error_lock, flags); + + if (do_once) { + kref_get(&xdev->kref); /* xdev is used by work item */ + queue_work(xdev->workq, &xdev->wakeup_workitem); + } +} + +/* + * safely_assign_in_fifo() changes the value of chan->in_fifo and ensures + * the previous pointer is never used after its return. + */ + +static void safely_assign_in_fifo(struct xillyusb_channel *chan, + struct xillyfifo *fifo) +{ + mutex_lock(&chan->lock); + chan->in_fifo = fifo; + mutex_unlock(&chan->lock); + + flush_work(&chan->xdev->in_ep->workitem); +} + +static void bulk_in_completer(struct urb *urb) +{ + struct xillybuffer *xb = urb->context; + struct xillyusb_endpoint *ep = xb->ep; + unsigned long flags; + + if (urb->status) { + if (!(urb->status == -ENOENT || + urb->status == -ECONNRESET || + urb->status == -ESHUTDOWN)) + report_io_error(ep->xdev, -EIO); + + spin_lock_irqsave(&ep->buffers_lock, flags); + list_add_tail(&xb->entry, &ep->buffers); + ep->outstanding_urbs--; + spin_unlock_irqrestore(&ep->buffers_lock, flags); + + return; + } + + xb->len = urb->actual_length; + + spin_lock_irqsave(&ep->buffers_lock, flags); + list_add_tail(&xb->entry, &ep->filled_buffers); + spin_unlock_irqrestore(&ep->buffers_lock, flags); + + if (!ep->shutting_down) + queue_work(ep->xdev->workq, &ep->workitem); +} + +static void bulk_out_completer(struct urb *urb) +{ + struct xillybuffer *xb = urb->context; + struct xillyusb_endpoint *ep = xb->ep; + unsigned long flags; + + if (urb->status && + (!(urb->status == -ENOENT || + urb->status == -ECONNRESET || + urb->status == -ESHUTDOWN))) + report_io_error(ep->xdev, -EIO); + + spin_lock_irqsave(&ep->buffers_lock, flags); + list_add_tail(&xb->entry, &ep->buffers); + ep->outstanding_urbs--; + spin_unlock_irqrestore(&ep->buffers_lock, flags); + + if (!ep->shutting_down) + queue_work(ep->xdev->workq, &ep->workitem); +} + +static void try_queue_bulk_in(struct xillyusb_endpoint *ep) +{ + struct xillyusb_dev *xdev = ep->xdev; + struct xillybuffer *xb; + struct urb *urb; + + int rc; + unsigned long flags; + unsigned int bufsize = ep->buffer_size; + + mutex_lock(&ep->ep_mutex); + + if (ep->shutting_down || xdev->error) + goto done; + + while (1) { + spin_lock_irqsave(&ep->buffers_lock, flags); + + if (list_empty(&ep->buffers)) { + spin_unlock_irqrestore(&ep->buffers_lock, flags); + goto done; + } + + xb = list_first_entry(&ep->buffers, struct xillybuffer, entry); + list_del(&xb->entry); + ep->outstanding_urbs++; + + spin_unlock_irqrestore(&ep->buffers_lock, flags); + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + report_io_error(xdev, -ENOMEM); + goto relist; + } + + usb_fill_bulk_urb(urb, xdev->udev, + usb_rcvbulkpipe(xdev->udev, ep->ep_num), + xb->buf, bufsize, bulk_in_completer, xb); + + usb_anchor_urb(urb, &ep->anchor); + + rc = usb_submit_urb(urb, GFP_KERNEL); + + if (rc) { + report_io_error(xdev, (rc == -ENOMEM) ? -ENOMEM : + -EIO); + goto unanchor; + } + + usb_free_urb(urb); /* This just decrements reference count */ + } + +unanchor: + usb_unanchor_urb(urb); + usb_free_urb(urb); + +relist: + spin_lock_irqsave(&ep->buffers_lock, flags); + list_add_tail(&xb->entry, &ep->buffers); + ep->outstanding_urbs--; + spin_unlock_irqrestore(&ep->buffers_lock, flags); + +done: + mutex_unlock(&ep->ep_mutex); +} + +static void try_queue_bulk_out(struct xillyusb_endpoint *ep) +{ + struct xillyfifo *fifo = &ep->fifo; + struct xillyusb_dev *xdev = ep->xdev; + struct xillybuffer *xb; + struct urb *urb; + + int rc; + unsigned int fill; + unsigned long flags; + bool do_wake = false; + + mutex_lock(&ep->ep_mutex); + + if (ep->shutting_down || xdev->error) + goto done; + + fill = READ_ONCE(fifo->fill) & ep->fill_mask; + + while (1) { + int count; + unsigned int max_read; + + spin_lock_irqsave(&ep->buffers_lock, flags); + + /* + * Race conditions might have the FIFO filled while the + * endpoint is marked as drained here. That doesn't matter, + * because the sole purpose of @drained is to ensure that + * certain data has been sent on the USB channel before + * shutting it down. Hence knowing that the FIFO appears + * to be empty with no outstanding URBs at some moment + * is good enough. + */ + + if (!fill) { + ep->drained = !ep->outstanding_urbs; + if (ep->drained && ep->wake_on_drain) + do_wake = true; + + spin_unlock_irqrestore(&ep->buffers_lock, flags); + goto done; + } + + ep->drained = false; + + if ((fill < ep->buffer_size && ep->outstanding_urbs) || + list_empty(&ep->buffers)) { + spin_unlock_irqrestore(&ep->buffers_lock, flags); + goto done; + } + + xb = list_first_entry(&ep->buffers, struct xillybuffer, entry); + list_del(&xb->entry); + ep->outstanding_urbs++; + + spin_unlock_irqrestore(&ep->buffers_lock, flags); + + max_read = min(fill, ep->buffer_size); + + count = fifo_read(&ep->fifo, xb->buf, max_read, xilly_memcpy); + + /* + * xilly_memcpy always returns 0 => fifo_read can't fail => + * count > 0 + */ + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + report_io_error(xdev, -ENOMEM); + goto relist; + } + + usb_fill_bulk_urb(urb, xdev->udev, + usb_sndbulkpipe(xdev->udev, ep->ep_num), + xb->buf, count, bulk_out_completer, xb); + + usb_anchor_urb(urb, &ep->anchor); + + rc = usb_submit_urb(urb, GFP_KERNEL); + + if (rc) { + report_io_error(xdev, (rc == -ENOMEM) ? -ENOMEM : + -EIO); + goto unanchor; + } + + usb_free_urb(urb); /* This just decrements reference count */ + + fill -= count; + do_wake = true; + } + +unanchor: + usb_unanchor_urb(urb); + usb_free_urb(urb); + +relist: + spin_lock_irqsave(&ep->buffers_lock, flags); + list_add_tail(&xb->entry, &ep->buffers); + ep->outstanding_urbs--; + spin_unlock_irqrestore(&ep->buffers_lock, flags); + +done: + mutex_unlock(&ep->ep_mutex); + + if (do_wake) + wake_up_interruptible(&fifo->waitq); +} + +static void bulk_out_work(struct work_struct *work) +{ + struct xillyusb_endpoint *ep = container_of(work, + struct xillyusb_endpoint, + workitem); + try_queue_bulk_out(ep); +} + +static int process_in_opcode(struct xillyusb_dev *xdev, + int opcode, + int chan_num) +{ + struct xillyusb_channel *chan; + struct device *dev = xdev->dev; + int chan_idx = chan_num >> 1; + + if (chan_idx >= xdev->num_channels) { + dev_err(dev, "Received illegal channel ID %d from FPGA\n", + chan_num); + return -EIO; + } + + chan = &xdev->channels[chan_idx]; + + switch (opcode) { + case OPCODE_EOF: + if (!chan->read_data_ok) { + dev_err(dev, "Received unexpected EOF for channel %d\n", + chan_num); + return -EIO; + } + + /* + * A write memory barrier ensures that the FIFO's fill level + * is visible before read_data_ok turns zero, so the data in + * the FIFO isn't missed by the consumer. + */ + smp_wmb(); + WRITE_ONCE(chan->read_data_ok, 0); + wake_up_interruptible(&chan->in_fifo->waitq); + break; + + case OPCODE_REACHED_CHECKPOINT: + chan->flushing = 0; + wake_up_interruptible(&chan->flushq); + break; + + case OPCODE_CANCELED_CHECKPOINT: + chan->canceled = 1; + wake_up_interruptible(&chan->flushq); + break; + + default: + dev_err(dev, "Received illegal opcode %d from FPGA\n", + opcode); + return -EIO; + } + + return 0; +} + +static int process_bulk_in(struct xillybuffer *xb) +{ + struct xillyusb_endpoint *ep = xb->ep; + struct xillyusb_dev *xdev = ep->xdev; + struct device *dev = xdev->dev; + int dws = xb->len >> 2; + __le32 *p = xb->buf; + u32 ctrlword; + struct xillyusb_channel *chan; + struct xillyfifo *fifo; + int chan_num = 0, opcode; + int chan_idx; + int bytes, count, dwconsume; + int in_bytes_left = 0; + int rc; + + if ((dws << 2) != xb->len) { + dev_err(dev, "Received BULK IN transfer with %d bytes, not a multiple of 4\n", + xb->len); + return -EIO; + } + + if (xdev->in_bytes_left) { + bytes = min(xdev->in_bytes_left, dws << 2); + in_bytes_left = xdev->in_bytes_left - bytes; + chan_num = xdev->leftover_chan_num; + goto resume_leftovers; + } + + while (dws) { + ctrlword = le32_to_cpu(*p++); + dws--; + + chan_num = ctrlword & 0xfff; + count = (ctrlword >> 12) & 0x3ff; + opcode = (ctrlword >> 24) & 0xf; + + if (opcode != OPCODE_DATA) { + unsigned int in_counter = xdev->in_counter++ & 0x3ff; + + if (count != in_counter) { + dev_err(dev, "Expected opcode counter %d, got %d\n", + in_counter, count); + return -EIO; + } + + rc = process_in_opcode(xdev, opcode, chan_num); + + if (rc) + return rc; + + continue; + } + + bytes = min(count + 1, dws << 2); + in_bytes_left = count + 1 - bytes; + +resume_leftovers: + chan_idx = chan_num >> 1; + + if (!(chan_num & 1) || chan_idx >= xdev->num_channels || + !xdev->channels[chan_idx].read_data_ok) { + dev_err(dev, "Received illegal channel ID %d from FPGA\n", + chan_num); + return -EIO; + } + chan = &xdev->channels[chan_idx]; + + fifo = chan->in_fifo; + + if (unlikely(!fifo)) + return -EIO; /* We got really unexpected data */ + + if (bytes != fifo_write(fifo, p, bytes, xilly_memcpy)) { + dev_err(dev, "Misbehaving FPGA overflowed an upstream FIFO!\n"); + return -EIO; + } + + wake_up_interruptible(&fifo->waitq); + + dwconsume = (bytes + 3) >> 2; + dws -= dwconsume; + p += dwconsume; + } + + xdev->in_bytes_left = in_bytes_left; + xdev->leftover_chan_num = chan_num; + return 0; +} + +static void bulk_in_work(struct work_struct *work) +{ + struct xillyusb_endpoint *ep = + container_of(work, struct xillyusb_endpoint, workitem); + struct xillyusb_dev *xdev = ep->xdev; + unsigned long flags; + struct xillybuffer *xb; + bool consumed = false; + int rc = 0; + + mutex_lock(&xdev->process_in_mutex); + + spin_lock_irqsave(&ep->buffers_lock, flags); + + while (1) { + if (rc || list_empty(&ep->filled_buffers)) { + spin_unlock_irqrestore(&ep->buffers_lock, flags); + mutex_unlock(&xdev->process_in_mutex); + + if (rc) + report_io_error(xdev, rc); + else if (consumed) + try_queue_bulk_in(ep); + + return; + } + + xb = list_first_entry(&ep->filled_buffers, struct xillybuffer, + entry); + list_del(&xb->entry); + + spin_unlock_irqrestore(&ep->buffers_lock, flags); + + consumed = true; + + if (!xdev->error) + rc = process_bulk_in(xb); + + spin_lock_irqsave(&ep->buffers_lock, flags); + list_add_tail(&xb->entry, &ep->buffers); + ep->outstanding_urbs--; + } +} + +static int xillyusb_send_opcode(struct xillyusb_dev *xdev, + int chan_num, char opcode, u32 data) +{ + struct xillyusb_endpoint *ep = xdev->msg_ep; + struct xillyfifo *fifo = &ep->fifo; + __le32 msg[2]; + + int rc = 0; + + msg[0] = cpu_to_le32((chan_num & 0xfff) | + ((opcode & 0xf) << 24)); + msg[1] = cpu_to_le32(data); + + mutex_lock(&xdev->msg_mutex); + + /* + * The wait queue is woken with the interruptible variant, so the + * wait function matches, however returning because of an interrupt + * will mess things up considerably, in particular when the caller is + * the release method. And the xdev->error part prevents being stuck + * forever in the event of a bizarre hardware bug: Pull the USB plug. + */ + + while (wait_event_interruptible(fifo->waitq, + fifo->fill <= (fifo->size - 8) || + xdev->error)) + ; /* Empty loop */ + + if (xdev->error) { + rc = xdev->error; + goto unlock_done; + } + + fifo_write(fifo, (void *)msg, 8, xilly_memcpy); + + try_queue_bulk_out(ep); + +unlock_done: + mutex_unlock(&xdev->msg_mutex); + + return rc; +} + +/* + * Note that flush_downstream() merely waits for the data to arrive to + * the application logic at the FPGA -- unlike PCIe Xillybus' counterpart, + * it does nothing to make it happen (and neither is it necessary). + * + * This function is not reentrant for the same @chan, but this is covered + * by the fact that for any given @chan, it's called either by the open, + * write, llseek and flush fops methods, which can't run in parallel (and the + * write + flush and llseek method handlers are protected with out_mutex). + * + * chan->flushed is there to avoid multiple flushes at the same position, + * in particular as a result of programs that close the file descriptor + * e.g. after a dup2() for redirection. + */ + +static int flush_downstream(struct xillyusb_channel *chan, + long timeout, + bool interruptible) +{ + struct xillyusb_dev *xdev = chan->xdev; + int chan_num = chan->chan_idx << 1; + long deadline, left_to_sleep; + int rc; + + if (chan->flushed) + return 0; + + deadline = jiffies + 1 + timeout; + + if (chan->flushing) { + long cancel_deadline = jiffies + 1 + XILLY_RESPONSE_TIMEOUT; + + chan->canceled = 0; + rc = xillyusb_send_opcode(xdev, chan_num, + OPCODE_CANCEL_CHECKPOINT, 0); + + if (rc) + return rc; /* Only real error, never -EINTR */ + + /* Ignoring interrupts. Cancellation must be handled */ + while (!chan->canceled) { + left_to_sleep = cancel_deadline - ((long)jiffies); + + if (left_to_sleep <= 0) { + report_io_error(xdev, -EIO); + return -EIO; + } + + rc = wait_event_interruptible_timeout(chan->flushq, + chan->canceled || + xdev->error, + left_to_sleep); + + if (xdev->error) + return xdev->error; + } + } + + chan->flushing = 1; + + /* + * The checkpoint is given in terms of data elements, not bytes. As + * a result, if less than an element's worth of data is stored in the + * FIFO, it's not flushed, including the flush before closing, which + * means that such data is lost. This is consistent with PCIe Xillybus. + */ + + rc = xillyusb_send_opcode(xdev, chan_num, + OPCODE_SET_CHECKPOINT, + chan->out_bytes >> + chan->out_log2_element_size); + + if (rc) + return rc; /* Only real error, never -EINTR */ + + if (!timeout) { + while (chan->flushing) { + rc = wait_event_interruptible(chan->flushq, + !chan->flushing || + xdev->error); + if (xdev->error) + return xdev->error; + + if (interruptible && rc) + return -EINTR; + } + + goto done; + } + + while (chan->flushing) { + left_to_sleep = deadline - ((long)jiffies); + + if (left_to_sleep <= 0) + return -ETIMEDOUT; + + rc = wait_event_interruptible_timeout(chan->flushq, + !chan->flushing || + xdev->error, + left_to_sleep); + + if (xdev->error) + return xdev->error; + + if (interruptible && rc < 0) + return -EINTR; + } + +done: + chan->flushed = 1; + return 0; +} + +/* request_read_anything(): Ask the FPGA for any little amount of data */ +static int request_read_anything(struct xillyusb_channel *chan, + char opcode) +{ + struct xillyusb_dev *xdev = chan->xdev; + unsigned int sh = chan->in_log2_element_size; + int chan_num = (chan->chan_idx << 1) | 1; + u32 mercy = chan->in_consumed_bytes + (2 << sh) - 1; + + return xillyusb_send_opcode(xdev, chan_num, opcode, mercy >> sh); +} + +static int xillyusb_open(struct inode *inode, struct file *filp) +{ + struct xillyusb_dev *xdev; + struct xillyusb_channel *chan; + struct xillyfifo *in_fifo = NULL; + struct xillyusb_endpoint *out_ep = NULL; + int rc; + int index; + + rc = xillybus_find_inode(inode, (void **)&xdev, &index); + if (rc) + return rc; + + chan = &xdev->channels[index]; + filp->private_data = chan; + + mutex_lock(&chan->lock); + + rc = -ENODEV; + + if (xdev->error) + goto unmutex_fail; + + if (((filp->f_mode & FMODE_READ) && !chan->readable) || + ((filp->f_mode & FMODE_WRITE) && !chan->writable)) + goto unmutex_fail; + + if ((filp->f_flags & O_NONBLOCK) && (filp->f_mode & FMODE_READ) && + chan->in_synchronous) { + dev_err(xdev->dev, + "open() failed: O_NONBLOCK not allowed for read on this device\n"); + goto unmutex_fail; + } + + if ((filp->f_flags & O_NONBLOCK) && (filp->f_mode & FMODE_WRITE) && + chan->out_synchronous) { + dev_err(xdev->dev, + "open() failed: O_NONBLOCK not allowed for write on this device\n"); + goto unmutex_fail; + } + + rc = -EBUSY; + + if (((filp->f_mode & FMODE_READ) && chan->open_for_read) || + ((filp->f_mode & FMODE_WRITE) && chan->open_for_write)) + goto unmutex_fail; + + kref_get(&xdev->kref); + + if (filp->f_mode & FMODE_READ) + chan->open_for_read = 1; + + if (filp->f_mode & FMODE_WRITE) + chan->open_for_write = 1; + + mutex_unlock(&chan->lock); + + if (filp->f_mode & FMODE_WRITE) { + out_ep = endpoint_alloc(xdev, + (chan->chan_idx + 2) | USB_DIR_OUT, + bulk_out_work, BUF_SIZE_ORDER, BUFNUM); + + if (!out_ep) { + rc = -ENOMEM; + goto unopen; + } + + rc = fifo_init(&out_ep->fifo, chan->out_log2_fifo_size); + + if (rc) + goto late_unopen; + + out_ep->fill_mask = -(1 << chan->out_log2_element_size); + chan->out_bytes = 0; + chan->flushed = 0; + + /* + * Sending a flush request to a previously closed stream + * effectively opens it, and also waits until the command is + * confirmed by the FPGA. The latter is necessary because the + * data is sent through a separate BULK OUT endpoint, and the + * xHCI controller is free to reorder transmissions. + * + * This can't go wrong unless there's a serious hardware error + * (or the computer is stuck for 500 ms?) + */ + rc = flush_downstream(chan, XILLY_RESPONSE_TIMEOUT, false); + + if (rc == -ETIMEDOUT) { + rc = -EIO; + report_io_error(xdev, rc); + } + + if (rc) + goto late_unopen; + } + + if (filp->f_mode & FMODE_READ) { + in_fifo = kzalloc(sizeof(*in_fifo), GFP_KERNEL); + + if (!in_fifo) { + rc = -ENOMEM; + goto late_unopen; + } + + rc = fifo_init(in_fifo, chan->in_log2_fifo_size); + + if (rc) { + kfree(in_fifo); + goto late_unopen; + } + } + + mutex_lock(&chan->lock); + if (in_fifo) { + chan->in_fifo = in_fifo; + chan->read_data_ok = 1; + } + if (out_ep) + chan->out_ep = out_ep; + mutex_unlock(&chan->lock); + + if (in_fifo) { + u32 in_checkpoint = 0; + + if (!chan->in_synchronous) + in_checkpoint = in_fifo->size >> + chan->in_log2_element_size; + + chan->in_consumed_bytes = 0; + chan->poll_used = 0; + chan->in_current_checkpoint = in_checkpoint; + rc = xillyusb_send_opcode(xdev, (chan->chan_idx << 1) | 1, + OPCODE_SET_CHECKPOINT, + in_checkpoint); + + if (rc) /* Failure guarantees that opcode wasn't sent */ + goto unfifo; + + /* + * In non-blocking mode, request the FPGA to send any data it + * has right away. Otherwise, the first read() will always + * return -EAGAIN, which is OK strictly speaking, but ugly. + * Checking and unrolling if this fails isn't worth the + * effort -- the error is propagated to the first read() + * anyhow. + */ + if (filp->f_flags & O_NONBLOCK) + request_read_anything(chan, OPCODE_SET_PUSH); + } + + return 0; + +unfifo: + chan->read_data_ok = 0; + safely_assign_in_fifo(chan, NULL); + fifo_mem_release(in_fifo); + kfree(in_fifo); + + if (out_ep) { + mutex_lock(&chan->lock); + chan->out_ep = NULL; + mutex_unlock(&chan->lock); + } + +late_unopen: + if (out_ep) + endpoint_dealloc(out_ep); + +unopen: + mutex_lock(&chan->lock); + + if (filp->f_mode & FMODE_READ) + chan->open_for_read = 0; + + if (filp->f_mode & FMODE_WRITE) + chan->open_for_write = 0; + + mutex_unlock(&chan->lock); + + kref_put(&xdev->kref, cleanup_dev); + + return rc; + +unmutex_fail: + mutex_unlock(&chan->lock); + return rc; +} + +static ssize_t xillyusb_read(struct file *filp, char __user *userbuf, + size_t count, loff_t *f_pos) +{ + struct xillyusb_channel *chan = filp->private_data; + struct xillyusb_dev *xdev = chan->xdev; + struct xillyfifo *fifo = chan->in_fifo; + int chan_num = (chan->chan_idx << 1) | 1; + + long deadline, left_to_sleep; + int bytes_done = 0; + bool sent_set_push = false; + int rc; + + deadline = jiffies + 1 + XILLY_RX_TIMEOUT; + + rc = mutex_lock_interruptible(&chan->in_mutex); + + if (rc) + return rc; + + while (1) { + u32 fifo_checkpoint_bytes, complete_checkpoint_bytes; + u32 complete_checkpoint, fifo_checkpoint; + u32 checkpoint; + s32 diff, leap; + unsigned int sh = chan->in_log2_element_size; + bool checkpoint_for_complete; + + rc = fifo_read(fifo, (__force void *)userbuf + bytes_done, + count - bytes_done, xilly_copy_to_user); + + if (rc < 0) + break; + + bytes_done += rc; + chan->in_consumed_bytes += rc; + + left_to_sleep = deadline - ((long)jiffies); + + /* + * Some 32-bit arithmetic that may wrap. Note that + * complete_checkpoint is rounded up to the closest element + * boundary, because the read() can't be completed otherwise. + * fifo_checkpoint_bytes is rounded down, because it protects + * in_fifo from overflowing. + */ + + fifo_checkpoint_bytes = chan->in_consumed_bytes + fifo->size; + complete_checkpoint_bytes = + chan->in_consumed_bytes + count - bytes_done; + + fifo_checkpoint = fifo_checkpoint_bytes >> sh; + complete_checkpoint = + (complete_checkpoint_bytes + (1 << sh) - 1) >> sh; + + diff = (fifo_checkpoint - complete_checkpoint) << sh; + + if (chan->in_synchronous && diff >= 0) { + checkpoint = complete_checkpoint; + checkpoint_for_complete = true; + } else { + checkpoint = fifo_checkpoint; + checkpoint_for_complete = false; + } + + leap = (checkpoint - chan->in_current_checkpoint) << sh; + + /* + * To prevent flooding of OPCODE_SET_CHECKPOINT commands as + * data is consumed, it's issued only if it moves the + * checkpoint by at least an 8th of the FIFO's size, or if + * it's necessary to complete the number of bytes requested by + * the read() call. + * + * chan->read_data_ok is checked to spare an unnecessary + * submission after receiving EOF, however it's harmless if + * such slips away. + */ + + if (chan->read_data_ok && + (leap > (fifo->size >> 3) || + (checkpoint_for_complete && leap > 0))) { + chan->in_current_checkpoint = checkpoint; + rc = xillyusb_send_opcode(xdev, chan_num, + OPCODE_SET_CHECKPOINT, + checkpoint); + + if (rc) + break; + } + + if (bytes_done == count || + (left_to_sleep <= 0 && bytes_done)) + break; + + /* + * Reaching here means that the FIFO was empty when + * fifo_read() returned, but not necessarily right now. Error + * and EOF are checked and reported only now, so that no data + * that managed its way to the FIFO is lost. + */ + + if (!READ_ONCE(chan->read_data_ok)) { /* FPGA has sent EOF */ + /* Has data slipped into the FIFO since fifo_read()? */ + smp_rmb(); + if (READ_ONCE(fifo->fill)) + continue; + + rc = 0; + break; + } + + if (xdev->error) { + rc = xdev->error; + break; + } + + if (filp->f_flags & O_NONBLOCK) { + rc = -EAGAIN; + break; + } + + if (!sent_set_push) { + rc = xillyusb_send_opcode(xdev, chan_num, + OPCODE_SET_PUSH, + complete_checkpoint); + + if (rc) + break; + + sent_set_push = true; + } + + if (left_to_sleep > 0) { + /* + * Note that when xdev->error is set (e.g. when the + * device is unplugged), read_data_ok turns zero and + * fifo->waitq is awaken. + * Therefore no special attention to xdev->error. + */ + + rc = wait_event_interruptible_timeout + (fifo->waitq, + fifo->fill || !chan->read_data_ok, + left_to_sleep); + } else { /* bytes_done == 0 */ + /* Tell FPGA to send anything it has */ + rc = request_read_anything(chan, OPCODE_UPDATE_PUSH); + + if (rc) + break; + + rc = wait_event_interruptible + (fifo->waitq, + fifo->fill || !chan->read_data_ok); + } + + if (rc < 0) { + rc = -EINTR; + break; + } + } + + if (((filp->f_flags & O_NONBLOCK) || chan->poll_used) && + !READ_ONCE(fifo->fill)) + request_read_anything(chan, OPCODE_SET_PUSH); + + mutex_unlock(&chan->in_mutex); + + if (bytes_done) + return bytes_done; + + return rc; +} + +static int xillyusb_flush(struct file *filp, fl_owner_t id) +{ + struct xillyusb_channel *chan = filp->private_data; + int rc; + + if (!(filp->f_mode & FMODE_WRITE)) + return 0; + + rc = mutex_lock_interruptible(&chan->out_mutex); + + if (rc) + return rc; + + /* + * One second's timeout on flushing. Interrupts are ignored, because if + * the user pressed CTRL-C, that interrupt will still be in flight by + * the time we reach here, and the opportunity to flush is lost. + */ + rc = flush_downstream(chan, HZ, false); + + mutex_unlock(&chan->out_mutex); + + if (rc == -ETIMEDOUT) { + /* The things you do to use dev_warn() and not pr_warn() */ + struct xillyusb_dev *xdev = chan->xdev; + + mutex_lock(&chan->lock); + if (!xdev->error) + dev_warn(xdev->dev, + "Timed out while flushing. Output data may be lost.\n"); + mutex_unlock(&chan->lock); + } + + return rc; +} + +static ssize_t xillyusb_write(struct file *filp, const char __user *userbuf, + size_t count, loff_t *f_pos) +{ + struct xillyusb_channel *chan = filp->private_data; + struct xillyusb_dev *xdev = chan->xdev; + struct xillyfifo *fifo = &chan->out_ep->fifo; + int rc; + + rc = mutex_lock_interruptible(&chan->out_mutex); + + if (rc) + return rc; + + while (1) { + if (xdev->error) { + rc = xdev->error; + break; + } + + if (count == 0) + break; + + rc = fifo_write(fifo, (__force void *)userbuf, count, + xilly_copy_from_user); + + if (rc != 0) + break; + + if (filp->f_flags & O_NONBLOCK) { + rc = -EAGAIN; + break; + } + + if (wait_event_interruptible + (fifo->waitq, + fifo->fill != fifo->size || xdev->error)) { + rc = -EINTR; + break; + } + } + + if (rc < 0) + goto done; + + chan->out_bytes += rc; + + if (rc) { + try_queue_bulk_out(chan->out_ep); + chan->flushed = 0; + } + + if (chan->out_synchronous) { + int flush_rc = flush_downstream(chan, 0, true); + + if (flush_rc && !rc) + rc = flush_rc; + } + +done: + mutex_unlock(&chan->out_mutex); + + return rc; +} + +static int xillyusb_release(struct inode *inode, struct file *filp) +{ + struct xillyusb_channel *chan = filp->private_data; + struct xillyusb_dev *xdev = chan->xdev; + int rc_read = 0, rc_write = 0; + + if (filp->f_mode & FMODE_READ) { + struct xillyfifo *in_fifo = chan->in_fifo; + + rc_read = xillyusb_send_opcode(xdev, (chan->chan_idx << 1) | 1, + OPCODE_CLOSE, 0); + /* + * If rc_read is nonzero, xdev->error indicates a global + * device error. The error is reported later, so that + * resources are freed. + * + * Looping on wait_event_interruptible() kinda breaks the idea + * of being interruptible, and this should have been + * wait_event(). Only it's being waken with + * wake_up_interruptible() for the sake of other uses. If + * there's a global device error, chan->read_data_ok is + * deasserted and the wait queue is awaken, so this is covered. + */ + + while (wait_event_interruptible(in_fifo->waitq, + !chan->read_data_ok)) + ; /* Empty loop */ + + safely_assign_in_fifo(chan, NULL); + fifo_mem_release(in_fifo); + kfree(in_fifo); + + mutex_lock(&chan->lock); + chan->open_for_read = 0; + mutex_unlock(&chan->lock); + } + + if (filp->f_mode & FMODE_WRITE) { + struct xillyusb_endpoint *ep = chan->out_ep; + /* + * chan->flushing isn't zeroed. If the pre-release flush timed + * out, a cancel request will be sent before the next + * OPCODE_SET_CHECKPOINT (i.e. when the file is opened again). + * This is despite that the FPGA forgets about the checkpoint + * request as the file closes. Still, in an exceptional race + * condition, the FPGA could send an OPCODE_REACHED_CHECKPOINT + * just before closing that would reach the host after the + * file has re-opened. + */ + + mutex_lock(&chan->lock); + chan->out_ep = NULL; + mutex_unlock(&chan->lock); + + endpoint_quiesce(ep); + endpoint_dealloc(ep); + + /* See comments on rc_read above */ + rc_write = xillyusb_send_opcode(xdev, chan->chan_idx << 1, + OPCODE_CLOSE, 0); + + mutex_lock(&chan->lock); + chan->open_for_write = 0; + mutex_unlock(&chan->lock); + } + + kref_put(&xdev->kref, cleanup_dev); + + return rc_read ? rc_read : rc_write; +} + +/* + * Xillybus' API allows device nodes to be seekable, giving the user + * application access to a RAM array on the FPGA (or logic emulating it). + */ + +static loff_t xillyusb_llseek(struct file *filp, loff_t offset, int whence) +{ + struct xillyusb_channel *chan = filp->private_data; + struct xillyusb_dev *xdev = chan->xdev; + loff_t pos = filp->f_pos; + int rc = 0; + unsigned int log2_element_size = chan->readable ? + chan->in_log2_element_size : chan->out_log2_element_size; + + /* + * Take both mutexes not allowing interrupts, since it seems like + * common applications don't expect an -EINTR here. Besides, multiple + * access to a single file descriptor on seekable devices is a mess + * anyhow. + */ + + mutex_lock(&chan->out_mutex); + mutex_lock(&chan->in_mutex); + + switch (whence) { + case SEEK_SET: + pos = offset; + break; + case SEEK_CUR: + pos += offset; + break; + case SEEK_END: + pos = offset; /* Going to the end => to the beginning */ + break; + default: + rc = -EINVAL; + goto end; + } + + /* In any case, we must finish on an element boundary */ + if (pos & ((1 << log2_element_size) - 1)) { + rc = -EINVAL; + goto end; + } + + rc = xillyusb_send_opcode(xdev, chan->chan_idx << 1, + OPCODE_SET_ADDR, + pos >> log2_element_size); + + if (rc) + goto end; + + if (chan->writable) { + chan->flushed = 0; + rc = flush_downstream(chan, HZ, false); + } + +end: + mutex_unlock(&chan->out_mutex); + mutex_unlock(&chan->in_mutex); + + if (rc) /* Return error after releasing mutexes */ + return rc; + + filp->f_pos = pos; + + return pos; +} + +static __poll_t xillyusb_poll(struct file *filp, poll_table *wait) +{ + struct xillyusb_channel *chan = filp->private_data; + __poll_t mask = 0; + + if (chan->in_fifo) + poll_wait(filp, &chan->in_fifo->waitq, wait); + + if (chan->out_ep) + poll_wait(filp, &chan->out_ep->fifo.waitq, wait); + + /* + * If this is the first time poll() is called, and the file is + * readable, set the relevant flag. Also tell the FPGA to send all it + * has, to kickstart the mechanism that ensures there's always some + * data in in_fifo unless the stream is dry end-to-end. Note that the + * first poll() may not return a EPOLLIN, even if there's data on the + * FPGA. Rather, the data will arrive soon, and trigger the relevant + * wait queue. + */ + + if (!chan->poll_used && chan->in_fifo) { + chan->poll_used = 1; + request_read_anything(chan, OPCODE_SET_PUSH); + } + + /* + * poll() won't play ball regarding read() channels which + * are synchronous. Allowing that will create situations where data has + * been delivered at the FPGA, and users expecting select() to wake up, + * which it may not. So make it never work. + */ + + if (chan->in_fifo && !chan->in_synchronous && + (READ_ONCE(chan->in_fifo->fill) || !chan->read_data_ok)) + mask |= EPOLLIN | EPOLLRDNORM; + + if (chan->out_ep && + (READ_ONCE(chan->out_ep->fifo.fill) != chan->out_ep->fifo.size)) + mask |= EPOLLOUT | EPOLLWRNORM; + + if (chan->xdev->error) + mask |= EPOLLERR; + + return mask; +} + +static const struct file_operations xillyusb_fops = { + .owner = THIS_MODULE, + .read = xillyusb_read, + .write = xillyusb_write, + .open = xillyusb_open, + .flush = xillyusb_flush, + .release = xillyusb_release, + .llseek = xillyusb_llseek, + .poll = xillyusb_poll, +}; + +static int xillyusb_setup_base_eps(struct xillyusb_dev *xdev) +{ + xdev->msg_ep = endpoint_alloc(xdev, MSG_EP_NUM | USB_DIR_OUT, + bulk_out_work, 1, 2); + if (!xdev->msg_ep) + return -ENOMEM; + + if (fifo_init(&xdev->msg_ep->fifo, 13)) /* 8 kiB */ + goto dealloc; + + xdev->msg_ep->fill_mask = -8; /* 8 bytes granularity */ + + xdev->in_ep = endpoint_alloc(xdev, IN_EP_NUM | USB_DIR_IN, + bulk_in_work, BUF_SIZE_ORDER, BUFNUM); + if (!xdev->in_ep) + goto dealloc; + + try_queue_bulk_in(xdev->in_ep); + + return 0; + +dealloc: + endpoint_dealloc(xdev->msg_ep); /* Also frees FIFO mem if allocated */ + return -ENOMEM; +} + +static int setup_channels(struct xillyusb_dev *xdev, + __le16 *chandesc, + int num_channels) +{ + struct xillyusb_channel *chan; + int i; + + chan = kcalloc(num_channels, sizeof(*chan), GFP_KERNEL); + if (!chan) + return -ENOMEM; + + xdev->channels = chan; + + for (i = 0; i < num_channels; i++, chan++) { + unsigned int in_desc = le16_to_cpu(*chandesc++); + unsigned int out_desc = le16_to_cpu(*chandesc++); + + chan->xdev = xdev; + mutex_init(&chan->in_mutex); + mutex_init(&chan->out_mutex); + mutex_init(&chan->lock); + init_waitqueue_head(&chan->flushq); + + chan->chan_idx = i; + + if (in_desc & 0x80) { /* Entry is valid */ + chan->readable = 1; + chan->in_synchronous = !!(in_desc & 0x40); + chan->in_seekable = !!(in_desc & 0x20); + chan->in_log2_element_size = in_desc & 0x0f; + chan->in_log2_fifo_size = ((in_desc >> 8) & 0x1f) + 16; + } + + /* + * A downstream channel should never exist above index 13, + * as it would request a nonexistent BULK endpoint > 15. + * In the peculiar case that it does, it's ignored silently. + */ + + if ((out_desc & 0x80) && i < 14) { /* Entry is valid */ + chan->writable = 1; + chan->out_synchronous = !!(out_desc & 0x40); + chan->out_seekable = !!(out_desc & 0x20); + chan->out_log2_element_size = out_desc & 0x0f; + chan->out_log2_fifo_size = + ((out_desc >> 8) & 0x1f) + 16; + } + } + + return 0; +} + +static int xillyusb_discovery(struct usb_interface *interface) +{ + int rc; + struct xillyusb_dev *xdev = usb_get_intfdata(interface); + __le16 bogus_chandesc[2]; + struct xillyfifo idt_fifo; + struct xillyusb_channel *chan; + unsigned int idt_len, names_offset; + unsigned char *idt; + int num_channels; + + rc = xillyusb_send_opcode(xdev, ~0, OPCODE_QUIESCE, 0); + + if (rc) { + dev_err(&interface->dev, "Failed to send quiesce request. Aborting.\n"); + return rc; + } + + /* Phase I: Set up one fake upstream channel and obtain IDT */ + + /* Set up a fake IDT with one async IN stream */ + bogus_chandesc[0] = cpu_to_le16(0x80); + bogus_chandesc[1] = cpu_to_le16(0); + + rc = setup_channels(xdev, bogus_chandesc, 1); + + if (rc) + return rc; + + rc = fifo_init(&idt_fifo, LOG2_IDT_FIFO_SIZE); + + if (rc) + return rc; + + chan = xdev->channels; + + chan->in_fifo = &idt_fifo; + chan->read_data_ok = 1; + + xdev->num_channels = 1; + + rc = xillyusb_send_opcode(xdev, ~0, OPCODE_REQ_IDT, 0); + + if (rc) { + dev_err(&interface->dev, "Failed to send IDT request. Aborting.\n"); + goto unfifo; + } + + rc = wait_event_interruptible_timeout(idt_fifo.waitq, + !chan->read_data_ok, + XILLY_RESPONSE_TIMEOUT); + + if (xdev->error) { + rc = xdev->error; + goto unfifo; + } + + if (rc < 0) { + rc = -EINTR; /* Interrupt on probe method? Interesting. */ + goto unfifo; + } + + if (chan->read_data_ok) { + rc = -ETIMEDOUT; + dev_err(&interface->dev, "No response from FPGA. Aborting.\n"); + goto unfifo; + } + + idt_len = READ_ONCE(idt_fifo.fill); + idt = kmalloc(idt_len, GFP_KERNEL); + + if (!idt) { + rc = -ENOMEM; + goto unfifo; + } + + fifo_read(&idt_fifo, idt, idt_len, xilly_memcpy); + + if (crc32_le(~0, idt, idt_len) != 0) { + dev_err(&interface->dev, "IDT failed CRC check. Aborting.\n"); + rc = -ENODEV; + goto unidt; + } + + if (*idt > 0x90) { + dev_err(&interface->dev, "No support for IDT version 0x%02x. Maybe the xillyusb driver needs an upgrade. Aborting.\n", + (int)*idt); + rc = -ENODEV; + goto unidt; + } + + /* Phase II: Set up the streams as defined in IDT */ + + num_channels = le16_to_cpu(*((__le16 *)(idt + 1))); + names_offset = 3 + num_channels * 4; + idt_len -= 4; /* Exclude CRC */ + + if (idt_len < names_offset) { + dev_err(&interface->dev, "IDT too short. This is exceptionally weird, because its CRC is OK\n"); + rc = -ENODEV; + goto unidt; + } + + rc = setup_channels(xdev, (void *)idt + 3, num_channels); + + if (rc) + goto unidt; + + /* + * Except for wildly misbehaving hardware, or if it was disconnected + * just after responding with the IDT, there is no reason for any + * work item to be running now. To be sure that xdev->channels + * is updated on anything that might run in parallel, flush the + * workqueue, which rarely does anything. + */ + flush_workqueue(xdev->workq); + + xdev->num_channels = num_channels; + + fifo_mem_release(&idt_fifo); + kfree(chan); + + rc = xillybus_init_chrdev(&interface->dev, &xillyusb_fops, + THIS_MODULE, xdev, + idt + names_offset, + idt_len - names_offset, + num_channels, + xillyname, true); + + kfree(idt); + + return rc; + +unidt: + kfree(idt); + +unfifo: + safely_assign_in_fifo(chan, NULL); + fifo_mem_release(&idt_fifo); + + return rc; +} + +static int xillyusb_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct xillyusb_dev *xdev; + int rc; + + xdev = kzalloc(sizeof(*xdev), GFP_KERNEL); + if (!xdev) + return -ENOMEM; + + kref_init(&xdev->kref); + mutex_init(&xdev->process_in_mutex); + mutex_init(&xdev->msg_mutex); + + xdev->udev = usb_get_dev(interface_to_usbdev(interface)); + xdev->dev = &interface->dev; + xdev->error = 0; + spin_lock_init(&xdev->error_lock); + xdev->in_counter = 0; + xdev->in_bytes_left = 0; + xdev->workq = alloc_workqueue(xillyname, WQ_HIGHPRI, 0); + + if (!xdev->workq) { + dev_err(&interface->dev, "Failed to allocate work queue\n"); + rc = -ENOMEM; + goto fail; + } + + INIT_WORK(&xdev->wakeup_workitem, wakeup_all); + + usb_set_intfdata(interface, xdev); + + rc = xillyusb_setup_base_eps(xdev); + if (rc) + goto fail; + + rc = xillyusb_discovery(interface); + if (rc) + goto latefail; + + return 0; + +latefail: + endpoint_quiesce(xdev->in_ep); + endpoint_quiesce(xdev->msg_ep); + +fail: + usb_set_intfdata(interface, NULL); + kref_put(&xdev->kref, cleanup_dev); + return rc; +} + +static void xillyusb_disconnect(struct usb_interface *interface) +{ + struct xillyusb_dev *xdev = usb_get_intfdata(interface); + struct xillyusb_endpoint *msg_ep = xdev->msg_ep; + struct xillyfifo *fifo = &msg_ep->fifo; + int rc; + int i; + + xillybus_cleanup_chrdev(xdev, &interface->dev); + + /* + * Try to send OPCODE_QUIESCE, which will fail silently if the device + * was disconnected, but makes sense on module unload. + */ + + msg_ep->wake_on_drain = true; + xillyusb_send_opcode(xdev, ~0, OPCODE_QUIESCE, 0); + + /* + * If the device has been disconnected, sending the opcode causes + * a global device error with xdev->error, if such error didn't + * occur earlier. Hence timing out means that the USB link is fine, + * but somehow the message wasn't sent. Should never happen. + */ + + rc = wait_event_interruptible_timeout(fifo->waitq, + msg_ep->drained || xdev->error, + XILLY_RESPONSE_TIMEOUT); + + if (!rc) + dev_err(&interface->dev, + "Weird timeout condition on sending quiesce request.\n"); + + report_io_error(xdev, -ENODEV); /* Discourage further activity */ + + /* + * This device driver is declared with soft_unbind set, or else + * sending OPCODE_QUIESCE above would always fail. The price is + * that the USB framework didn't kill outstanding URBs, so it has + * to be done explicitly before returning from this call. + */ + + for (i = 0; i < xdev->num_channels; i++) { + struct xillyusb_channel *chan = &xdev->channels[i]; + + /* + * Lock taken to prevent chan->out_ep from changing. It also + * ensures xillyusb_open() and xillyusb_flush() don't access + * xdev->dev after being nullified below. + */ + mutex_lock(&chan->lock); + if (chan->out_ep) + endpoint_quiesce(chan->out_ep); + mutex_unlock(&chan->lock); + } + + endpoint_quiesce(xdev->in_ep); + endpoint_quiesce(xdev->msg_ep); + + usb_set_intfdata(interface, NULL); + + xdev->dev = NULL; + + kref_put(&xdev->kref, cleanup_dev); +} + +static struct usb_driver xillyusb_driver = { + .name = xillyname, + .id_table = xillyusb_table, + .probe = xillyusb_probe, + .disconnect = xillyusb_disconnect, + .soft_unbind = 1, +}; + +static int __init xillyusb_init(void) +{ + int rc = 0; + + if (LOG2_INITIAL_FIFO_BUF_SIZE > PAGE_SHIFT) + fifo_buf_order = LOG2_INITIAL_FIFO_BUF_SIZE - PAGE_SHIFT; + else + fifo_buf_order = 0; + + rc = usb_register(&xillyusb_driver); + + return rc; +} + +static void __exit xillyusb_exit(void) +{ + usb_deregister(&xillyusb_driver); +} + +module_init(xillyusb_init); +module_exit(xillyusb_exit); diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 344997203f0e..87ba4966b0e8 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -343,16 +343,63 @@ static int clk_divider_bestdiv(struct clk_hw *hw, struct clk_hw *parent, return bestdiv; } +int divider_determine_rate(struct clk_hw *hw, struct clk_rate_request *req, + const struct clk_div_table *table, u8 width, + unsigned long flags) +{ + int div; + + div = clk_divider_bestdiv(hw, req->best_parent_hw, req->rate, + &req->best_parent_rate, table, width, flags); + + req->rate = DIV_ROUND_UP_ULL((u64)req->best_parent_rate, div); + + return 0; +} +EXPORT_SYMBOL_GPL(divider_determine_rate); + +int divider_ro_determine_rate(struct clk_hw *hw, struct clk_rate_request *req, + const struct clk_div_table *table, u8 width, + unsigned long flags, unsigned int val) +{ + int div; + + div = _get_div(table, val, flags, width); + + /* Even a read-only clock can propagate a rate change */ + if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) { + if (!req->best_parent_hw) + return -EINVAL; + + req->best_parent_rate = clk_hw_round_rate(req->best_parent_hw, + req->rate * div); + } + + req->rate = DIV_ROUND_UP_ULL((u64)req->best_parent_rate, div); + + return 0; +} +EXPORT_SYMBOL_GPL(divider_ro_determine_rate); + long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, unsigned long rate, unsigned long *prate, const struct clk_div_table *table, u8 width, unsigned long flags) { - int div; + struct clk_rate_request req = { + .rate = rate, + .best_parent_rate = *prate, + .best_parent_hw = parent, + }; + int ret; - div = clk_divider_bestdiv(hw, parent, rate, prate, table, width, flags); + ret = divider_determine_rate(hw, &req, table, width, flags); + if (ret) + return ret; - return DIV_ROUND_UP_ULL((u64)*prate, div); + *prate = req.best_parent_rate; + + return req.rate; } EXPORT_SYMBOL_GPL(divider_round_rate_parent); @@ -361,23 +408,23 @@ long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, const struct clk_div_table *table, u8 width, unsigned long flags, unsigned int val) { - int div; - - div = _get_div(table, val, flags, width); + struct clk_rate_request req = { + .rate = rate, + .best_parent_rate = *prate, + .best_parent_hw = parent, + }; + int ret; - /* Even a read-only clock can propagate a rate change */ - if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) { - if (!parent) - return -EINVAL; + ret = divider_ro_determine_rate(hw, &req, table, width, flags, val); + if (ret) + return ret; - *prate = clk_hw_round_rate(parent, rate * div); - } + *prate = req.best_parent_rate; - return DIV_ROUND_UP_ULL((u64)*prate, div); + return req.rate; } EXPORT_SYMBOL_GPL(divider_ro_round_rate_parent); - static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { diff --git a/drivers/clk/clk-k210.c b/drivers/clk/clk-k210.c index 6c84abf5b2e3..67a7cb3503c3 100644 --- a/drivers/clk/clk-k210.c +++ b/drivers/clk/clk-k210.c @@ -722,6 +722,7 @@ static int k210_clk_set_parent(struct clk_hw *hw, u8 index) reg |= BIT(cfg->mux_bit); else reg &= ~BIT(cfg->mux_bit); + writel(reg, ksc->regs + cfg->mux_reg); spin_unlock_irqrestore(&ksc->clk_lock, flags); return 0; diff --git a/drivers/clk/clk-lmk04832.c b/drivers/clk/clk-lmk04832.c index c1095e733220..c7a3a029fb1e 100644 --- a/drivers/clk/clk-lmk04832.c +++ b/drivers/clk/clk-lmk04832.c @@ -519,7 +519,7 @@ static long lmk04832_vco_round_rate(struct clk_hw *hw, unsigned long rate, vco_rate = lmk04832_calc_pll2_params(*prate, rate, &n, &p, &r); if (vco_rate < 0) { - dev_err(lmk->dev, "PLL2 parmeters out of range\n"); + dev_err(lmk->dev, "PLL2 parameters out of range\n"); return vco_rate; } @@ -550,7 +550,7 @@ static int lmk04832_vco_set_rate(struct clk_hw *hw, unsigned long rate, vco_rate = lmk04832_calc_pll2_params(prate, rate, &n, &p, &r); if (vco_rate < 0) { - dev_err(lmk->dev, "failed to determine PLL2 parmeters\n"); + dev_err(lmk->dev, "failed to determine PLL2 parameters\n"); return vco_rate; } @@ -573,7 +573,7 @@ static int lmk04832_vco_set_rate(struct clk_hw *hw, unsigned long rate, /* * PLL2_N registers must be programmed after other PLL2 dividers are - * programed to ensure proper VCO frequency calibration + * programmed to ensure proper VCO frequency calibration */ ret = regmap_write(lmk->regmap, LMK04832_REG_PLL2_N_0, FIELD_GET(0x030000, n)); @@ -1120,7 +1120,7 @@ static int lmk04832_dclk_set_rate(struct clk_hw *hw, unsigned long rate, return -EINVAL; } - /* Enable Duty Cycle Corretion */ + /* Enable Duty Cycle Correction */ if (dclk_div == 1) { ret = regmap_update_bits(lmk->regmap, LMK04832_REG_CLKOUT_CTRL3(dclk->id), @@ -1425,23 +1425,23 @@ static int lmk04832_probe(struct spi_device *spi) lmk->dclk = devm_kcalloc(lmk->dev, info->num_channels >> 1, sizeof(struct lmk_dclk), GFP_KERNEL); - if (IS_ERR(lmk->dclk)) { - ret = PTR_ERR(lmk->dclk); + if (!lmk->dclk) { + ret = -ENOMEM; goto err_disable_oscin; } lmk->clkout = devm_kcalloc(lmk->dev, info->num_channels, sizeof(*lmk->clkout), GFP_KERNEL); - if (IS_ERR(lmk->clkout)) { - ret = PTR_ERR(lmk->clkout); + if (!lmk->clkout) { + ret = -ENOMEM; goto err_disable_oscin; } lmk->clk_data = devm_kzalloc(lmk->dev, struct_size(lmk->clk_data, hws, info->num_channels), GFP_KERNEL); - if (IS_ERR(lmk->clk_data)) { - ret = PTR_ERR(lmk->clk_data); + if (!lmk->clk_data) { + ret = -ENOMEM; goto err_disable_oscin; } diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c index 6adc625e79cb..256575bd29b9 100644 --- a/drivers/clk/clk-stm32mp1.c +++ b/drivers/clk/clk-stm32mp1.c @@ -2263,6 +2263,7 @@ static int stm32_rcc_reset_init(struct device *dev, void __iomem *base, if (!reset_data) return -ENOMEM; + spin_lock_init(&reset_data->lock); reset_data->membase = base; reset_data->rcdev.owner = THIS_MODULE; reset_data->rcdev.ops = &stm32_reset_ops; diff --git a/drivers/clk/hisilicon/clk-hi3559a.c b/drivers/clk/hisilicon/clk-hi3559a.c index b1f19c43b558..56012a3d0219 100644 --- a/drivers/clk/hisilicon/clk-hi3559a.c +++ b/drivers/clk/hisilicon/clk-hi3559a.c @@ -107,25 +107,25 @@ static const struct hisi_fixed_rate_clock hi3559av100_fixed_rate_clks_crg[] = { }; -static const char *fmc_mux_p[] __initconst = { +static const char *fmc_mux_p[] = { "24m", "75m", "125m", "150m", "200m", "250m", "300m", "400m" }; -static const char *mmc_mux_p[] __initconst = { +static const char *mmc_mux_p[] = { "100k", "25m", "49p5m", "99m", "187p5m", "150m", "198m", "400k" }; -static const char *sysapb_mux_p[] __initconst = { +static const char *sysapb_mux_p[] = { "24m", "50m", }; -static const char *sysbus_mux_p[] __initconst = { +static const char *sysbus_mux_p[] = { "24m", "300m" }; -static const char *uart_mux_p[] __initconst = { "50m", "24m", "3m" }; +static const char *uart_mux_p[] = { "50m", "24m", "3m" }; -static const char *a73_clksel_mux_p[] __initconst = { +static const char *a73_clksel_mux_p[] = { "24m", "apll", "1000m" }; @@ -136,7 +136,7 @@ static const u32 sysbus_mux_table[] = { 0, 1 }; static const u32 uart_mux_table[] = { 0, 1, 2 }; static const u32 a73_clksel_mux_table[] = { 0, 1, 2 }; -static struct hisi_mux_clock hi3559av100_mux_clks_crg[] __initdata = { +static struct hisi_mux_clock hi3559av100_mux_clks_crg[] = { { HI3559AV100_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p), CLK_SET_RATE_PARENT, 0x170, 2, 3, 0, fmc_mux_table, @@ -181,7 +181,7 @@ static struct hisi_mux_clock hi3559av100_mux_clks_crg[] __initdata = { }, }; -static struct hisi_gate_clock hi3559av100_gate_clks[] __initdata = { +static struct hisi_gate_clock hi3559av100_gate_clks[] = { { HI3559AV100_FMC_CLK, "clk_fmc", "fmc_mux", CLK_SET_RATE_PARENT, 0x170, 1, 0, @@ -336,7 +336,7 @@ static struct hisi_gate_clock hi3559av100_gate_clks[] __initdata = { }, }; -static struct hi3559av100_pll_clock hi3559av100_pll_clks[] __initdata = { +static struct hi3559av100_pll_clock hi3559av100_pll_clks[] = { { HI3559AV100_APLL_CLK, "apll", NULL, 0x0, 0, 24, 24, 3, 28, 3, 0x4, 0, 12, 12, 6 @@ -502,7 +502,7 @@ static void hisi_clk_register_pll(struct hi3559av100_pll_clock *clks, } } -static __init struct hisi_clock_data *hi3559av100_clk_register( +static struct hisi_clock_data *hi3559av100_clk_register( struct platform_device *pdev) { struct hisi_clock_data *clk_data; @@ -549,7 +549,7 @@ unregister_fixed_rate: return ERR_PTR(ret); } -static __init void hi3559av100_clk_unregister(struct platform_device *pdev) +static void hi3559av100_clk_unregister(struct platform_device *pdev) { struct hisi_crg_dev *crg = platform_get_drvdata(pdev); @@ -568,8 +568,7 @@ static const struct hisi_crg_funcs hi3559av100_crg_funcs = { .unregister_clks = hi3559av100_clk_unregister, }; -static struct hisi_fixed_rate_clock hi3559av100_shub_fixed_rate_clks[] - __initdata = { +static struct hisi_fixed_rate_clock hi3559av100_shub_fixed_rate_clks[] = { { HI3559AV100_SHUB_SOURCE_SOC_24M, "clk_source_24M", NULL, 0, 24000000UL, }, { HI3559AV100_SHUB_SOURCE_SOC_200M, "clk_source_200M", NULL, 0, 200000000UL, }, { HI3559AV100_SHUB_SOURCE_SOC_300M, "clk_source_300M", NULL, 0, 300000000UL, }, @@ -587,16 +586,16 @@ static struct hisi_fixed_rate_clock hi3559av100_shub_fixed_rate_clks[] /* shub mux clk */ static u32 shub_source_clk_mux_table[] = {0, 1, 2, 3}; -static const char *shub_source_clk_mux_p[] __initconst = { +static const char *shub_source_clk_mux_p[] = { "clk_source_24M", "clk_source_200M", "clk_source_300M", "clk_source_PLL" }; static u32 shub_uart_source_clk_mux_table[] = {0, 1, 2, 3}; -static const char *shub_uart_source_clk_mux_p[] __initconst = { +static const char *shub_uart_source_clk_mux_p[] = { "clk_uart_32K", "clk_uart_div_clk", "clk_uart_div_clk", "clk_source_24M" }; -static struct hisi_mux_clock hi3559av100_shub_mux_clks[] __initdata = { +static struct hisi_mux_clock hi3559av100_shub_mux_clks[] = { { HI3559AV100_SHUB_SOURCE_CLK, "shub_clk", shub_source_clk_mux_p, ARRAY_SIZE(shub_source_clk_mux_p), @@ -615,7 +614,7 @@ static struct hisi_mux_clock hi3559av100_shub_mux_clks[] __initdata = { static struct clk_div_table shub_spi_clk_table[] = {{0, 8}, {1, 4}, {2, 2}}; static struct clk_div_table shub_uart_div_clk_table[] = {{1, 8}, {2, 4}}; -static struct hisi_divider_clock hi3559av100_shub_div_clks[] __initdata = { +static struct hisi_divider_clock hi3559av100_shub_div_clks[] = { { HI3559AV100_SHUB_SPI_SOURCE_CLK, "clk_spi_clk", "shub_clk", 0, 0x20, 24, 2, CLK_DIVIDER_ALLOW_ZERO, shub_spi_clk_table, }, @@ -625,7 +624,7 @@ static struct hisi_divider_clock hi3559av100_shub_div_clks[] __initdata = { }; /* shub gate clk */ -static struct hisi_gate_clock hi3559av100_shub_gate_clks[] __initdata = { +static struct hisi_gate_clock hi3559av100_shub_gate_clks[] = { { HI3559AV100_SHUB_SPI0_CLK, "clk_shub_spi0", "clk_spi_clk", 0, 0x20, 1, 0, @@ -697,7 +696,7 @@ static int hi3559av100_shub_default_clk_set(void) return 0; } -static __init struct hisi_clock_data *hi3559av100_shub_clk_register( +static struct hisi_clock_data *hi3559av100_shub_clk_register( struct platform_device *pdev) { struct hisi_clock_data *clk_data = NULL; @@ -751,7 +750,7 @@ unregister_fixed_rate: return ERR_PTR(ret); } -static __init void hi3559av100_shub_clk_unregister(struct platform_device *pdev) +static void hi3559av100_shub_clk_unregister(struct platform_device *pdev) { struct hisi_crg_dev *crg = platform_get_drvdata(pdev); diff --git a/drivers/clk/meson/clk-regmap.c b/drivers/clk/meson/clk-regmap.c index dcd1757cc5df..8ad8977cf1c2 100644 --- a/drivers/clk/meson/clk-regmap.c +++ b/drivers/clk/meson/clk-regmap.c @@ -75,8 +75,8 @@ static unsigned long clk_regmap_div_recalc_rate(struct clk_hw *hw, div->width); } -static long clk_regmap_div_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_regmap_div_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct clk_regmap *clk = to_clk_regmap(hw); struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk); @@ -87,18 +87,17 @@ static long clk_regmap_div_round_rate(struct clk_hw *hw, unsigned long rate, if (div->flags & CLK_DIVIDER_READ_ONLY) { ret = regmap_read(clk->map, div->offset, &val); if (ret) - /* Gives a hint that something is wrong */ - return 0; + return ret; val >>= div->shift; val &= clk_div_mask(div->width); - return divider_ro_round_rate(hw, rate, prate, div->table, - div->width, div->flags, val); + return divider_ro_determine_rate(hw, req, div->table, + div->width, div->flags, val); } - return divider_round_rate(hw, rate, prate, div->table, div->width, - div->flags); + return divider_determine_rate(hw, req, div->table, div->width, + div->flags); } static int clk_regmap_div_set_rate(struct clk_hw *hw, unsigned long rate, @@ -123,14 +122,14 @@ static int clk_regmap_div_set_rate(struct clk_hw *hw, unsigned long rate, const struct clk_ops clk_regmap_divider_ops = { .recalc_rate = clk_regmap_div_recalc_rate, - .round_rate = clk_regmap_div_round_rate, + .determine_rate = clk_regmap_div_determine_rate, .set_rate = clk_regmap_div_set_rate, }; EXPORT_SYMBOL_GPL(clk_regmap_divider_ops); const struct clk_ops clk_regmap_divider_ro_ops = { .recalc_rate = clk_regmap_div_recalc_rate, - .round_rate = clk_regmap_div_round_rate, + .determine_rate = clk_regmap_div_determine_rate, }; EXPORT_SYMBOL_GPL(clk_regmap_divider_ro_ops); diff --git a/drivers/comedi/drivers/comedi_8254.c b/drivers/comedi/drivers/comedi_8254.c index d1d509e9add9..4bf5daa9e885 100644 --- a/drivers/comedi/drivers/comedi_8254.c +++ b/drivers/comedi/drivers/comedi_8254.c @@ -555,6 +555,7 @@ static int comedi_8254_insn_config(struct comedi_device *dev, /** * comedi_8254_subdevice_init - initialize a comedi_subdevice for the 8254 timer * @s: comedi_subdevice struct + * @i8254: comedi_8254 struct */ void comedi_8254_subdevice_init(struct comedi_subdevice *s, struct comedi_8254 *i8254) @@ -607,7 +608,7 @@ static struct comedi_8254 *__i8254_init(unsigned long iobase, /** * comedi_8254_init - allocate and initialize the 8254 device for pio access - * @mmio: port I/O base address + * @iobase: port I/O base address * @osc_base: base time of the counter in ns * OPTIONAL - only used by comedi_8254_cascade_ns_to_timer() * @iosize: I/O register size diff --git a/drivers/comedi/drivers/comedi_isadma.c b/drivers/comedi/drivers/comedi_isadma.c index c729094298c2..479b58e209ba 100644 --- a/drivers/comedi/drivers/comedi_isadma.c +++ b/drivers/comedi/drivers/comedi_isadma.c @@ -143,7 +143,7 @@ EXPORT_SYMBOL_GPL(comedi_isadma_set_mode); * comedi_isadma_alloc - allocate and initialize the ISA DMA * @dev: comedi_device struct * @n_desc: the number of cookies to allocate - * @dma_chan: DMA channel for the first cookie + * @dma_chan1: DMA channel for the first cookie * @dma_chan2: DMA channel for the second cookie * @maxsize: the size of the buffer to allocate for each cookie * @dma_dir: the DMA direction diff --git a/drivers/comedi/drivers/jr3_pci.c b/drivers/comedi/drivers/jr3_pci.c index 7a02c4fa3cda..f963080dd61f 100644 --- a/drivers/comedi/drivers/jr3_pci.c +++ b/drivers/comedi/drivers/jr3_pci.c @@ -186,19 +186,6 @@ static void set_full_scales(struct jr3_sensor __iomem *sensor, set_s16(&sensor->command_word0, 0x0a00); } -static struct six_axis_t get_min_full_scales(struct jr3_sensor __iomem *sensor) -{ - struct six_axis_t result; - - result.fx = get_s16(&sensor->min_full_scale.fx); - result.fy = get_s16(&sensor->min_full_scale.fy); - result.fz = get_s16(&sensor->min_full_scale.fz); - result.mx = get_s16(&sensor->min_full_scale.mx); - result.my = get_s16(&sensor->min_full_scale.my); - result.mz = get_s16(&sensor->min_full_scale.mz); - return result; -} - static struct six_axis_t get_max_full_scales(struct jr3_sensor __iomem *sensor) { struct six_axis_t result; @@ -504,10 +491,8 @@ jr3_pci_poll_subdevice(struct comedi_subdevice *s) result = poll_delay_min_max(20, 100); } else { /* Set full scale */ - struct six_axis_t min_full_scale; struct six_axis_t max_full_scale; - min_full_scale = get_min_full_scales(sensor); max_full_scale = get_max_full_scales(sensor); set_full_scales(sensor, max_full_scale); diff --git a/drivers/comedi/drivers/ni_routes.c b/drivers/comedi/drivers/ni_routes.c index c426a9286f15..f0f8cd424b30 100644 --- a/drivers/comedi/drivers/ni_routes.c +++ b/drivers/comedi/drivers/ni_routes.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routes.c * Route information for NI boards. @@ -246,7 +245,7 @@ unsigned int ni_get_valid_routes(const struct ni_route_tables *tables, } EXPORT_SYMBOL_GPL(ni_get_valid_routes); -/** +/* * List of NI global signal names that, as destinations, are only routeable * indirectly through the *_arg elements of the comedi_cmd structure. */ @@ -388,7 +387,7 @@ ni_find_route_set(const int destination, } EXPORT_SYMBOL_GPL(ni_find_route_set); -/** +/* * ni_route_set_has_source() - Determines whether the given source is in * included given route_set. * @@ -507,7 +506,7 @@ s8 ni_route_to_register(const int src, const int dest, } EXPORT_SYMBOL_GPL(ni_route_to_register); -/** +/* * ni_find_route_source() - Finds the signal source corresponding to a signal * route (src-->dest) of the specified routing register * value and the specified route destination on the diff --git a/drivers/comedi/drivers/ni_routes.h b/drivers/comedi/drivers/ni_routes.h index b7680fd2afe1..036982315584 100644 --- a/drivers/comedi/drivers/ni_routes.h +++ b/drivers/comedi/drivers/ni_routes.h @@ -1,5 +1,4 @@ /* SPDX-License-Identifier: GPL-2.0+ */ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routes.h * Route information for NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes.c b/drivers/comedi/drivers/ni_routing/ni_device_routes.c index 7b6a74dfe48b..58654c2b12d6 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes.h b/drivers/comedi/drivers/ni_routing/ni_device_routes.h index b9f1c47d19e1..09e4e172c659 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes.h +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes.h @@ -1,5 +1,4 @@ /* SPDX-License-Identifier: GPL-2.0+ */ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/all.h b/drivers/comedi/drivers/ni_routing/ni_device_routes/all.h index 78b24138acb7..001dbb88a874 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/all.h +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/all.h @@ -1,5 +1,4 @@ /* SPDX-License-Identifier: GPL-2.0+ */ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/all.h * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6070e.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6070e.c index f1126a0cb285..7d3064c92643 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6070e.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6070e.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pci-6070e.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6220.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6220.c index 74a59222963f..e2c462edb8ec 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6220.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6220.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pci-6220.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6221.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6221.c index 44dcbabf2a99..9e02ec0a66ad 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6221.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6221.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pci-6221.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6229.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6229.c index fa5794e4e2b3..33f7fff61f74 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6229.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6229.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pci-6229.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6251.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6251.c index 645fd1cd2de4..dde676b73624 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6251.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6251.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pci-6251.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6254.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6254.c index 056a240cd3a2..167a2da97c14 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6254.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6254.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pci-6254.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6259.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6259.c index e0b5fa78c3bc..ba990f98590c 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6259.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6259.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pci-6259.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6534.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6534.c index a2472ed288cf..f8d2a91b6c0a 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6534.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6534.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pci-6534.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6602.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6602.c index 91de9dac2d6a..2eee91f590eb 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6602.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6602.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pci-6602.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6713.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6713.c index d378b36d2084..c07ef3584a4b 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6713.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6713.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pci-6713.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6723.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6723.c index e0cc57ab06e7..c37373f8f0e1 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6723.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6723.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pci-6723.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6733.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6733.c index f6e1e17ab854..f252fbe19638 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6733.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pci-6733.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pci-6733.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6030e.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6030e.c index 9978d632117f..4ccba4fdf3bc 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6030e.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6030e.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pxi-6030e.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6224.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6224.c index 1b89e27d7aa5..84fdfa2ef9a7 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6224.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6224.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pxi-6224.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6225.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6225.c index 10dfc34bc87c..2b99ce0f87a4 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6225.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6225.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pxi-6225.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6251.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6251.c index 25db4b7363de..1c5164c46306 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6251.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6251.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pxi-6251.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6733.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6733.c index 27da4433fc4a..a3402b1ca6e8 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6733.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pxi-6733.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pxi-6733.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pxie-6251.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pxie-6251.c index 8354fe971d59..defcc4cfe1e4 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pxie-6251.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pxie-6251.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pxie-6251.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pxie-6535.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pxie-6535.c index 2ebb679e0129..d2013b9e6767 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pxie-6535.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pxie-6535.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pxie-6535.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_device_routes/pxie-6738.c b/drivers/comedi/drivers/ni_routing/ni_device_routes/pxie-6738.c index d88504314d7f..89aff39a4fc2 100644 --- a/drivers/comedi/drivers/ni_routing/ni_device_routes/pxie-6738.c +++ b/drivers/comedi/drivers/ni_routing/ni_device_routes/pxie-6738.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_device_routes/pxie-6738.c * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_route_values.c b/drivers/comedi/drivers/ni_routing/ni_route_values.c index 5901762734ed..54a740b39819 100644 --- a/drivers/comedi/drivers/ni_routing/ni_route_values.c +++ b/drivers/comedi/drivers/ni_routing/ni_route_values.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_route_values.c * Route information for NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_route_values.h b/drivers/comedi/drivers/ni_routing/ni_route_values.h index 80e0145fb82b..6e358efa6f7f 100644 --- a/drivers/comedi/drivers/ni_routing/ni_route_values.h +++ b/drivers/comedi/drivers/ni_routing/ni_route_values.h @@ -1,5 +1,4 @@ /* SPDX-License-Identifier: GPL-2.0+ */ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_route_values.h * Route information for NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_route_values/all.h b/drivers/comedi/drivers/ni_routing/ni_route_values/all.h index 7227461500b5..30761e55f746 100644 --- a/drivers/comedi/drivers/ni_routing/ni_route_values/all.h +++ b/drivers/comedi/drivers/ni_routing/ni_route_values/all.h @@ -1,5 +1,4 @@ /* SPDX-License-Identifier: GPL-2.0+ */ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_route_values/all.h * List of valid routes for specific NI boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_route_values/ni_660x.c b/drivers/comedi/drivers/ni_routing/ni_route_values/ni_660x.c index f1c7e6646261..aace60e49507 100644 --- a/drivers/comedi/drivers/ni_routing/ni_route_values/ni_660x.c +++ b/drivers/comedi/drivers/ni_routing/ni_route_values/ni_660x.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_route_values/ni_660x.c * Route information for NI_660X boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_route_values/ni_eseries.c b/drivers/comedi/drivers/ni_routing/ni_route_values/ni_eseries.c index d1ab3c9ce585..7a52f024cdbd 100644 --- a/drivers/comedi/drivers/ni_routing/ni_route_values/ni_eseries.c +++ b/drivers/comedi/drivers/ni_routing/ni_route_values/ni_eseries.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_route_values/ni_eseries.c * Route information for NI_ESERIES boards. diff --git a/drivers/comedi/drivers/ni_routing/ni_route_values/ni_mseries.c b/drivers/comedi/drivers/ni_routing/ni_route_values/ni_mseries.c index c59d8afe0ae9..d1ddd13b33b5 100644 --- a/drivers/comedi/drivers/ni_routing/ni_route_values/ni_mseries.c +++ b/drivers/comedi/drivers/ni_routing/ni_route_values/ni_mseries.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/ni_route_values/ni_mseries.c * Route information for NI_MSERIES boards. diff --git a/drivers/comedi/drivers/ni_routing/tools/convert_c_to_py.c b/drivers/comedi/drivers/ni_routing/tools/convert_c_to_py.c index dedb6f2fc678..d55521b5bdcb 100644 --- a/drivers/comedi/drivers/ni_routing/tools/convert_c_to_py.c +++ b/drivers/comedi/drivers/ni_routing/tools/convert_c_to_py.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ #include <stdint.h> #include <stdbool.h> diff --git a/drivers/comedi/drivers/ni_routing/tools/convert_csv_to_c.py b/drivers/comedi/drivers/ni_routing/tools/convert_csv_to_c.py index 532eb6372a5a..90378fb50580 100755 --- a/drivers/comedi/drivers/ni_routing/tools/convert_csv_to_c.py +++ b/drivers/comedi/drivers/ni_routing/tools/convert_csv_to_c.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0+ -# vim: ts=2:sw=2:et:tw=80:nowrap # This is simply to aide in creating the entries in the order of the value of # the device-global NI signal/terminal constants defined in comedi.h @@ -123,7 +122,6 @@ class DeviceRoutes(CSVCollection): output_file_top = """\ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/{filename} * List of valid routes for specific NI boards. @@ -155,7 +153,6 @@ class DeviceRoutes(CSVCollection): extern_header = """\ /* SPDX-License-Identifier: GPL-2.0+ */ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/{filename} * List of valid routes for specific NI boards. @@ -193,7 +190,6 @@ class DeviceRoutes(CSVCollection): single_output_file_top = """\ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/{filename} * List of valid routes for specific NI boards. @@ -299,7 +295,6 @@ class RouteValues(CSVCollection): output_file_top = """\ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/{filename} * Route information for NI boards. @@ -337,7 +332,6 @@ class RouteValues(CSVCollection): extern_header = """\ /* SPDX-License-Identifier: GPL-2.0+ */ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/{filename} * List of valid routes for specific NI boards. @@ -375,7 +369,6 @@ class RouteValues(CSVCollection): single_output_file_top = """\ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/ni_routing/{filename} * Route information for {sheet} boards. diff --git a/drivers/comedi/drivers/ni_routing/tools/convert_py_to_csv.py b/drivers/comedi/drivers/ni_routing/tools/convert_py_to_csv.py index b3e6472bac22..a273b33edb8f 100755 --- a/drivers/comedi/drivers/ni_routing/tools/convert_py_to_csv.py +++ b/drivers/comedi/drivers/ni_routing/tools/convert_py_to_csv.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0+ -# vim: ts=2:sw=2:et:tw=80:nowrap from os import path import os, csv diff --git a/drivers/comedi/drivers/ni_routing/tools/csv_collection.py b/drivers/comedi/drivers/ni_routing/tools/csv_collection.py index 12617329a928..db977ecb4307 100644 --- a/drivers/comedi/drivers/ni_routing/tools/csv_collection.py +++ b/drivers/comedi/drivers/ni_routing/tools/csv_collection.py @@ -1,5 +1,4 @@ # SPDX-License-Identifier: GPL-2.0+ -# vim: ts=2:sw=2:et:tw=80:nowrap import os, csv, glob diff --git a/drivers/comedi/drivers/ni_routing/tools/make_blank_csv.py b/drivers/comedi/drivers/ni_routing/tools/make_blank_csv.py index 89c90a0ba24d..c00eaf803299 100755 --- a/drivers/comedi/drivers/ni_routing/tools/make_blank_csv.py +++ b/drivers/comedi/drivers/ni_routing/tools/make_blank_csv.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0+ -# vim: ts=2:sw=2:et:tw=80:nowrap from os import path import os, csv diff --git a/drivers/comedi/drivers/ni_routing/tools/ni_names.py b/drivers/comedi/drivers/ni_routing/tools/ni_names.py index 5f9b825968b1..d4df5f29e3e5 100644 --- a/drivers/comedi/drivers/ni_routing/tools/ni_names.py +++ b/drivers/comedi/drivers/ni_routing/tools/ni_names.py @@ -1,5 +1,4 @@ # SPDX-License-Identifier: GPL-2.0+ -# vim: ts=2:sw=2:et:tw=80:nowrap """ This file helps to extract string names of NI signals as included in comedi.h between NI_NAMES_BASE and NI_NAMES_BASE+NI_NUM_NAMES. diff --git a/drivers/comedi/drivers/ni_tio.c b/drivers/comedi/drivers/ni_tio.c index f6154addaa95..da6826d77e60 100644 --- a/drivers/comedi/drivers/ni_tio.c +++ b/drivers/comedi/drivers/ni_tio.c @@ -1501,7 +1501,7 @@ int ni_tio_insn_config(struct comedi_device *dev, } EXPORT_SYMBOL_GPL(ni_tio_insn_config); -/** +/* * Retrieves the register value of the current source of the output selector for * the given destination. * @@ -1541,10 +1541,10 @@ int ni_tio_get_routing(struct ni_gpct_device *counter_dev, unsigned int dest) EXPORT_SYMBOL_GPL(ni_tio_get_routing); /** - * Sets the register value of the selector MUX for the given destination. - * @counter_dev:Pointer to general counter device. - * @destination:Device-global identifier of route destination. - * @register_value: + * ni_tio_set_routing() - Sets the register value of the selector MUX for the given destination. + * @counter_dev: Pointer to general counter device. + * @dest: Device-global identifier of route destination. + * @reg: * The first several bits of this value should store the desired * value to write to the register. All other bits are for * transmitting information that modify the mode of the particular @@ -1580,7 +1580,7 @@ int ni_tio_set_routing(struct ni_gpct_device *counter_dev, unsigned int dest, } EXPORT_SYMBOL_GPL(ni_tio_set_routing); -/** +/* * Sets the given destination MUX to its default value or disable it. * * Return: 0 if successful; -EINVAL if terminal is unknown. diff --git a/drivers/comedi/drivers/tests/comedi_example_test.c b/drivers/comedi/drivers/tests/comedi_example_test.c index e5aaaeab7bdd..81d074bcdea5 100644 --- a/drivers/comedi/drivers/tests/comedi_example_test.c +++ b/drivers/comedi/drivers/tests/comedi_example_test.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/tests/comedi_example_test.c * Example set of unit tests. diff --git a/drivers/comedi/drivers/tests/ni_routes_test.c b/drivers/comedi/drivers/tests/ni_routes_test.c index 32073850d545..652362486ff6 100644 --- a/drivers/comedi/drivers/tests/ni_routes_test.c +++ b/drivers/comedi/drivers/tests/ni_routes_test.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/tests/ni_routes_test.c * Unit tests for NI routes (ni_routes.c module). diff --git a/drivers/comedi/drivers/tests/unittest.h b/drivers/comedi/drivers/tests/unittest.h index 2da3beea2479..b0b34e058aad 100644 --- a/drivers/comedi/drivers/tests/unittest.h +++ b/drivers/comedi/drivers/tests/unittest.h @@ -1,5 +1,4 @@ /* SPDX-License-Identifier: GPL-2.0+ */ -/* vim: set ts=8 sw=8 noet tw=80 nowrap: */ /* * comedi/drivers/tests/unittest.h * Simple framework for unittests for comedi drivers. diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c index 9691f8612be8..09a9a77cce06 100644 --- a/drivers/counter/104-quad-8.c +++ b/drivers/counter/104-quad-8.c @@ -21,7 +21,7 @@ static unsigned int base[max_num_isa_dev(QUAD8_EXTENT)]; static unsigned int num_quad8; -module_param_array(base, uint, &num_quad8, 0); +module_param_hw_array(base, uint, ioport, &num_quad8, 0); MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses"); #define QUAD8_NUM_COUNTERS 8 @@ -193,7 +193,7 @@ enum quad8_count_function { QUAD8_COUNT_FUNCTION_QUADRATURE_X4 }; -static enum counter_count_function quad8_count_functions_list[] = { +static const enum counter_count_function quad8_count_functions_list[] = { [QUAD8_COUNT_FUNCTION_PULSE_DIRECTION] = COUNTER_COUNT_FUNCTION_PULSE_DIRECTION, [QUAD8_COUNT_FUNCTION_QUADRATURE_X1] = COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A, [QUAD8_COUNT_FUNCTION_QUADRATURE_X2] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A, @@ -305,12 +305,12 @@ enum quad8_synapse_action { QUAD8_SYNAPSE_ACTION_BOTH_EDGES }; -static enum counter_synapse_action quad8_index_actions_list[] = { +static const enum counter_synapse_action quad8_index_actions_list[] = { [QUAD8_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE, [QUAD8_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE }; -static enum counter_synapse_action quad8_synapse_actions_list[] = { +static const enum counter_synapse_action quad8_synapse_actions_list[] = { [QUAD8_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE, [QUAD8_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE, [QUAD8_SYNAPSE_ACTION_FALLING_EDGE] = COUNTER_SYNAPSE_ACTION_FALLING_EDGE, @@ -632,8 +632,8 @@ static ssize_t quad8_count_preset_read(struct counter_device *counter, return sprintf(buf, "%u\n", priv->preset[count->id]); } -static void quad8_preset_register_set(struct quad8 *priv, int id, - unsigned int preset) +static void quad8_preset_register_set(struct quad8 *const priv, const int id, + const unsigned int preset) { const unsigned int base_offset = priv->base + 2 * id; int i; @@ -1082,7 +1082,6 @@ static int quad8_probe(struct device *dev, unsigned int id) /* Enable all counters */ outb(QUAD8_CHAN_OP_ENABLE_COUNTERS, base[id] + QUAD8_REG_CHAN_OP); - /* Register Counter device */ return devm_counter_register(dev, &priv->counter); } diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig index 5328705aa09c..d5d2540b30c2 100644 --- a/drivers/counter/Kconfig +++ b/drivers/counter/Kconfig @@ -91,4 +91,14 @@ config MICROCHIP_TCB_CAPTURE To compile this driver as a module, choose M here: the module will be called microchip-tcb-capture. +config INTEL_QEP + tristate "Intel Quadrature Encoder Peripheral driver" + depends on PCI + help + Select this option to enable the Intel Quadrature Encoder Peripheral + driver. + + To compile this driver as a module, choose M here: the module + will be called intel-qep. + endif # COUNTER diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile index cb646ed2f039..19742e6f5e3e 100644 --- a/drivers/counter/Makefile +++ b/drivers/counter/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_STM32_LPTIMER_CNT) += stm32-lptimer-cnt.o obj-$(CONFIG_TI_EQEP) += ti-eqep.o obj-$(CONFIG_FTM_QUADDEC) += ftm-quaddec.o obj-$(CONFIG_MICROCHIP_TCB_CAPTURE) += microchip-tcb-capture.o +obj-$(CONFIG_INTEL_QEP) += intel-qep.o diff --git a/drivers/counter/ftm-quaddec.c b/drivers/counter/ftm-quaddec.c index c2b3fdfd8b77..9371532406ca 100644 --- a/drivers/counter/ftm-quaddec.c +++ b/drivers/counter/ftm-quaddec.c @@ -162,7 +162,7 @@ enum ftm_quaddec_synapse_action { FTM_QUADDEC_SYNAPSE_ACTION_BOTH_EDGES, }; -static enum counter_synapse_action ftm_quaddec_synapse_actions[] = { +static const enum counter_synapse_action ftm_quaddec_synapse_actions[] = { [FTM_QUADDEC_SYNAPSE_ACTION_BOTH_EDGES] = COUNTER_SYNAPSE_ACTION_BOTH_EDGES }; diff --git a/drivers/counter/intel-qep.c b/drivers/counter/intel-qep.c new file mode 100644 index 000000000000..8d7ae28fbd67 --- /dev/null +++ b/drivers/counter/intel-qep.c @@ -0,0 +1,544 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Intel Quadrature Encoder Peripheral driver + * + * Copyright (C) 2019-2021 Intel Corporation + * + * Author: Felipe Balbi (Intel) + * Author: Jarkko Nikula <jarkko.nikula@linux.intel.com> + * Author: Raymond Tan <raymond.tan@intel.com> + */ +#include <linux/bitops.h> +#include <linux/counter.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/pci.h> +#include <linux/pm_runtime.h> + +#define INTEL_QEPCON 0x00 +#define INTEL_QEPFLT 0x04 +#define INTEL_QEPCOUNT 0x08 +#define INTEL_QEPMAX 0x0c +#define INTEL_QEPWDT 0x10 +#define INTEL_QEPCAPDIV 0x14 +#define INTEL_QEPCNTR 0x18 +#define INTEL_QEPCAPBUF 0x1c +#define INTEL_QEPINT_STAT 0x20 +#define INTEL_QEPINT_MASK 0x24 + +/* QEPCON */ +#define INTEL_QEPCON_EN BIT(0) +#define INTEL_QEPCON_FLT_EN BIT(1) +#define INTEL_QEPCON_EDGE_A BIT(2) +#define INTEL_QEPCON_EDGE_B BIT(3) +#define INTEL_QEPCON_EDGE_INDX BIT(4) +#define INTEL_QEPCON_SWPAB BIT(5) +#define INTEL_QEPCON_OP_MODE BIT(6) +#define INTEL_QEPCON_PH_ERR BIT(7) +#define INTEL_QEPCON_COUNT_RST_MODE BIT(8) +#define INTEL_QEPCON_INDX_GATING_MASK GENMASK(10, 9) +#define INTEL_QEPCON_INDX_GATING(n) (((n) & 3) << 9) +#define INTEL_QEPCON_INDX_PAL_PBL INTEL_QEPCON_INDX_GATING(0) +#define INTEL_QEPCON_INDX_PAL_PBH INTEL_QEPCON_INDX_GATING(1) +#define INTEL_QEPCON_INDX_PAH_PBL INTEL_QEPCON_INDX_GATING(2) +#define INTEL_QEPCON_INDX_PAH_PBH INTEL_QEPCON_INDX_GATING(3) +#define INTEL_QEPCON_CAP_MODE BIT(11) +#define INTEL_QEPCON_FIFO_THRE_MASK GENMASK(14, 12) +#define INTEL_QEPCON_FIFO_THRE(n) ((((n) - 1) & 7) << 12) +#define INTEL_QEPCON_FIFO_EMPTY BIT(15) + +/* QEPFLT */ +#define INTEL_QEPFLT_MAX_COUNT(n) ((n) & 0x1fffff) + +/* QEPINT */ +#define INTEL_QEPINT_FIFOCRIT BIT(5) +#define INTEL_QEPINT_FIFOENTRY BIT(4) +#define INTEL_QEPINT_QEPDIR BIT(3) +#define INTEL_QEPINT_QEPRST_UP BIT(2) +#define INTEL_QEPINT_QEPRST_DOWN BIT(1) +#define INTEL_QEPINT_WDT BIT(0) + +#define INTEL_QEPINT_MASK_ALL GENMASK(5, 0) + +#define INTEL_QEP_CLK_PERIOD_NS 10 + +#define INTEL_QEP_COUNTER_EXT_RW(_name) \ +{ \ + .name = #_name, \ + .read = _name##_read, \ + .write = _name##_write, \ +} + +struct intel_qep { + struct counter_device counter; + struct mutex lock; + struct device *dev; + void __iomem *regs; + bool enabled; + /* Context save registers */ + u32 qepcon; + u32 qepflt; + u32 qepmax; +}; + +static inline u32 intel_qep_readl(struct intel_qep *qep, u32 offset) +{ + return readl(qep->regs + offset); +} + +static inline void intel_qep_writel(struct intel_qep *qep, + u32 offset, u32 value) +{ + writel(value, qep->regs + offset); +} + +static void intel_qep_init(struct intel_qep *qep) +{ + u32 reg; + + reg = intel_qep_readl(qep, INTEL_QEPCON); + reg &= ~INTEL_QEPCON_EN; + intel_qep_writel(qep, INTEL_QEPCON, reg); + qep->enabled = false; + /* + * Make sure peripheral is disabled by flushing the write with + * a dummy read + */ + reg = intel_qep_readl(qep, INTEL_QEPCON); + + reg &= ~(INTEL_QEPCON_OP_MODE | INTEL_QEPCON_FLT_EN); + reg |= INTEL_QEPCON_EDGE_A | INTEL_QEPCON_EDGE_B | + INTEL_QEPCON_EDGE_INDX | INTEL_QEPCON_COUNT_RST_MODE; + intel_qep_writel(qep, INTEL_QEPCON, reg); + intel_qep_writel(qep, INTEL_QEPINT_MASK, INTEL_QEPINT_MASK_ALL); +} + +static int intel_qep_count_read(struct counter_device *counter, + struct counter_count *count, + unsigned long *val) +{ + struct intel_qep *const qep = counter->priv; + + pm_runtime_get_sync(qep->dev); + *val = intel_qep_readl(qep, INTEL_QEPCOUNT); + pm_runtime_put(qep->dev); + + return 0; +} + +static const enum counter_count_function intel_qep_count_functions[] = { + COUNTER_COUNT_FUNCTION_QUADRATURE_X4, +}; + +static int intel_qep_function_get(struct counter_device *counter, + struct counter_count *count, + size_t *function) +{ + *function = 0; + + return 0; +} + +static const enum counter_synapse_action intel_qep_synapse_actions[] = { + COUNTER_SYNAPSE_ACTION_BOTH_EDGES, +}; + +static int intel_qep_action_get(struct counter_device *counter, + struct counter_count *count, + struct counter_synapse *synapse, + size_t *action) +{ + *action = 0; + return 0; +} + +static const struct counter_ops intel_qep_counter_ops = { + .count_read = intel_qep_count_read, + .function_get = intel_qep_function_get, + .action_get = intel_qep_action_get, +}; + +#define INTEL_QEP_SIGNAL(_id, _name) { \ + .id = (_id), \ + .name = (_name), \ +} + +static struct counter_signal intel_qep_signals[] = { + INTEL_QEP_SIGNAL(0, "Phase A"), + INTEL_QEP_SIGNAL(1, "Phase B"), + INTEL_QEP_SIGNAL(2, "Index"), +}; + +#define INTEL_QEP_SYNAPSE(_signal_id) { \ + .actions_list = intel_qep_synapse_actions, \ + .num_actions = ARRAY_SIZE(intel_qep_synapse_actions), \ + .signal = &intel_qep_signals[(_signal_id)], \ +} + +static struct counter_synapse intel_qep_count_synapses[] = { + INTEL_QEP_SYNAPSE(0), + INTEL_QEP_SYNAPSE(1), + INTEL_QEP_SYNAPSE(2), +}; + +static ssize_t ceiling_read(struct counter_device *counter, + struct counter_count *count, + void *priv, char *buf) +{ + struct intel_qep *qep = counter->priv; + u32 reg; + + pm_runtime_get_sync(qep->dev); + reg = intel_qep_readl(qep, INTEL_QEPMAX); + pm_runtime_put(qep->dev); + + return sysfs_emit(buf, "%u\n", reg); +} + +static ssize_t ceiling_write(struct counter_device *counter, + struct counter_count *count, + void *priv, const char *buf, size_t len) +{ + struct intel_qep *qep = counter->priv; + u32 max; + int ret; + + ret = kstrtou32(buf, 0, &max); + if (ret < 0) + return ret; + + mutex_lock(&qep->lock); + if (qep->enabled) { + ret = -EBUSY; + goto out; + } + + pm_runtime_get_sync(qep->dev); + intel_qep_writel(qep, INTEL_QEPMAX, max); + pm_runtime_put(qep->dev); + ret = len; + +out: + mutex_unlock(&qep->lock); + return ret; +} + +static ssize_t enable_read(struct counter_device *counter, + struct counter_count *count, + void *priv, char *buf) +{ + struct intel_qep *qep = counter->priv; + + return sysfs_emit(buf, "%u\n", qep->enabled); +} + +static ssize_t enable_write(struct counter_device *counter, + struct counter_count *count, + void *priv, const char *buf, size_t len) +{ + struct intel_qep *qep = counter->priv; + u32 reg; + bool val, changed; + int ret; + + ret = kstrtobool(buf, &val); + if (ret) + return ret; + + mutex_lock(&qep->lock); + changed = val ^ qep->enabled; + if (!changed) + goto out; + + pm_runtime_get_sync(qep->dev); + reg = intel_qep_readl(qep, INTEL_QEPCON); + if (val) { + /* Enable peripheral and keep runtime PM always on */ + reg |= INTEL_QEPCON_EN; + pm_runtime_get_noresume(qep->dev); + } else { + /* Let runtime PM be idle and disable peripheral */ + pm_runtime_put_noidle(qep->dev); + reg &= ~INTEL_QEPCON_EN; + } + intel_qep_writel(qep, INTEL_QEPCON, reg); + pm_runtime_put(qep->dev); + qep->enabled = val; + +out: + mutex_unlock(&qep->lock); + return len; +} + +static ssize_t spike_filter_ns_read(struct counter_device *counter, + struct counter_count *count, + void *priv, char *buf) +{ + struct intel_qep *qep = counter->priv; + u32 reg; + + pm_runtime_get_sync(qep->dev); + reg = intel_qep_readl(qep, INTEL_QEPCON); + if (!(reg & INTEL_QEPCON_FLT_EN)) { + pm_runtime_put(qep->dev); + return sysfs_emit(buf, "0\n"); + } + reg = INTEL_QEPFLT_MAX_COUNT(intel_qep_readl(qep, INTEL_QEPFLT)); + pm_runtime_put(qep->dev); + + return sysfs_emit(buf, "%u\n", (reg + 2) * INTEL_QEP_CLK_PERIOD_NS); +} + +static ssize_t spike_filter_ns_write(struct counter_device *counter, + struct counter_count *count, + void *priv, const char *buf, size_t len) +{ + struct intel_qep *qep = counter->priv; + u32 reg, length; + bool enable; + int ret; + + ret = kstrtou32(buf, 0, &length); + if (ret < 0) + return ret; + + /* + * Spike filter length is (MAX_COUNT + 2) clock periods. + * Disable filter when userspace writes 0, enable for valid + * nanoseconds values and error out otherwise. + */ + length /= INTEL_QEP_CLK_PERIOD_NS; + if (length == 0) { + enable = false; + length = 0; + } else if (length >= 2) { + enable = true; + length -= 2; + } else { + return -EINVAL; + } + + if (length > INTEL_QEPFLT_MAX_COUNT(length)) + return -EINVAL; + + mutex_lock(&qep->lock); + if (qep->enabled) { + ret = -EBUSY; + goto out; + } + + pm_runtime_get_sync(qep->dev); + reg = intel_qep_readl(qep, INTEL_QEPCON); + if (enable) + reg |= INTEL_QEPCON_FLT_EN; + else + reg &= ~INTEL_QEPCON_FLT_EN; + intel_qep_writel(qep, INTEL_QEPFLT, length); + intel_qep_writel(qep, INTEL_QEPCON, reg); + pm_runtime_put(qep->dev); + ret = len; + +out: + mutex_unlock(&qep->lock); + return ret; +} + +static ssize_t preset_enable_read(struct counter_device *counter, + struct counter_count *count, + void *priv, char *buf) +{ + struct intel_qep *qep = counter->priv; + u32 reg; + + pm_runtime_get_sync(qep->dev); + reg = intel_qep_readl(qep, INTEL_QEPCON); + pm_runtime_put(qep->dev); + return sysfs_emit(buf, "%u\n", !(reg & INTEL_QEPCON_COUNT_RST_MODE)); +} + +static ssize_t preset_enable_write(struct counter_device *counter, + struct counter_count *count, + void *priv, const char *buf, size_t len) +{ + struct intel_qep *qep = counter->priv; + u32 reg; + bool val; + int ret; + + ret = kstrtobool(buf, &val); + if (ret) + return ret; + + mutex_lock(&qep->lock); + if (qep->enabled) { + ret = -EBUSY; + goto out; + } + + pm_runtime_get_sync(qep->dev); + reg = intel_qep_readl(qep, INTEL_QEPCON); + if (val) + reg &= ~INTEL_QEPCON_COUNT_RST_MODE; + else + reg |= INTEL_QEPCON_COUNT_RST_MODE; + + intel_qep_writel(qep, INTEL_QEPCON, reg); + pm_runtime_put(qep->dev); + ret = len; + +out: + mutex_unlock(&qep->lock); + + return ret; +} + +static const struct counter_count_ext intel_qep_count_ext[] = { + INTEL_QEP_COUNTER_EXT_RW(ceiling), + INTEL_QEP_COUNTER_EXT_RW(enable), + INTEL_QEP_COUNTER_EXT_RW(spike_filter_ns), + INTEL_QEP_COUNTER_EXT_RW(preset_enable) +}; + +static struct counter_count intel_qep_counter_count[] = { + { + .id = 0, + .name = "Channel 1 Count", + .functions_list = intel_qep_count_functions, + .num_functions = ARRAY_SIZE(intel_qep_count_functions), + .synapses = intel_qep_count_synapses, + .num_synapses = ARRAY_SIZE(intel_qep_count_synapses), + .ext = intel_qep_count_ext, + .num_ext = ARRAY_SIZE(intel_qep_count_ext), + }, +}; + +static int intel_qep_probe(struct pci_dev *pci, const struct pci_device_id *id) +{ + struct intel_qep *qep; + struct device *dev = &pci->dev; + void __iomem *regs; + int ret; + + qep = devm_kzalloc(dev, sizeof(*qep), GFP_KERNEL); + if (!qep) + return -ENOMEM; + + ret = pcim_enable_device(pci); + if (ret) + return ret; + + pci_set_master(pci); + + ret = pcim_iomap_regions(pci, BIT(0), pci_name(pci)); + if (ret) + return ret; + + regs = pcim_iomap_table(pci)[0]; + if (!regs) + return -ENOMEM; + + qep->dev = dev; + qep->regs = regs; + mutex_init(&qep->lock); + + intel_qep_init(qep); + pci_set_drvdata(pci, qep); + + qep->counter.name = pci_name(pci); + qep->counter.parent = dev; + qep->counter.ops = &intel_qep_counter_ops; + qep->counter.counts = intel_qep_counter_count; + qep->counter.num_counts = ARRAY_SIZE(intel_qep_counter_count); + qep->counter.signals = intel_qep_signals; + qep->counter.num_signals = ARRAY_SIZE(intel_qep_signals); + qep->counter.priv = qep; + qep->enabled = false; + + pm_runtime_put(dev); + pm_runtime_allow(dev); + + return devm_counter_register(&pci->dev, &qep->counter); +} + +static void intel_qep_remove(struct pci_dev *pci) +{ + struct intel_qep *qep = pci_get_drvdata(pci); + struct device *dev = &pci->dev; + + pm_runtime_forbid(dev); + if (!qep->enabled) + pm_runtime_get(dev); + + intel_qep_writel(qep, INTEL_QEPCON, 0); +} + +static int __maybe_unused intel_qep_suspend(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct intel_qep *qep = pci_get_drvdata(pdev); + + qep->qepcon = intel_qep_readl(qep, INTEL_QEPCON); + qep->qepflt = intel_qep_readl(qep, INTEL_QEPFLT); + qep->qepmax = intel_qep_readl(qep, INTEL_QEPMAX); + + return 0; +} + +static int __maybe_unused intel_qep_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct intel_qep *qep = pci_get_drvdata(pdev); + + /* + * Make sure peripheral is disabled when restoring registers and + * control register bits that are writable only when the peripheral + * is disabled + */ + intel_qep_writel(qep, INTEL_QEPCON, 0); + intel_qep_readl(qep, INTEL_QEPCON); + + intel_qep_writel(qep, INTEL_QEPFLT, qep->qepflt); + intel_qep_writel(qep, INTEL_QEPMAX, qep->qepmax); + intel_qep_writel(qep, INTEL_QEPINT_MASK, INTEL_QEPINT_MASK_ALL); + + /* Restore all other control register bits except enable status */ + intel_qep_writel(qep, INTEL_QEPCON, qep->qepcon & ~INTEL_QEPCON_EN); + intel_qep_readl(qep, INTEL_QEPCON); + + /* Restore enable status */ + intel_qep_writel(qep, INTEL_QEPCON, qep->qepcon); + + return 0; +} + +static UNIVERSAL_DEV_PM_OPS(intel_qep_pm_ops, + intel_qep_suspend, intel_qep_resume, NULL); + +static const struct pci_device_id intel_qep_id_table[] = { + /* EHL */ + { PCI_VDEVICE(INTEL, 0x4bc3), }, + { PCI_VDEVICE(INTEL, 0x4b81), }, + { PCI_VDEVICE(INTEL, 0x4b82), }, + { PCI_VDEVICE(INTEL, 0x4b83), }, + { } /* Terminating Entry */ +}; +MODULE_DEVICE_TABLE(pci, intel_qep_id_table); + +static struct pci_driver intel_qep_driver = { + .name = "intel-qep", + .id_table = intel_qep_id_table, + .probe = intel_qep_probe, + .remove = intel_qep_remove, + .driver = { + .pm = &intel_qep_pm_ops, + } +}; + +module_pci_driver(intel_qep_driver); + +MODULE_AUTHOR("Felipe Balbi (Intel)"); +MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@linux.intel.com>"); +MODULE_AUTHOR("Raymond Tan <raymond.tan@intel.com>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Intel Quadrature Encoder Peripheral driver"); diff --git a/drivers/counter/interrupt-cnt.c b/drivers/counter/interrupt-cnt.c index a99ee7996977..5df7cd13d4c7 100644 --- a/drivers/counter/interrupt-cnt.c +++ b/drivers/counter/interrupt-cnt.c @@ -77,7 +77,7 @@ static const struct counter_count_ext interrupt_cnt_ext[] = { }, }; -static enum counter_synapse_action interrupt_cnt_synapse_actionss[] = { +static const enum counter_synapse_action interrupt_cnt_synapse_actions[] = { COUNTER_SYNAPSE_ACTION_RISING_EDGE, }; @@ -112,7 +112,7 @@ static int interrupt_cnt_write(struct counter_device *counter, return 0; } -static enum counter_count_function interrupt_cnt_functions[] = { +static const enum counter_count_function interrupt_cnt_functions[] = { COUNTER_COUNT_FUNCTION_INCREASE, }; @@ -194,8 +194,8 @@ static int interrupt_cnt_probe(struct platform_device *pdev) priv->counter.signals = &priv->signals; priv->counter.num_signals = 1; - priv->synapses.actions_list = interrupt_cnt_synapse_actionss; - priv->synapses.num_actions = ARRAY_SIZE(interrupt_cnt_synapse_actionss); + priv->synapses.actions_list = interrupt_cnt_synapse_actions; + priv->synapses.num_actions = ARRAY_SIZE(interrupt_cnt_synapse_actions); priv->synapses.signal = &priv->signals; priv->cnts.name = "Channel 0 Count"; diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c index 710acc0a3704..51b8af80f98b 100644 --- a/drivers/counter/microchip-tcb-capture.c +++ b/drivers/counter/microchip-tcb-capture.c @@ -37,7 +37,7 @@ enum mchp_tc_count_function { MCHP_TC_FUNCTION_QUADRATURE, }; -static enum counter_count_function mchp_tc_count_functions[] = { +static const enum counter_count_function mchp_tc_count_functions[] = { [MCHP_TC_FUNCTION_INCREASE] = COUNTER_COUNT_FUNCTION_INCREASE, [MCHP_TC_FUNCTION_QUADRATURE] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4, }; @@ -49,7 +49,7 @@ enum mchp_tc_synapse_action { MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE }; -static enum counter_synapse_action mchp_tc_synapse_actions[] = { +static const enum counter_synapse_action mchp_tc_synapse_actions[] = { [MCHP_TC_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE, [MCHP_TC_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE, [MCHP_TC_SYNAPSE_ACTION_FALLING_EDGE] = COUNTER_SYNAPSE_ACTION_FALLING_EDGE, diff --git a/drivers/counter/stm32-lptimer-cnt.c b/drivers/counter/stm32-lptimer-cnt.c index 937439635d53..c19d998df5ba 100644 --- a/drivers/counter/stm32-lptimer-cnt.c +++ b/drivers/counter/stm32-lptimer-cnt.c @@ -134,7 +134,7 @@ enum stm32_lptim_cnt_function { STM32_LPTIM_ENCODER_BOTH_EDGE, }; -static enum counter_count_function stm32_lptim_cnt_functions[] = { +static const enum counter_count_function stm32_lptim_cnt_functions[] = { [STM32_LPTIM_COUNTER_INCREASE] = COUNTER_COUNT_FUNCTION_INCREASE, [STM32_LPTIM_ENCODER_BOTH_EDGE] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4, }; @@ -146,7 +146,7 @@ enum stm32_lptim_synapse_action { STM32_LPTIM_SYNAPSE_ACTION_NONE, }; -static enum counter_synapse_action stm32_lptim_cnt_synapse_actions[] = { +static const enum counter_synapse_action stm32_lptim_cnt_synapse_actions[] = { /* Index must match with stm32_lptim_cnt_polarity[] (priv->polarity) */ [STM32_LPTIM_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE, [STM32_LPTIM_SYNAPSE_ACTION_FALLING_EDGE] = COUNTER_SYNAPSE_ACTION_FALLING_EDGE, diff --git a/drivers/counter/stm32-timer-cnt.c b/drivers/counter/stm32-timer-cnt.c index 75bc401fdd18..603b30ada839 100644 --- a/drivers/counter/stm32-timer-cnt.c +++ b/drivers/counter/stm32-timer-cnt.c @@ -50,7 +50,7 @@ enum stm32_count_function { STM32_COUNT_ENCODER_MODE_3, }; -static enum counter_count_function stm32_count_functions[] = { +static const enum counter_count_function stm32_count_functions[] = { [STM32_COUNT_SLAVE_MODE_DISABLED] = COUNTER_COUNT_FUNCTION_INCREASE, [STM32_COUNT_ENCODER_MODE_1] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A, [STM32_COUNT_ENCODER_MODE_2] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B, @@ -267,7 +267,7 @@ enum stm32_synapse_action { STM32_SYNAPSE_ACTION_BOTH_EDGES }; -static enum counter_synapse_action stm32_synapse_actions[] = { +static const enum counter_synapse_action stm32_synapse_actions[] = { [STM32_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE, [STM32_SYNAPSE_ACTION_BOTH_EDGES] = COUNTER_SYNAPSE_ACTION_BOTH_EDGES }; diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index e65e0a43be64..a5c5f70acfc9 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -19,6 +19,16 @@ config ACPI_CPPC_CPUFREQ If in doubt, say N. +config ACPI_CPPC_CPUFREQ_FIE + bool "Frequency Invariance support for CPPC cpufreq driver" + depends on ACPI_CPPC_CPUFREQ && GENERIC_ARCH_TOPOLOGY + default y + help + This extends frequency invariance support in the CPPC cpufreq driver, + by using CPPC delivered and reference performance counters. + + If in doubt, say N. + config ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM tristate "Allwinner nvmem based SUN50I CPUFreq driver" depends on ARCH_SUNXI diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index 2f769b1630c5..d4c27022b9c9 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -10,14 +10,18 @@ #define pr_fmt(fmt) "CPPC Cpufreq:" fmt +#include <linux/arch_topology.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/delay.h> #include <linux/cpu.h> #include <linux/cpufreq.h> #include <linux/dmi.h> +#include <linux/irq_work.h> +#include <linux/kthread.h> #include <linux/time.h> #include <linux/vmalloc.h> +#include <uapi/linux/sched/types.h> #include <asm/unaligned.h> @@ -57,6 +61,216 @@ static struct cppc_workaround_oem_info wa_info[] = { } }; +#ifdef CONFIG_ACPI_CPPC_CPUFREQ_FIE + +/* Frequency invariance support */ +struct cppc_freq_invariance { + int cpu; + struct irq_work irq_work; + struct kthread_work work; + struct cppc_perf_fb_ctrs prev_perf_fb_ctrs; + struct cppc_cpudata *cpu_data; +}; + +static DEFINE_PER_CPU(struct cppc_freq_invariance, cppc_freq_inv); +static struct kthread_worker *kworker_fie; + +static struct cpufreq_driver cppc_cpufreq_driver; +static unsigned int hisi_cppc_cpufreq_get_rate(unsigned int cpu); +static int cppc_perf_from_fbctrs(struct cppc_cpudata *cpu_data, + struct cppc_perf_fb_ctrs *fb_ctrs_t0, + struct cppc_perf_fb_ctrs *fb_ctrs_t1); + +/** + * cppc_scale_freq_workfn - CPPC arch_freq_scale updater for frequency invariance + * @work: The work item. + * + * The CPPC driver register itself with the topology core to provide its own + * implementation (cppc_scale_freq_tick()) of topology_scale_freq_tick() which + * gets called by the scheduler on every tick. + * + * Note that the arch specific counters have higher priority than CPPC counters, + * if available, though the CPPC driver doesn't need to have any special + * handling for that. + * + * On an invocation of cppc_scale_freq_tick(), we schedule an irq work (since we + * reach here from hard-irq context), which then schedules a normal work item + * and cppc_scale_freq_workfn() updates the per_cpu arch_freq_scale variable + * based on the counter updates since the last tick. + */ +static void cppc_scale_freq_workfn(struct kthread_work *work) +{ + struct cppc_freq_invariance *cppc_fi; + struct cppc_perf_fb_ctrs fb_ctrs = {0}; + struct cppc_cpudata *cpu_data; + unsigned long local_freq_scale; + u64 perf; + + cppc_fi = container_of(work, struct cppc_freq_invariance, work); + cpu_data = cppc_fi->cpu_data; + + if (cppc_get_perf_ctrs(cppc_fi->cpu, &fb_ctrs)) { + pr_warn("%s: failed to read perf counters\n", __func__); + return; + } + + perf = cppc_perf_from_fbctrs(cpu_data, &cppc_fi->prev_perf_fb_ctrs, + &fb_ctrs); + cppc_fi->prev_perf_fb_ctrs = fb_ctrs; + + perf <<= SCHED_CAPACITY_SHIFT; + local_freq_scale = div64_u64(perf, cpu_data->perf_caps.highest_perf); + + /* This can happen due to counter's overflow */ + if (unlikely(local_freq_scale > 1024)) + local_freq_scale = 1024; + + per_cpu(arch_freq_scale, cppc_fi->cpu) = local_freq_scale; +} + +static void cppc_irq_work(struct irq_work *irq_work) +{ + struct cppc_freq_invariance *cppc_fi; + + cppc_fi = container_of(irq_work, struct cppc_freq_invariance, irq_work); + kthread_queue_work(kworker_fie, &cppc_fi->work); +} + +static void cppc_scale_freq_tick(void) +{ + struct cppc_freq_invariance *cppc_fi = &per_cpu(cppc_freq_inv, smp_processor_id()); + + /* + * cppc_get_perf_ctrs() can potentially sleep, call that from the right + * context. + */ + irq_work_queue(&cppc_fi->irq_work); +} + +static struct scale_freq_data cppc_sftd = { + .source = SCALE_FREQ_SOURCE_CPPC, + .set_freq_scale = cppc_scale_freq_tick, +}; + +static void cppc_cpufreq_cpu_fie_init(struct cpufreq_policy *policy) +{ + struct cppc_freq_invariance *cppc_fi; + int cpu, ret; + + if (cppc_cpufreq_driver.get == hisi_cppc_cpufreq_get_rate) + return; + + for_each_cpu(cpu, policy->cpus) { + cppc_fi = &per_cpu(cppc_freq_inv, cpu); + cppc_fi->cpu = cpu; + cppc_fi->cpu_data = policy->driver_data; + kthread_init_work(&cppc_fi->work, cppc_scale_freq_workfn); + init_irq_work(&cppc_fi->irq_work, cppc_irq_work); + + ret = cppc_get_perf_ctrs(cpu, &cppc_fi->prev_perf_fb_ctrs); + if (ret) { + pr_warn("%s: failed to read perf counters for cpu:%d: %d\n", + __func__, cpu, ret); + + /* + * Don't abort if the CPU was offline while the driver + * was getting registered. + */ + if (cpu_online(cpu)) + return; + } + } + + /* Register for freq-invariance */ + topology_set_scale_freq_source(&cppc_sftd, policy->cpus); +} + +/* + * We free all the resources on policy's removal and not on CPU removal as the + * irq-work are per-cpu and the hotplug core takes care of flushing the pending + * irq-works (hint: smpcfd_dying_cpu()) on CPU hotplug. Even if the kthread-work + * fires on another CPU after the concerned CPU is removed, it won't harm. + * + * We just need to make sure to remove them all on policy->exit(). + */ +static void cppc_cpufreq_cpu_fie_exit(struct cpufreq_policy *policy) +{ + struct cppc_freq_invariance *cppc_fi; + int cpu; + + if (cppc_cpufreq_driver.get == hisi_cppc_cpufreq_get_rate) + return; + + /* policy->cpus will be empty here, use related_cpus instead */ + topology_clear_scale_freq_source(SCALE_FREQ_SOURCE_CPPC, policy->related_cpus); + + for_each_cpu(cpu, policy->related_cpus) { + cppc_fi = &per_cpu(cppc_freq_inv, cpu); + irq_work_sync(&cppc_fi->irq_work); + kthread_cancel_work_sync(&cppc_fi->work); + } +} + +static void __init cppc_freq_invariance_init(void) +{ + struct sched_attr attr = { + .size = sizeof(struct sched_attr), + .sched_policy = SCHED_DEADLINE, + .sched_nice = 0, + .sched_priority = 0, + /* + * Fake (unused) bandwidth; workaround to "fix" + * priority inheritance. + */ + .sched_runtime = 1000000, + .sched_deadline = 10000000, + .sched_period = 10000000, + }; + int ret; + + if (cppc_cpufreq_driver.get == hisi_cppc_cpufreq_get_rate) + return; + + kworker_fie = kthread_create_worker(0, "cppc_fie"); + if (IS_ERR(kworker_fie)) + return; + + ret = sched_setattr_nocheck(kworker_fie->task, &attr); + if (ret) { + pr_warn("%s: failed to set SCHED_DEADLINE: %d\n", __func__, + ret); + kthread_destroy_worker(kworker_fie); + return; + } +} + +static void cppc_freq_invariance_exit(void) +{ + if (cppc_cpufreq_driver.get == hisi_cppc_cpufreq_get_rate) + return; + + kthread_destroy_worker(kworker_fie); + kworker_fie = NULL; +} + +#else +static inline void cppc_cpufreq_cpu_fie_init(struct cpufreq_policy *policy) +{ +} + +static inline void cppc_cpufreq_cpu_fie_exit(struct cpufreq_policy *policy) +{ +} + +static inline void cppc_freq_invariance_init(void) +{ +} + +static inline void cppc_freq_invariance_exit(void) +{ +} +#endif /* CONFIG_ACPI_CPPC_CPUFREQ_FIE */ + /* Callback function used to retrieve the max frequency from DMI */ static void cppc_find_dmi_mhz(const struct dmi_header *dm, void *private) { @@ -182,27 +396,6 @@ static int cppc_verify_policy(struct cpufreq_policy_data *policy) return 0; } -static void cppc_cpufreq_stop_cpu(struct cpufreq_policy *policy) -{ - struct cppc_cpudata *cpu_data = policy->driver_data; - struct cppc_perf_caps *caps = &cpu_data->perf_caps; - unsigned int cpu = policy->cpu; - int ret; - - cpu_data->perf_ctrls.desired_perf = caps->lowest_perf; - - ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls); - if (ret) - pr_debug("Err setting perf value:%d on CPU:%d. ret:%d\n", - caps->lowest_perf, cpu, ret); - - /* Remove CPU node from list and free driver data for policy */ - free_cpumask_var(cpu_data->shared_cpu_map); - list_del(&cpu_data->node); - kfree(policy->driver_data); - policy->driver_data = NULL; -} - /* * The PCC subspace describes the rate at which platform can accept commands * on the shared PCC channel (including READs which do not count towards freq @@ -277,6 +470,16 @@ out: return NULL; } +static void cppc_cpufreq_put_cpu_data(struct cpufreq_policy *policy) +{ + struct cppc_cpudata *cpu_data = policy->driver_data; + + list_del(&cpu_data->node); + free_cpumask_var(cpu_data->shared_cpu_map); + kfree(cpu_data); + policy->driver_data = NULL; +} + static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) { unsigned int cpu = policy->cpu; @@ -330,7 +533,8 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) default: pr_debug("Unsupported CPU co-ord type: %d\n", policy->shared_type); - return -EFAULT; + ret = -EFAULT; + goto out; } /* @@ -345,13 +549,40 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) cpu_data->perf_ctrls.desired_perf = caps->highest_perf; ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls); - if (ret) + if (ret) { pr_debug("Err setting perf value:%d on CPU:%d. ret:%d\n", caps->highest_perf, cpu, ret); + goto out; + } + + cppc_cpufreq_cpu_fie_init(policy); + return 0; +out: + cppc_cpufreq_put_cpu_data(policy); return ret; } +static int cppc_cpufreq_cpu_exit(struct cpufreq_policy *policy) +{ + struct cppc_cpudata *cpu_data = policy->driver_data; + struct cppc_perf_caps *caps = &cpu_data->perf_caps; + unsigned int cpu = policy->cpu; + int ret; + + cppc_cpufreq_cpu_fie_exit(policy); + + cpu_data->perf_ctrls.desired_perf = caps->lowest_perf; + + ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls); + if (ret) + pr_debug("Err setting perf value:%d on CPU:%d. ret:%d\n", + caps->lowest_perf, cpu, ret); + + cppc_cpufreq_put_cpu_data(policy); + return 0; +} + static inline u64 get_delta(u64 t1, u64 t0) { if (t1 > t0 || t0 > ~(u32)0) @@ -360,28 +591,25 @@ static inline u64 get_delta(u64 t1, u64 t0) return (u32)t1 - (u32)t0; } -static int cppc_get_rate_from_fbctrs(struct cppc_cpudata *cpu_data, - struct cppc_perf_fb_ctrs fb_ctrs_t0, - struct cppc_perf_fb_ctrs fb_ctrs_t1) +static int cppc_perf_from_fbctrs(struct cppc_cpudata *cpu_data, + struct cppc_perf_fb_ctrs *fb_ctrs_t0, + struct cppc_perf_fb_ctrs *fb_ctrs_t1) { u64 delta_reference, delta_delivered; - u64 reference_perf, delivered_perf; + u64 reference_perf; - reference_perf = fb_ctrs_t0.reference_perf; + reference_perf = fb_ctrs_t0->reference_perf; - delta_reference = get_delta(fb_ctrs_t1.reference, - fb_ctrs_t0.reference); - delta_delivered = get_delta(fb_ctrs_t1.delivered, - fb_ctrs_t0.delivered); + delta_reference = get_delta(fb_ctrs_t1->reference, + fb_ctrs_t0->reference); + delta_delivered = get_delta(fb_ctrs_t1->delivered, + fb_ctrs_t0->delivered); - /* Check to avoid divide-by zero */ - if (delta_reference || delta_delivered) - delivered_perf = (reference_perf * delta_delivered) / - delta_reference; - else - delivered_perf = cpu_data->perf_ctrls.desired_perf; + /* Check to avoid divide-by zero and invalid delivered_perf */ + if (!delta_reference || !delta_delivered) + return cpu_data->perf_ctrls.desired_perf; - return cppc_cpufreq_perf_to_khz(cpu_data, delivered_perf); + return (reference_perf * delta_delivered) / delta_reference; } static unsigned int cppc_cpufreq_get_rate(unsigned int cpu) @@ -389,6 +617,7 @@ static unsigned int cppc_cpufreq_get_rate(unsigned int cpu) struct cppc_perf_fb_ctrs fb_ctrs_t0 = {0}, fb_ctrs_t1 = {0}; struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); struct cppc_cpudata *cpu_data = policy->driver_data; + u64 delivered_perf; int ret; cpufreq_cpu_put(policy); @@ -403,7 +632,10 @@ static unsigned int cppc_cpufreq_get_rate(unsigned int cpu) if (ret) return ret; - return cppc_get_rate_from_fbctrs(cpu_data, fb_ctrs_t0, fb_ctrs_t1); + delivered_perf = cppc_perf_from_fbctrs(cpu_data, &fb_ctrs_t0, + &fb_ctrs_t1); + + return cppc_cpufreq_perf_to_khz(cpu_data, delivered_perf); } static int cppc_cpufreq_set_boost(struct cpufreq_policy *policy, int state) @@ -451,7 +683,7 @@ static struct cpufreq_driver cppc_cpufreq_driver = { .target = cppc_cpufreq_set_target, .get = cppc_cpufreq_get_rate, .init = cppc_cpufreq_cpu_init, - .stop_cpu = cppc_cpufreq_stop_cpu, + .exit = cppc_cpufreq_cpu_exit, .set_boost = cppc_cpufreq_set_boost, .attr = cppc_cpufreq_attr, .name = "cppc_cpufreq", @@ -504,14 +736,21 @@ static void cppc_check_hisi_workaround(void) static int __init cppc_cpufreq_init(void) { + int ret; + if ((acpi_disabled) || !acpi_cpc_valid()) return -ENODEV; INIT_LIST_HEAD(&cpu_data_list); cppc_check_hisi_workaround(); + cppc_freq_invariance_init(); + + ret = cpufreq_register_driver(&cppc_cpufreq_driver); + if (ret) + cppc_freq_invariance_exit(); - return cpufreq_register_driver(&cppc_cpufreq_driver); + return ret; } static inline void free_cpu_data(void) @@ -529,6 +768,7 @@ static inline void free_cpu_data(void) static void __exit cppc_cpufreq_exit(void) { cpufreq_unregister_driver(&cppc_cpufreq_driver); + cppc_freq_invariance_exit(); free_cpu_data(); } diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 5e07065ec22f..bef7528aecd3 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -15,7 +15,7 @@ * Machines for which the cpufreq device is *always* created, mostly used for * platforms using "operating-points" (V1) property. */ -static const struct of_device_id whitelist[] __initconst = { +static const struct of_device_id allowlist[] __initconst = { { .compatible = "allwinner,sun4i-a10", }, { .compatible = "allwinner,sun5i-a10s", }, { .compatible = "allwinner,sun5i-a13", }, @@ -100,7 +100,7 @@ static const struct of_device_id whitelist[] __initconst = { * Machines for which the cpufreq device is *not* created, mostly used for * platforms using "operating-points-v2" property. */ -static const struct of_device_id blacklist[] __initconst = { +static const struct of_device_id blocklist[] __initconst = { { .compatible = "allwinner,sun50i-h6", }, { .compatible = "arm,vexpress", }, @@ -126,6 +126,7 @@ static const struct of_device_id blacklist[] __initconst = { { .compatible = "mediatek,mt8173", }, { .compatible = "mediatek,mt8176", }, { .compatible = "mediatek,mt8183", }, + { .compatible = "mediatek,mt8365", }, { .compatible = "mediatek,mt8516", }, { .compatible = "nvidia,tegra20", }, @@ -137,6 +138,7 @@ static const struct of_device_id blacklist[] __initconst = { { .compatible = "qcom,msm8996", }, { .compatible = "qcom,qcs404", }, { .compatible = "qcom,sc7180", }, + { .compatible = "qcom,sc7280", }, { .compatible = "qcom,sdm845", }, { .compatible = "st,stih407", }, @@ -177,13 +179,13 @@ static int __init cpufreq_dt_platdev_init(void) if (!np) return -ENODEV; - match = of_match_node(whitelist, np); + match = of_match_node(allowlist, np); if (match) { data = match->data; goto create_pdev; } - if (cpu0_node_has_opp_v2_prop() && !of_match_node(blacklist, np)) + if (cpu0_node_has_opp_v2_prop() && !of_match_node(blocklist, np)) goto create_pdev; of_node_put(np); diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index cbab834c37a0..45f3416988f1 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -524,6 +524,22 @@ void cpufreq_disable_fast_switch(struct cpufreq_policy *policy) } EXPORT_SYMBOL_GPL(cpufreq_disable_fast_switch); +static unsigned int __resolve_freq(struct cpufreq_policy *policy, + unsigned int target_freq, unsigned int relation) +{ + unsigned int idx; + + target_freq = clamp_val(target_freq, policy->min, policy->max); + + if (!cpufreq_driver->target_index) + return target_freq; + + idx = cpufreq_frequency_table_target(policy, target_freq, relation); + policy->cached_resolved_idx = idx; + policy->cached_target_freq = target_freq; + return policy->freq_table[idx].frequency; +} + /** * cpufreq_driver_resolve_freq - Map a target frequency to a driver-supported * one. @@ -538,22 +554,7 @@ EXPORT_SYMBOL_GPL(cpufreq_disable_fast_switch); unsigned int cpufreq_driver_resolve_freq(struct cpufreq_policy *policy, unsigned int target_freq) { - target_freq = clamp_val(target_freq, policy->min, policy->max); - policy->cached_target_freq = target_freq; - - if (cpufreq_driver->target_index) { - unsigned int idx; - - idx = cpufreq_frequency_table_target(policy, target_freq, - CPUFREQ_RELATION_L); - policy->cached_resolved_idx = idx; - return policy->freq_table[idx].frequency; - } - - if (cpufreq_driver->resolve_freq) - return cpufreq_driver->resolve_freq(policy, target_freq); - - return target_freq; + return __resolve_freq(policy, target_freq, CPUFREQ_RELATION_L); } EXPORT_SYMBOL_GPL(cpufreq_driver_resolve_freq); @@ -1606,9 +1607,6 @@ static int cpufreq_offline(unsigned int cpu) policy->cdev = NULL; } - if (cpufreq_driver->stop_cpu) - cpufreq_driver->stop_cpu(policy); - if (has_target()) cpufreq_exit_governor(policy); @@ -2234,13 +2232,11 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int relation) { unsigned int old_target_freq = target_freq; - int index; if (cpufreq_disabled()) return -ENODEV; - /* Make sure that target_freq is within supported range */ - target_freq = clamp_val(target_freq, policy->min, policy->max); + target_freq = __resolve_freq(policy, target_freq, relation); pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n", policy->cpu, target_freq, relation, old_target_freq); @@ -2261,9 +2257,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, if (!cpufreq_driver->target_index) return -EINVAL; - index = cpufreq_frequency_table_target(policy, target_freq, relation); - - return __target_index(policy, index); + return __target_index(policy, policy->cached_resolved_idx); } EXPORT_SYMBOL_GPL(__cpufreq_driver_target); diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 6012964df51b..bb4549959b11 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -2532,7 +2532,7 @@ static int intel_pstate_verify_policy(struct cpufreq_policy_data *policy) return 0; } -static int intel_pstate_cpu_offline(struct cpufreq_policy *policy) +static int intel_cpufreq_cpu_offline(struct cpufreq_policy *policy) { struct cpudata *cpu = all_cpu_data[policy->cpu]; @@ -2577,11 +2577,11 @@ static int intel_pstate_cpu_online(struct cpufreq_policy *policy) return 0; } -static void intel_pstate_stop_cpu(struct cpufreq_policy *policy) +static int intel_pstate_cpu_offline(struct cpufreq_policy *policy) { - pr_debug("CPU %d stopping\n", policy->cpu); - intel_pstate_clear_update_util_hook(policy->cpu); + + return intel_cpufreq_cpu_offline(policy); } static int intel_pstate_cpu_exit(struct cpufreq_policy *policy) @@ -2654,7 +2654,6 @@ static struct cpufreq_driver intel_pstate = { .resume = intel_pstate_resume, .init = intel_pstate_cpu_init, .exit = intel_pstate_cpu_exit, - .stop_cpu = intel_pstate_stop_cpu, .offline = intel_pstate_cpu_offline, .online = intel_pstate_cpu_online, .update_limits = intel_pstate_update_limits, @@ -2956,7 +2955,7 @@ static struct cpufreq_driver intel_cpufreq = { .fast_switch = intel_cpufreq_fast_switch, .init = intel_cpufreq_cpu_init, .exit = intel_cpufreq_cpu_exit, - .offline = intel_pstate_cpu_offline, + .offline = intel_cpufreq_cpu_offline, .online = intel_pstate_cpu_online, .suspend = intel_pstate_suspend, .resume = intel_pstate_resume, diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c index f2e491b25b07..87019d5a9547 100644 --- a/drivers/cpufreq/mediatek-cpufreq.c +++ b/drivers/cpufreq/mediatek-cpufreq.c @@ -537,6 +537,7 @@ static const struct of_device_id mtk_cpufreq_machines[] __initconst = { { .compatible = "mediatek,mt8173", }, { .compatible = "mediatek,mt8176", }, { .compatible = "mediatek,mt8183", }, + { .compatible = "mediatek,mt8365", }, { .compatible = "mediatek,mt8516", }, { } diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index e439b43c19eb..005600cef273 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@ -875,7 +875,15 @@ static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy) static int powernv_cpufreq_cpu_exit(struct cpufreq_policy *policy) { - /* timer is deleted in cpufreq_cpu_stop() */ + struct powernv_smp_call_data freq_data; + struct global_pstate_info *gpstates = policy->driver_data; + + freq_data.pstate_id = idx_to_pstate(powernv_pstate_info.min); + freq_data.gpstate_id = idx_to_pstate(powernv_pstate_info.min); + smp_call_function_single(policy->cpu, set_pstate, &freq_data, 1); + if (gpstates) + del_timer_sync(&gpstates->timer); + kfree(policy->driver_data); return 0; @@ -1007,18 +1015,6 @@ static struct notifier_block powernv_cpufreq_opal_nb = { .priority = 0, }; -static void powernv_cpufreq_stop_cpu(struct cpufreq_policy *policy) -{ - struct powernv_smp_call_data freq_data; - struct global_pstate_info *gpstates = policy->driver_data; - - freq_data.pstate_id = idx_to_pstate(powernv_pstate_info.min); - freq_data.gpstate_id = idx_to_pstate(powernv_pstate_info.min); - smp_call_function_single(policy->cpu, set_pstate, &freq_data, 1); - if (gpstates) - del_timer_sync(&gpstates->timer); -} - static unsigned int powernv_fast_switch(struct cpufreq_policy *policy, unsigned int target_freq) { @@ -1042,7 +1038,6 @@ static struct cpufreq_driver powernv_cpufreq_driver = { .target_index = powernv_cpufreq_target_index, .fast_switch = powernv_fast_switch, .get = powernv_cpufreq_get, - .stop_cpu = powernv_cpufreq_stop_cpu, .attr = powernv_cpu_freq_attr, }; diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c index c8a4364ad3c2..ec9a87ca2dbb 100644 --- a/drivers/cpufreq/scmi-cpufreq.c +++ b/drivers/cpufreq/scmi-cpufreq.c @@ -174,7 +174,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy) nr_opp = dev_pm_opp_get_opp_count(cpu_dev); if (nr_opp <= 0) { dev_err(cpu_dev, "%s: No OPPs for this device: %d\n", - __func__, ret); + __func__, nr_opp); ret = -ENODEV; goto out_free_opp; diff --git a/drivers/cpuidle/cpuidle-qcom-spm.c b/drivers/cpuidle/cpuidle-qcom-spm.c index adf91a6e4d7d..c0e7971da2da 100644 --- a/drivers/cpuidle/cpuidle-qcom-spm.c +++ b/drivers/cpuidle/cpuidle-qcom-spm.c @@ -87,6 +87,18 @@ static const struct spm_reg_data spm_reg_8974_8084_cpu = { .start_index[PM_SLEEP_MODE_SPC] = 3, }; +/* SPM register data for 8226 */ +static const struct spm_reg_data spm_reg_8226_cpu = { + .reg_offset = spm_reg_offset_v2_1, + .spm_cfg = 0x0, + .spm_dly = 0x3C102800, + .seq = { 0x60, 0x03, 0x60, 0x0B, 0x0F, 0x20, 0x10, 0x80, 0x30, 0x90, + 0x5B, 0x60, 0x03, 0x60, 0x3B, 0x76, 0x76, 0x0B, 0x94, 0x5B, + 0x80, 0x10, 0x26, 0x30, 0x0F }, + .start_index[PM_SLEEP_MODE_STBY] = 0, + .start_index[PM_SLEEP_MODE_SPC] = 5, +}; + static const u8 spm_reg_offset_v1_1[SPM_REG_NR] = { [SPM_REG_CFG] = 0x08, [SPM_REG_SPM_CTL] = 0x20, @@ -259,6 +271,8 @@ static struct spm_driver_data *spm_get_drv(struct platform_device *pdev, } static const struct of_device_id spm_match_table[] = { + { .compatible = "qcom,msm8226-saw2-v2.1-cpu", + .data = &spm_reg_8226_cpu }, { .compatible = "qcom,msm8974-saw2-v2.1-cpu", .data = &spm_reg_8974_8084_cpu }, { .compatible = "qcom,apq8084-saw2-v2.1-cpu", diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index ebcec460c045..51690e73153a 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -267,14 +267,14 @@ config CRYPTO_DEV_NIAGARA2 checksumming, and raw copies. config CRYPTO_DEV_SL3516 - tristate "Stormlink SL3516 crypto offloader" - depends on HAS_IOMEM + tristate "Storlink SL3516 crypto offloader" + depends on ARCH_GEMINI || COMPILE_TEST + depends on HAS_IOMEM && PM select CRYPTO_SKCIPHER select CRYPTO_ENGINE select CRYPTO_ECB select CRYPTO_AES select HW_RANDOM - depends on PM help This option allows you to have support for SL3516 crypto offloader. diff --git a/drivers/crypto/gemini/sl3516-ce-cipher.c b/drivers/crypto/gemini/sl3516-ce-cipher.c index b41c2f5fc495..c1c2b1d86663 100644 --- a/drivers/crypto/gemini/sl3516-ce-cipher.c +++ b/drivers/crypto/gemini/sl3516-ce-cipher.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * sl3516-ce-cipher.c - hardware cryptographic offloader for Stormlink SL3516 SoC + * sl3516-ce-cipher.c - hardware cryptographic offloader for Storlink SL3516 SoC * * Copyright (C) 2021 Corentin LABBE <clabbe@baylibre.com> * diff --git a/drivers/crypto/gemini/sl3516-ce-core.c b/drivers/crypto/gemini/sl3516-ce-core.c index da6cd529a6c0..b7524b649068 100644 --- a/drivers/crypto/gemini/sl3516-ce-core.c +++ b/drivers/crypto/gemini/sl3516-ce-core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * sl3516-ce-core.c - hardware cryptographic offloader for Stormlink SL3516 SoC + * sl3516-ce-core.c - hardware cryptographic offloader for Storlink SL3516 SoC * * Copyright (C) 2021 Corentin Labbe <clabbe@baylibre.com> * diff --git a/drivers/crypto/hisilicon/sec2/sec_main.c b/drivers/crypto/hisilicon/sec2/sec_main.c index d120ce3e34ed..490db7bccf61 100644 --- a/drivers/crypto/hisilicon/sec2/sec_main.c +++ b/drivers/crypto/hisilicon/sec2/sec_main.c @@ -364,6 +364,9 @@ static void sec_close_sva_prefetch(struct hisi_qm *qm) u32 val; int ret; + if (qm->ver < QM_HW_V3) + return; + val = readl_relaxed(qm->io_base + SEC_PREFETCH_CFG); val |= SEC_PREFETCH_DISABLE; writel(val, qm->io_base + SEC_PREFETCH_CFG); diff --git a/drivers/crypto/omap-crypto.c b/drivers/crypto/omap-crypto.c index 94b2dba90f0d..31bdb1d76d11 100644 --- a/drivers/crypto/omap-crypto.c +++ b/drivers/crypto/omap-crypto.c @@ -183,8 +183,7 @@ static void omap_crypto_copy_data(struct scatterlist *src, memcpy(dstb, srcb, amt); - if (!PageSlab(sg_page(dst))) - flush_kernel_dcache_page(sg_page(dst)); + flush_dcache_page(sg_page(dst)); kunmap_atomic(srcb); kunmap_atomic(dstb); diff --git a/drivers/crypto/qat/qat_common/adf_ctl_drv.c b/drivers/crypto/qat/qat_common/adf_ctl_drv.c index 96b437bfe3de..6f64aa693146 100644 --- a/drivers/crypto/qat/qat_common/adf_ctl_drv.c +++ b/drivers/crypto/qat/qat_common/adf_ctl_drv.c @@ -406,7 +406,7 @@ static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) ret = adf_ctl_ioctl_get_status(fp, cmd, arg); break; default: - pr_err("QAT: Invalid ioctl\n"); + pr_err_ratelimited("QAT: Invalid ioctl %d\n", cmd); ret = -EFAULT; break; } diff --git a/drivers/cxl/Kconfig b/drivers/cxl/Kconfig index 97dc4d751651..e6de221cc568 100644 --- a/drivers/cxl/Kconfig +++ b/drivers/cxl/Kconfig @@ -15,21 +15,17 @@ if CXL_BUS config CXL_MEM tristate "CXL.mem: Memory Devices" + default CXL_BUS help The CXL.mem protocol allows a device to act as a provider of "System RAM" and/or "Persistent Memory" that is fully coherent as if the memory was attached to the typical CPU memory controller. - Say 'y/m' to enable a driver (named "cxl_mem.ko" when built as - a module) that will attach to CXL.mem devices for - configuration, provisioning, and health monitoring. This - driver is required for dynamic provisioning of CXL.mem - attached memory which is a prerequisite for persistent memory - support. Typically volatile memory is mapped by platform - firmware and included in the platform memory map, but in some - cases the OS is responsible for mapping that memory. See - Chapter 2.3 Type 3 CXL Device in the CXL 2.0 specification. + Say 'y/m' to enable a driver that will attach to CXL.mem devices for + configuration and management primarily via the mailbox interface. See + Chapter 2.3 Type 3 CXL Device in the CXL 2.0 specification for more + details. If unsure say 'm'. @@ -50,4 +46,33 @@ config CXL_MEM_RAW_COMMANDS potential impact to memory currently in use by the kernel. If developing CXL hardware or the driver say Y, otherwise say N. + +config CXL_ACPI + tristate "CXL ACPI: Platform Support" + depends on ACPI + default CXL_BUS + help + Enable support for host managed device memory (HDM) resources + published by a platform's ACPI CXL memory layout description. See + Chapter 9.14.1 CXL Early Discovery Table (CEDT) in the CXL 2.0 + specification, and CXL Fixed Memory Window Structures (CEDT.CFMWS) + (https://www.computeexpresslink.org/spec-landing). The CXL core + consumes these resource to publish the root of a cxl_port decode + hierarchy to map regions that represent System RAM, or Persistent + Memory regions to be managed by LIBNVDIMM. + + If unsure say 'm'. + +config CXL_PMEM + tristate "CXL PMEM: Persistent Memory Support" + depends on LIBNVDIMM + default CXL_BUS + help + In addition to typical memory resources a platform may also advertise + support for persistent memory attached via CXL. This support is + managed via a bridge driver from CXL to the LIBNVDIMM system + subsystem. Say 'y/m' to enable support for enumerating and + provisioning the persistent memory capacity of CXL memory expanders. + + If unsure say 'm'. endif diff --git a/drivers/cxl/Makefile b/drivers/cxl/Makefile index a314a1891f4d..32954059b37b 100644 --- a/drivers/cxl/Makefile +++ b/drivers/cxl/Makefile @@ -1,7 +1,11 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_CXL_BUS) += cxl_bus.o -obj-$(CONFIG_CXL_MEM) += cxl_mem.o +obj-$(CONFIG_CXL_BUS) += cxl_core.o +obj-$(CONFIG_CXL_MEM) += cxl_pci.o +obj-$(CONFIG_CXL_ACPI) += cxl_acpi.o +obj-$(CONFIG_CXL_PMEM) += cxl_pmem.o ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=CXL -cxl_bus-y := bus.o -cxl_mem-y := mem.o +cxl_core-y := core.o +cxl_pci-y := pci.o +cxl_acpi-y := acpi.o +cxl_pmem-y := pmem.o diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c new file mode 100644 index 000000000000..8ae89273f58e --- /dev/null +++ b/drivers/cxl/acpi.c @@ -0,0 +1,434 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2021 Intel Corporation. All rights reserved. */ +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/acpi.h> +#include <linux/pci.h> +#include "cxl.h" + +static struct acpi_table_header *acpi_cedt; + +/* Encode defined in CXL 2.0 8.2.5.12.7 HDM Decoder Control Register */ +#define CFMWS_INTERLEAVE_WAYS(x) (1 << (x)->interleave_ways) +#define CFMWS_INTERLEAVE_GRANULARITY(x) ((x)->granularity + 8) + +static unsigned long cfmws_to_decoder_flags(int restrictions) +{ + unsigned long flags = 0; + + if (restrictions & ACPI_CEDT_CFMWS_RESTRICT_TYPE2) + flags |= CXL_DECODER_F_TYPE2; + if (restrictions & ACPI_CEDT_CFMWS_RESTRICT_TYPE3) + flags |= CXL_DECODER_F_TYPE3; + if (restrictions & ACPI_CEDT_CFMWS_RESTRICT_VOLATILE) + flags |= CXL_DECODER_F_RAM; + if (restrictions & ACPI_CEDT_CFMWS_RESTRICT_PMEM) + flags |= CXL_DECODER_F_PMEM; + if (restrictions & ACPI_CEDT_CFMWS_RESTRICT_FIXED) + flags |= CXL_DECODER_F_LOCK; + + return flags; +} + +static int cxl_acpi_cfmws_verify(struct device *dev, + struct acpi_cedt_cfmws *cfmws) +{ + int expected_len; + + if (cfmws->interleave_arithmetic != ACPI_CEDT_CFMWS_ARITHMETIC_MODULO) { + dev_err(dev, "CFMWS Unsupported Interleave Arithmetic\n"); + return -EINVAL; + } + + if (!IS_ALIGNED(cfmws->base_hpa, SZ_256M)) { + dev_err(dev, "CFMWS Base HPA not 256MB aligned\n"); + return -EINVAL; + } + + if (!IS_ALIGNED(cfmws->window_size, SZ_256M)) { + dev_err(dev, "CFMWS Window Size not 256MB aligned\n"); + return -EINVAL; + } + + expected_len = struct_size((cfmws), interleave_targets, + CFMWS_INTERLEAVE_WAYS(cfmws)); + + if (cfmws->header.length < expected_len) { + dev_err(dev, "CFMWS length %d less than expected %d\n", + cfmws->header.length, expected_len); + return -EINVAL; + } + + if (cfmws->header.length > expected_len) + dev_dbg(dev, "CFMWS length %d greater than expected %d\n", + cfmws->header.length, expected_len); + + return 0; +} + +static void cxl_add_cfmws_decoders(struct device *dev, + struct cxl_port *root_port) +{ + struct acpi_cedt_cfmws *cfmws; + struct cxl_decoder *cxld; + acpi_size len, cur = 0; + void *cedt_subtable; + unsigned long flags; + int rc; + + len = acpi_cedt->length - sizeof(*acpi_cedt); + cedt_subtable = acpi_cedt + 1; + + while (cur < len) { + struct acpi_cedt_header *c = cedt_subtable + cur; + + if (c->type != ACPI_CEDT_TYPE_CFMWS) { + cur += c->length; + continue; + } + + cfmws = cedt_subtable + cur; + + if (cfmws->header.length < sizeof(*cfmws)) { + dev_warn_once(dev, + "CFMWS entry skipped:invalid length:%u\n", + cfmws->header.length); + cur += c->length; + continue; + } + + rc = cxl_acpi_cfmws_verify(dev, cfmws); + if (rc) { + dev_err(dev, "CFMWS range %#llx-%#llx not registered\n", + cfmws->base_hpa, cfmws->base_hpa + + cfmws->window_size - 1); + cur += c->length; + continue; + } + + flags = cfmws_to_decoder_flags(cfmws->restrictions); + cxld = devm_cxl_add_decoder(dev, root_port, + CFMWS_INTERLEAVE_WAYS(cfmws), + cfmws->base_hpa, cfmws->window_size, + CFMWS_INTERLEAVE_WAYS(cfmws), + CFMWS_INTERLEAVE_GRANULARITY(cfmws), + CXL_DECODER_EXPANDER, + flags); + + if (IS_ERR(cxld)) { + dev_err(dev, "Failed to add decoder for %#llx-%#llx\n", + cfmws->base_hpa, cfmws->base_hpa + + cfmws->window_size - 1); + } else { + dev_dbg(dev, "add: %s range %#llx-%#llx\n", + dev_name(&cxld->dev), cfmws->base_hpa, + cfmws->base_hpa + cfmws->window_size - 1); + } + cur += c->length; + } +} + +static struct acpi_cedt_chbs *cxl_acpi_match_chbs(struct device *dev, u32 uid) +{ + struct acpi_cedt_chbs *chbs, *chbs_match = NULL; + acpi_size len, cur = 0; + void *cedt_subtable; + + len = acpi_cedt->length - sizeof(*acpi_cedt); + cedt_subtable = acpi_cedt + 1; + + while (cur < len) { + struct acpi_cedt_header *c = cedt_subtable + cur; + + if (c->type != ACPI_CEDT_TYPE_CHBS) { + cur += c->length; + continue; + } + + chbs = cedt_subtable + cur; + + if (chbs->header.length < sizeof(*chbs)) { + dev_warn_once(dev, + "CHBS entry skipped: invalid length:%u\n", + chbs->header.length); + cur += c->length; + continue; + } + + if (chbs->uid != uid) { + cur += c->length; + continue; + } + + if (chbs_match) { + dev_warn_once(dev, + "CHBS entry skipped: duplicate UID:%u\n", + uid); + cur += c->length; + continue; + } + + chbs_match = chbs; + cur += c->length; + } + + return chbs_match ? chbs_match : ERR_PTR(-ENODEV); +} + +static resource_size_t get_chbcr(struct acpi_cedt_chbs *chbs) +{ + return IS_ERR(chbs) ? CXL_RESOURCE_NONE : chbs->base; +} + +struct cxl_walk_context { + struct device *dev; + struct pci_bus *root; + struct cxl_port *port; + int error; + int count; +}; + +static int match_add_root_ports(struct pci_dev *pdev, void *data) +{ + struct cxl_walk_context *ctx = data; + struct pci_bus *root_bus = ctx->root; + struct cxl_port *port = ctx->port; + int type = pci_pcie_type(pdev); + struct device *dev = ctx->dev; + u32 lnkcap, port_num; + int rc; + + if (pdev->bus != root_bus) + return 0; + if (!pci_is_pcie(pdev)) + return 0; + if (type != PCI_EXP_TYPE_ROOT_PORT) + return 0; + if (pci_read_config_dword(pdev, pci_pcie_cap(pdev) + PCI_EXP_LNKCAP, + &lnkcap) != PCIBIOS_SUCCESSFUL) + return 0; + + /* TODO walk DVSEC to find component register base */ + port_num = FIELD_GET(PCI_EXP_LNKCAP_PN, lnkcap); + rc = cxl_add_dport(port, &pdev->dev, port_num, CXL_RESOURCE_NONE); + if (rc) { + ctx->error = rc; + return rc; + } + ctx->count++; + + dev_dbg(dev, "add dport%d: %s\n", port_num, dev_name(&pdev->dev)); + + return 0; +} + +static struct cxl_dport *find_dport_by_dev(struct cxl_port *port, struct device *dev) +{ + struct cxl_dport *dport; + + device_lock(&port->dev); + list_for_each_entry(dport, &port->dports, list) + if (dport->dport == dev) { + device_unlock(&port->dev); + return dport; + } + + device_unlock(&port->dev); + return NULL; +} + +static struct acpi_device *to_cxl_host_bridge(struct device *dev) +{ + struct acpi_device *adev = to_acpi_device(dev); + + if (strcmp(acpi_device_hid(adev), "ACPI0016") == 0) + return adev; + return NULL; +} + +/* + * A host bridge is a dport to a CFMWS decode and it is a uport to the + * dport (PCIe Root Ports) in the host bridge. + */ +static int add_host_bridge_uport(struct device *match, void *arg) +{ + struct acpi_device *bridge = to_cxl_host_bridge(match); + struct cxl_port *root_port = arg; + struct device *host = root_port->dev.parent; + struct acpi_pci_root *pci_root; + struct cxl_walk_context ctx; + struct cxl_decoder *cxld; + struct cxl_dport *dport; + struct cxl_port *port; + + if (!bridge) + return 0; + + pci_root = acpi_pci_find_root(bridge->handle); + if (!pci_root) + return -ENXIO; + + dport = find_dport_by_dev(root_port, match); + if (!dport) { + dev_dbg(host, "host bridge expected and not found\n"); + return -ENODEV; + } + + port = devm_cxl_add_port(host, match, dport->component_reg_phys, + root_port); + if (IS_ERR(port)) + return PTR_ERR(port); + dev_dbg(host, "%s: add: %s\n", dev_name(match), dev_name(&port->dev)); + + ctx = (struct cxl_walk_context){ + .dev = host, + .root = pci_root->bus, + .port = port, + }; + pci_walk_bus(pci_root->bus, match_add_root_ports, &ctx); + + if (ctx.count == 0) + return -ENODEV; + if (ctx.error) + return ctx.error; + + /* TODO: Scan CHBCR for HDM Decoder resources */ + + /* + * In the single-port host-bridge case there are no HDM decoders + * in the CHBCR and a 1:1 passthrough decode is implied. + */ + if (ctx.count == 1) { + cxld = devm_cxl_add_passthrough_decoder(host, port); + if (IS_ERR(cxld)) + return PTR_ERR(cxld); + + dev_dbg(host, "add: %s\n", dev_name(&cxld->dev)); + } + + return 0; +} + +static int add_host_bridge_dport(struct device *match, void *arg) +{ + int rc; + acpi_status status; + unsigned long long uid; + struct acpi_cedt_chbs *chbs; + struct cxl_port *root_port = arg; + struct device *host = root_port->dev.parent; + struct acpi_device *bridge = to_cxl_host_bridge(match); + + if (!bridge) + return 0; + + status = acpi_evaluate_integer(bridge->handle, METHOD_NAME__UID, NULL, + &uid); + if (status != AE_OK) { + dev_err(host, "unable to retrieve _UID of %s\n", + dev_name(match)); + return -ENODEV; + } + + chbs = cxl_acpi_match_chbs(host, uid); + if (IS_ERR(chbs)) + dev_dbg(host, "No CHBS found for Host Bridge: %s\n", + dev_name(match)); + + rc = cxl_add_dport(root_port, match, uid, get_chbcr(chbs)); + if (rc) { + dev_err(host, "failed to add downstream port: %s\n", + dev_name(match)); + return rc; + } + dev_dbg(host, "add dport%llu: %s\n", uid, dev_name(match)); + return 0; +} + +static int add_root_nvdimm_bridge(struct device *match, void *data) +{ + struct cxl_decoder *cxld; + struct cxl_port *root_port = data; + struct cxl_nvdimm_bridge *cxl_nvb; + struct device *host = root_port->dev.parent; + + if (!is_root_decoder(match)) + return 0; + + cxld = to_cxl_decoder(match); + if (!(cxld->flags & CXL_DECODER_F_PMEM)) + return 0; + + cxl_nvb = devm_cxl_add_nvdimm_bridge(host, root_port); + if (IS_ERR(cxl_nvb)) { + dev_dbg(host, "failed to register pmem\n"); + return PTR_ERR(cxl_nvb); + } + dev_dbg(host, "%s: add: %s\n", dev_name(&root_port->dev), + dev_name(&cxl_nvb->dev)); + return 1; +} + +static int cxl_acpi_probe(struct platform_device *pdev) +{ + int rc; + acpi_status status; + struct cxl_port *root_port; + struct device *host = &pdev->dev; + struct acpi_device *adev = ACPI_COMPANION(host); + + root_port = devm_cxl_add_port(host, host, CXL_RESOURCE_NONE, NULL); + if (IS_ERR(root_port)) + return PTR_ERR(root_port); + dev_dbg(host, "add: %s\n", dev_name(&root_port->dev)); + + status = acpi_get_table(ACPI_SIG_CEDT, 0, &acpi_cedt); + if (ACPI_FAILURE(status)) + return -ENXIO; + + rc = bus_for_each_dev(adev->dev.bus, NULL, root_port, + add_host_bridge_dport); + if (rc) + goto out; + + cxl_add_cfmws_decoders(host, root_port); + + /* + * Root level scanned with host-bridge as dports, now scan host-bridges + * for their role as CXL uports to their CXL-capable PCIe Root Ports. + */ + rc = bus_for_each_dev(adev->dev.bus, NULL, root_port, + add_host_bridge_uport); + if (rc) + goto out; + + if (IS_ENABLED(CONFIG_CXL_PMEM)) + rc = device_for_each_child(&root_port->dev, root_port, + add_root_nvdimm_bridge); + +out: + acpi_put_table(acpi_cedt); + if (rc < 0) + return rc; + return 0; +} + +static const struct acpi_device_id cxl_acpi_ids[] = { + { "ACPI0017", 0 }, + { "", 0 }, +}; +MODULE_DEVICE_TABLE(acpi, cxl_acpi_ids); + +static struct platform_driver cxl_acpi_driver = { + .probe = cxl_acpi_probe, + .driver = { + .name = KBUILD_MODNAME, + .acpi_match_table = cxl_acpi_ids, + }, +}; + +module_platform_driver(cxl_acpi_driver); +MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS(CXL); diff --git a/drivers/cxl/bus.c b/drivers/cxl/bus.c deleted file mode 100644 index 58f74796d525..000000000000 --- a/drivers/cxl/bus.c +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright(c) 2020 Intel Corporation. All rights reserved. */ -#include <linux/device.h> -#include <linux/module.h> - -/** - * DOC: cxl bus - * - * The CXL bus provides namespace for control devices and a rendezvous - * point for cross-device interleave coordination. - */ -struct bus_type cxl_bus_type = { - .name = "cxl", -}; -EXPORT_SYMBOL_GPL(cxl_bus_type); - -static __init int cxl_bus_init(void) -{ - return bus_register(&cxl_bus_type); -} - -static void cxl_bus_exit(void) -{ - bus_unregister(&cxl_bus_type); -} - -module_init(cxl_bus_init); -module_exit(cxl_bus_exit); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/cxl/core.c b/drivers/cxl/core.c new file mode 100644 index 000000000000..a2e4d54fc7bc --- /dev/null +++ b/drivers/cxl/core.c @@ -0,0 +1,1067 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2020 Intel Corporation. All rights reserved. */ +#include <linux/io-64-nonatomic-lo-hi.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/slab.h> +#include <linux/idr.h> +#include "cxl.h" +#include "mem.h" + +/** + * DOC: cxl core + * + * The CXL core provides a sysfs hierarchy for control devices and a rendezvous + * point for cross-device interleave coordination through cxl ports. + */ + +static DEFINE_IDA(cxl_port_ida); + +static ssize_t devtype_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%s\n", dev->type->name); +} +static DEVICE_ATTR_RO(devtype); + +static struct attribute *cxl_base_attributes[] = { + &dev_attr_devtype.attr, + NULL, +}; + +static struct attribute_group cxl_base_attribute_group = { + .attrs = cxl_base_attributes, +}; + +static ssize_t start_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct cxl_decoder *cxld = to_cxl_decoder(dev); + + return sysfs_emit(buf, "%#llx\n", cxld->range.start); +} +static DEVICE_ATTR_RO(start); + +static ssize_t size_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct cxl_decoder *cxld = to_cxl_decoder(dev); + + return sysfs_emit(buf, "%#llx\n", range_len(&cxld->range)); +} +static DEVICE_ATTR_RO(size); + +#define CXL_DECODER_FLAG_ATTR(name, flag) \ +static ssize_t name##_show(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct cxl_decoder *cxld = to_cxl_decoder(dev); \ + \ + return sysfs_emit(buf, "%s\n", \ + (cxld->flags & (flag)) ? "1" : "0"); \ +} \ +static DEVICE_ATTR_RO(name) + +CXL_DECODER_FLAG_ATTR(cap_pmem, CXL_DECODER_F_PMEM); +CXL_DECODER_FLAG_ATTR(cap_ram, CXL_DECODER_F_RAM); +CXL_DECODER_FLAG_ATTR(cap_type2, CXL_DECODER_F_TYPE2); +CXL_DECODER_FLAG_ATTR(cap_type3, CXL_DECODER_F_TYPE3); +CXL_DECODER_FLAG_ATTR(locked, CXL_DECODER_F_LOCK); + +static ssize_t target_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct cxl_decoder *cxld = to_cxl_decoder(dev); + + switch (cxld->target_type) { + case CXL_DECODER_ACCELERATOR: + return sysfs_emit(buf, "accelerator\n"); + case CXL_DECODER_EXPANDER: + return sysfs_emit(buf, "expander\n"); + } + return -ENXIO; +} +static DEVICE_ATTR_RO(target_type); + +static ssize_t target_list_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct cxl_decoder *cxld = to_cxl_decoder(dev); + ssize_t offset = 0; + int i, rc = 0; + + device_lock(dev); + for (i = 0; i < cxld->interleave_ways; i++) { + struct cxl_dport *dport = cxld->target[i]; + struct cxl_dport *next = NULL; + + if (!dport) + break; + + if (i + 1 < cxld->interleave_ways) + next = cxld->target[i + 1]; + rc = sysfs_emit_at(buf, offset, "%d%s", dport->port_id, + next ? "," : ""); + if (rc < 0) + break; + offset += rc; + } + device_unlock(dev); + + if (rc < 0) + return rc; + + rc = sysfs_emit_at(buf, offset, "\n"); + if (rc < 0) + return rc; + + return offset + rc; +} +static DEVICE_ATTR_RO(target_list); + +static struct attribute *cxl_decoder_base_attrs[] = { + &dev_attr_start.attr, + &dev_attr_size.attr, + &dev_attr_locked.attr, + &dev_attr_target_list.attr, + NULL, +}; + +static struct attribute_group cxl_decoder_base_attribute_group = { + .attrs = cxl_decoder_base_attrs, +}; + +static struct attribute *cxl_decoder_root_attrs[] = { + &dev_attr_cap_pmem.attr, + &dev_attr_cap_ram.attr, + &dev_attr_cap_type2.attr, + &dev_attr_cap_type3.attr, + NULL, +}; + +static struct attribute_group cxl_decoder_root_attribute_group = { + .attrs = cxl_decoder_root_attrs, +}; + +static const struct attribute_group *cxl_decoder_root_attribute_groups[] = { + &cxl_decoder_root_attribute_group, + &cxl_decoder_base_attribute_group, + &cxl_base_attribute_group, + NULL, +}; + +static struct attribute *cxl_decoder_switch_attrs[] = { + &dev_attr_target_type.attr, + NULL, +}; + +static struct attribute_group cxl_decoder_switch_attribute_group = { + .attrs = cxl_decoder_switch_attrs, +}; + +static const struct attribute_group *cxl_decoder_switch_attribute_groups[] = { + &cxl_decoder_switch_attribute_group, + &cxl_decoder_base_attribute_group, + &cxl_base_attribute_group, + NULL, +}; + +static void cxl_decoder_release(struct device *dev) +{ + struct cxl_decoder *cxld = to_cxl_decoder(dev); + struct cxl_port *port = to_cxl_port(dev->parent); + + ida_free(&port->decoder_ida, cxld->id); + kfree(cxld); +} + +static const struct device_type cxl_decoder_switch_type = { + .name = "cxl_decoder_switch", + .release = cxl_decoder_release, + .groups = cxl_decoder_switch_attribute_groups, +}; + +static const struct device_type cxl_decoder_root_type = { + .name = "cxl_decoder_root", + .release = cxl_decoder_release, + .groups = cxl_decoder_root_attribute_groups, +}; + +bool is_root_decoder(struct device *dev) +{ + return dev->type == &cxl_decoder_root_type; +} +EXPORT_SYMBOL_GPL(is_root_decoder); + +struct cxl_decoder *to_cxl_decoder(struct device *dev) +{ + if (dev_WARN_ONCE(dev, dev->type->release != cxl_decoder_release, + "not a cxl_decoder device\n")) + return NULL; + return container_of(dev, struct cxl_decoder, dev); +} +EXPORT_SYMBOL_GPL(to_cxl_decoder); + +static void cxl_dport_release(struct cxl_dport *dport) +{ + list_del(&dport->list); + put_device(dport->dport); + kfree(dport); +} + +static void cxl_port_release(struct device *dev) +{ + struct cxl_port *port = to_cxl_port(dev); + struct cxl_dport *dport, *_d; + + device_lock(dev); + list_for_each_entry_safe(dport, _d, &port->dports, list) + cxl_dport_release(dport); + device_unlock(dev); + ida_free(&cxl_port_ida, port->id); + kfree(port); +} + +static const struct attribute_group *cxl_port_attribute_groups[] = { + &cxl_base_attribute_group, + NULL, +}; + +static const struct device_type cxl_port_type = { + .name = "cxl_port", + .release = cxl_port_release, + .groups = cxl_port_attribute_groups, +}; + +struct cxl_port *to_cxl_port(struct device *dev) +{ + if (dev_WARN_ONCE(dev, dev->type != &cxl_port_type, + "not a cxl_port device\n")) + return NULL; + return container_of(dev, struct cxl_port, dev); +} + +static void unregister_port(void *_port) +{ + struct cxl_port *port = _port; + struct cxl_dport *dport; + + device_lock(&port->dev); + list_for_each_entry(dport, &port->dports, list) { + char link_name[CXL_TARGET_STRLEN]; + + if (snprintf(link_name, CXL_TARGET_STRLEN, "dport%d", + dport->port_id) >= CXL_TARGET_STRLEN) + continue; + sysfs_remove_link(&port->dev.kobj, link_name); + } + device_unlock(&port->dev); + device_unregister(&port->dev); +} + +static void cxl_unlink_uport(void *_port) +{ + struct cxl_port *port = _port; + + sysfs_remove_link(&port->dev.kobj, "uport"); +} + +static int devm_cxl_link_uport(struct device *host, struct cxl_port *port) +{ + int rc; + + rc = sysfs_create_link(&port->dev.kobj, &port->uport->kobj, "uport"); + if (rc) + return rc; + return devm_add_action_or_reset(host, cxl_unlink_uport, port); +} + +static struct cxl_port *cxl_port_alloc(struct device *uport, + resource_size_t component_reg_phys, + struct cxl_port *parent_port) +{ + struct cxl_port *port; + struct device *dev; + int rc; + + port = kzalloc(sizeof(*port), GFP_KERNEL); + if (!port) + return ERR_PTR(-ENOMEM); + + rc = ida_alloc(&cxl_port_ida, GFP_KERNEL); + if (rc < 0) + goto err; + port->id = rc; + + /* + * The top-level cxl_port "cxl_root" does not have a cxl_port as + * its parent and it does not have any corresponding component + * registers as its decode is described by a fixed platform + * description. + */ + dev = &port->dev; + if (parent_port) + dev->parent = &parent_port->dev; + else + dev->parent = uport; + + port->uport = uport; + port->component_reg_phys = component_reg_phys; + ida_init(&port->decoder_ida); + INIT_LIST_HEAD(&port->dports); + + device_initialize(dev); + device_set_pm_not_required(dev); + dev->bus = &cxl_bus_type; + dev->type = &cxl_port_type; + + return port; + +err: + kfree(port); + return ERR_PTR(rc); +} + +/** + * devm_cxl_add_port - register a cxl_port in CXL memory decode hierarchy + * @host: host device for devm operations + * @uport: "physical" device implementing this upstream port + * @component_reg_phys: (optional) for configurable cxl_port instances + * @parent_port: next hop up in the CXL memory decode hierarchy + */ +struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport, + resource_size_t component_reg_phys, + struct cxl_port *parent_port) +{ + struct cxl_port *port; + struct device *dev; + int rc; + + port = cxl_port_alloc(uport, component_reg_phys, parent_port); + if (IS_ERR(port)) + return port; + + dev = &port->dev; + if (parent_port) + rc = dev_set_name(dev, "port%d", port->id); + else + rc = dev_set_name(dev, "root%d", port->id); + if (rc) + goto err; + + rc = device_add(dev); + if (rc) + goto err; + + rc = devm_add_action_or_reset(host, unregister_port, port); + if (rc) + return ERR_PTR(rc); + + rc = devm_cxl_link_uport(host, port); + if (rc) + return ERR_PTR(rc); + + return port; + +err: + put_device(dev); + return ERR_PTR(rc); +} +EXPORT_SYMBOL_GPL(devm_cxl_add_port); + +static struct cxl_dport *find_dport(struct cxl_port *port, int id) +{ + struct cxl_dport *dport; + + device_lock_assert(&port->dev); + list_for_each_entry (dport, &port->dports, list) + if (dport->port_id == id) + return dport; + return NULL; +} + +static int add_dport(struct cxl_port *port, struct cxl_dport *new) +{ + struct cxl_dport *dup; + + device_lock(&port->dev); + dup = find_dport(port, new->port_id); + if (dup) + dev_err(&port->dev, + "unable to add dport%d-%s non-unique port id (%s)\n", + new->port_id, dev_name(new->dport), + dev_name(dup->dport)); + else + list_add_tail(&new->list, &port->dports); + device_unlock(&port->dev); + + return dup ? -EEXIST : 0; +} + +/** + * cxl_add_dport - append downstream port data to a cxl_port + * @port: the cxl_port that references this dport + * @dport_dev: firmware or PCI device representing the dport + * @port_id: identifier for this dport in a decoder's target list + * @component_reg_phys: optional location of CXL component registers + * + * Note that all allocations and links are undone by cxl_port deletion + * and release. + */ +int cxl_add_dport(struct cxl_port *port, struct device *dport_dev, int port_id, + resource_size_t component_reg_phys) +{ + char link_name[CXL_TARGET_STRLEN]; + struct cxl_dport *dport; + int rc; + + if (snprintf(link_name, CXL_TARGET_STRLEN, "dport%d", port_id) >= + CXL_TARGET_STRLEN) + return -EINVAL; + + dport = kzalloc(sizeof(*dport), GFP_KERNEL); + if (!dport) + return -ENOMEM; + + INIT_LIST_HEAD(&dport->list); + dport->dport = get_device(dport_dev); + dport->port_id = port_id; + dport->component_reg_phys = component_reg_phys; + dport->port = port; + + rc = add_dport(port, dport); + if (rc) + goto err; + + rc = sysfs_create_link(&port->dev.kobj, &dport_dev->kobj, link_name); + if (rc) + goto err; + + return 0; +err: + cxl_dport_release(dport); + return rc; +} +EXPORT_SYMBOL_GPL(cxl_add_dport); + +static struct cxl_decoder * +cxl_decoder_alloc(struct cxl_port *port, int nr_targets, resource_size_t base, + resource_size_t len, int interleave_ways, + int interleave_granularity, enum cxl_decoder_type type, + unsigned long flags) +{ + struct cxl_decoder *cxld; + struct device *dev; + int rc = 0; + + if (interleave_ways < 1) + return ERR_PTR(-EINVAL); + + device_lock(&port->dev); + if (list_empty(&port->dports)) + rc = -EINVAL; + device_unlock(&port->dev); + if (rc) + return ERR_PTR(rc); + + cxld = kzalloc(struct_size(cxld, target, nr_targets), GFP_KERNEL); + if (!cxld) + return ERR_PTR(-ENOMEM); + + rc = ida_alloc(&port->decoder_ida, GFP_KERNEL); + if (rc < 0) + goto err; + + *cxld = (struct cxl_decoder) { + .id = rc, + .range = { + .start = base, + .end = base + len - 1, + }, + .flags = flags, + .interleave_ways = interleave_ways, + .interleave_granularity = interleave_granularity, + .target_type = type, + }; + + /* handle implied target_list */ + if (interleave_ways == 1) + cxld->target[0] = + list_first_entry(&port->dports, struct cxl_dport, list); + dev = &cxld->dev; + device_initialize(dev); + device_set_pm_not_required(dev); + dev->parent = &port->dev; + dev->bus = &cxl_bus_type; + + /* root ports do not have a cxl_port_type parent */ + if (port->dev.parent->type == &cxl_port_type) + dev->type = &cxl_decoder_switch_type; + else + dev->type = &cxl_decoder_root_type; + + return cxld; +err: + kfree(cxld); + return ERR_PTR(rc); +} + +static void unregister_dev(void *dev) +{ + device_unregister(dev); +} + +struct cxl_decoder * +devm_cxl_add_decoder(struct device *host, struct cxl_port *port, int nr_targets, + resource_size_t base, resource_size_t len, + int interleave_ways, int interleave_granularity, + enum cxl_decoder_type type, unsigned long flags) +{ + struct cxl_decoder *cxld; + struct device *dev; + int rc; + + cxld = cxl_decoder_alloc(port, nr_targets, base, len, interleave_ways, + interleave_granularity, type, flags); + if (IS_ERR(cxld)) + return cxld; + + dev = &cxld->dev; + rc = dev_set_name(dev, "decoder%d.%d", port->id, cxld->id); + if (rc) + goto err; + + rc = device_add(dev); + if (rc) + goto err; + + rc = devm_add_action_or_reset(host, unregister_dev, dev); + if (rc) + return ERR_PTR(rc); + return cxld; + +err: + put_device(dev); + return ERR_PTR(rc); +} +EXPORT_SYMBOL_GPL(devm_cxl_add_decoder); + +/** + * cxl_probe_component_regs() - Detect CXL Component register blocks + * @dev: Host device of the @base mapping + * @base: Mapping containing the HDM Decoder Capability Header + * @map: Map object describing the register block information found + * + * See CXL 2.0 8.2.4 Component Register Layout and Definition + * See CXL 2.0 8.2.5.5 CXL Device Register Interface + * + * Probe for component register information and return it in map object. + */ +void cxl_probe_component_regs(struct device *dev, void __iomem *base, + struct cxl_component_reg_map *map) +{ + int cap, cap_count; + u64 cap_array; + + *map = (struct cxl_component_reg_map) { 0 }; + + /* + * CXL.cache and CXL.mem registers are at offset 0x1000 as defined in + * CXL 2.0 8.2.4 Table 141. + */ + base += CXL_CM_OFFSET; + + cap_array = readq(base + CXL_CM_CAP_HDR_OFFSET); + + if (FIELD_GET(CXL_CM_CAP_HDR_ID_MASK, cap_array) != CM_CAP_HDR_CAP_ID) { + dev_err(dev, + "Couldn't locate the CXL.cache and CXL.mem capability array header./n"); + return; + } + + /* It's assumed that future versions will be backward compatible */ + cap_count = FIELD_GET(CXL_CM_CAP_HDR_ARRAY_SIZE_MASK, cap_array); + + for (cap = 1; cap <= cap_count; cap++) { + void __iomem *register_block; + u32 hdr; + int decoder_cnt; + u16 cap_id, offset; + u32 length; + + hdr = readl(base + cap * 0x4); + + cap_id = FIELD_GET(CXL_CM_CAP_HDR_ID_MASK, hdr); + offset = FIELD_GET(CXL_CM_CAP_PTR_MASK, hdr); + register_block = base + offset; + + switch (cap_id) { + case CXL_CM_CAP_CAP_ID_HDM: + dev_dbg(dev, "found HDM decoder capability (0x%x)\n", + offset); + + hdr = readl(register_block); + + decoder_cnt = cxl_hdm_decoder_count(hdr); + length = 0x20 * decoder_cnt + 0x10; + + map->hdm_decoder.valid = true; + map->hdm_decoder.offset = CXL_CM_OFFSET + offset; + map->hdm_decoder.size = length; + break; + default: + dev_dbg(dev, "Unknown CM cap ID: %d (0x%x)\n", cap_id, + offset); + break; + } + } +} +EXPORT_SYMBOL_GPL(cxl_probe_component_regs); + +static void cxl_nvdimm_bridge_release(struct device *dev) +{ + struct cxl_nvdimm_bridge *cxl_nvb = to_cxl_nvdimm_bridge(dev); + + kfree(cxl_nvb); +} + +static const struct attribute_group *cxl_nvdimm_bridge_attribute_groups[] = { + &cxl_base_attribute_group, + NULL, +}; + +static const struct device_type cxl_nvdimm_bridge_type = { + .name = "cxl_nvdimm_bridge", + .release = cxl_nvdimm_bridge_release, + .groups = cxl_nvdimm_bridge_attribute_groups, +}; + +struct cxl_nvdimm_bridge *to_cxl_nvdimm_bridge(struct device *dev) +{ + if (dev_WARN_ONCE(dev, dev->type != &cxl_nvdimm_bridge_type, + "not a cxl_nvdimm_bridge device\n")) + return NULL; + return container_of(dev, struct cxl_nvdimm_bridge, dev); +} +EXPORT_SYMBOL_GPL(to_cxl_nvdimm_bridge); + +static struct cxl_nvdimm_bridge * +cxl_nvdimm_bridge_alloc(struct cxl_port *port) +{ + struct cxl_nvdimm_bridge *cxl_nvb; + struct device *dev; + + cxl_nvb = kzalloc(sizeof(*cxl_nvb), GFP_KERNEL); + if (!cxl_nvb) + return ERR_PTR(-ENOMEM); + + dev = &cxl_nvb->dev; + cxl_nvb->port = port; + cxl_nvb->state = CXL_NVB_NEW; + device_initialize(dev); + device_set_pm_not_required(dev); + dev->parent = &port->dev; + dev->bus = &cxl_bus_type; + dev->type = &cxl_nvdimm_bridge_type; + + return cxl_nvb; +} + +static void unregister_nvb(void *_cxl_nvb) +{ + struct cxl_nvdimm_bridge *cxl_nvb = _cxl_nvb; + bool flush; + + /* + * If the bridge was ever activated then there might be in-flight state + * work to flush. Once the state has been changed to 'dead' then no new + * work can be queued by user-triggered bind. + */ + device_lock(&cxl_nvb->dev); + flush = cxl_nvb->state != CXL_NVB_NEW; + cxl_nvb->state = CXL_NVB_DEAD; + device_unlock(&cxl_nvb->dev); + + /* + * Even though the device core will trigger device_release_driver() + * before the unregister, it does not know about the fact that + * cxl_nvdimm_bridge_driver defers ->remove() work. So, do the driver + * release not and flush it before tearing down the nvdimm device + * hierarchy. + */ + device_release_driver(&cxl_nvb->dev); + if (flush) + flush_work(&cxl_nvb->state_work); + device_unregister(&cxl_nvb->dev); +} + +struct cxl_nvdimm_bridge *devm_cxl_add_nvdimm_bridge(struct device *host, + struct cxl_port *port) +{ + struct cxl_nvdimm_bridge *cxl_nvb; + struct device *dev; + int rc; + + if (!IS_ENABLED(CONFIG_CXL_PMEM)) + return ERR_PTR(-ENXIO); + + cxl_nvb = cxl_nvdimm_bridge_alloc(port); + if (IS_ERR(cxl_nvb)) + return cxl_nvb; + + dev = &cxl_nvb->dev; + rc = dev_set_name(dev, "nvdimm-bridge"); + if (rc) + goto err; + + rc = device_add(dev); + if (rc) + goto err; + + rc = devm_add_action_or_reset(host, unregister_nvb, cxl_nvb); + if (rc) + return ERR_PTR(rc); + + return cxl_nvb; + +err: + put_device(dev); + return ERR_PTR(rc); +} +EXPORT_SYMBOL_GPL(devm_cxl_add_nvdimm_bridge); + +static void cxl_nvdimm_release(struct device *dev) +{ + struct cxl_nvdimm *cxl_nvd = to_cxl_nvdimm(dev); + + kfree(cxl_nvd); +} + +static const struct attribute_group *cxl_nvdimm_attribute_groups[] = { + &cxl_base_attribute_group, + NULL, +}; + +static const struct device_type cxl_nvdimm_type = { + .name = "cxl_nvdimm", + .release = cxl_nvdimm_release, + .groups = cxl_nvdimm_attribute_groups, +}; + +bool is_cxl_nvdimm(struct device *dev) +{ + return dev->type == &cxl_nvdimm_type; +} +EXPORT_SYMBOL_GPL(is_cxl_nvdimm); + +struct cxl_nvdimm *to_cxl_nvdimm(struct device *dev) +{ + if (dev_WARN_ONCE(dev, !is_cxl_nvdimm(dev), + "not a cxl_nvdimm device\n")) + return NULL; + return container_of(dev, struct cxl_nvdimm, dev); +} +EXPORT_SYMBOL_GPL(to_cxl_nvdimm); + +static struct cxl_nvdimm *cxl_nvdimm_alloc(struct cxl_memdev *cxlmd) +{ + struct cxl_nvdimm *cxl_nvd; + struct device *dev; + + cxl_nvd = kzalloc(sizeof(*cxl_nvd), GFP_KERNEL); + if (!cxl_nvd) + return ERR_PTR(-ENOMEM); + + dev = &cxl_nvd->dev; + cxl_nvd->cxlmd = cxlmd; + device_initialize(dev); + device_set_pm_not_required(dev); + dev->parent = &cxlmd->dev; + dev->bus = &cxl_bus_type; + dev->type = &cxl_nvdimm_type; + + return cxl_nvd; +} + +int devm_cxl_add_nvdimm(struct device *host, struct cxl_memdev *cxlmd) +{ + struct cxl_nvdimm *cxl_nvd; + struct device *dev; + int rc; + + cxl_nvd = cxl_nvdimm_alloc(cxlmd); + if (IS_ERR(cxl_nvd)) + return PTR_ERR(cxl_nvd); + + dev = &cxl_nvd->dev; + rc = dev_set_name(dev, "pmem%d", cxlmd->id); + if (rc) + goto err; + + rc = device_add(dev); + if (rc) + goto err; + + dev_dbg(host, "%s: register %s\n", dev_name(dev->parent), + dev_name(dev)); + + return devm_add_action_or_reset(host, unregister_dev, dev); + +err: + put_device(dev); + return rc; +} +EXPORT_SYMBOL_GPL(devm_cxl_add_nvdimm); + +/** + * cxl_probe_device_regs() - Detect CXL Device register blocks + * @dev: Host device of the @base mapping + * @base: Mapping of CXL 2.0 8.2.8 CXL Device Register Interface + * @map: Map object describing the register block information found + * + * Probe for device register information and return it in map object. + */ +void cxl_probe_device_regs(struct device *dev, void __iomem *base, + struct cxl_device_reg_map *map) +{ + int cap, cap_count; + u64 cap_array; + + *map = (struct cxl_device_reg_map){ 0 }; + + cap_array = readq(base + CXLDEV_CAP_ARRAY_OFFSET); + if (FIELD_GET(CXLDEV_CAP_ARRAY_ID_MASK, cap_array) != + CXLDEV_CAP_ARRAY_CAP_ID) + return; + + cap_count = FIELD_GET(CXLDEV_CAP_ARRAY_COUNT_MASK, cap_array); + + for (cap = 1; cap <= cap_count; cap++) { + u32 offset, length; + u16 cap_id; + + cap_id = FIELD_GET(CXLDEV_CAP_HDR_CAP_ID_MASK, + readl(base + cap * 0x10)); + offset = readl(base + cap * 0x10 + 0x4); + length = readl(base + cap * 0x10 + 0x8); + + switch (cap_id) { + case CXLDEV_CAP_CAP_ID_DEVICE_STATUS: + dev_dbg(dev, "found Status capability (0x%x)\n", offset); + + map->status.valid = true; + map->status.offset = offset; + map->status.size = length; + break; + case CXLDEV_CAP_CAP_ID_PRIMARY_MAILBOX: + dev_dbg(dev, "found Mailbox capability (0x%x)\n", offset); + map->mbox.valid = true; + map->mbox.offset = offset; + map->mbox.size = length; + break; + case CXLDEV_CAP_CAP_ID_SECONDARY_MAILBOX: + dev_dbg(dev, "found Secondary Mailbox capability (0x%x)\n", offset); + break; + case CXLDEV_CAP_CAP_ID_MEMDEV: + dev_dbg(dev, "found Memory Device capability (0x%x)\n", offset); + map->memdev.valid = true; + map->memdev.offset = offset; + map->memdev.size = length; + break; + default: + if (cap_id >= 0x8000) + dev_dbg(dev, "Vendor cap ID: %#x offset: %#x\n", cap_id, offset); + else + dev_dbg(dev, "Unknown cap ID: %#x offset: %#x\n", cap_id, offset); + break; + } + } +} +EXPORT_SYMBOL_GPL(cxl_probe_device_regs); + +static void __iomem *devm_cxl_iomap_block(struct device *dev, + resource_size_t addr, + resource_size_t length) +{ + void __iomem *ret_val; + struct resource *res; + + res = devm_request_mem_region(dev, addr, length, dev_name(dev)); + if (!res) { + resource_size_t end = addr + length - 1; + + dev_err(dev, "Failed to request region %pa-%pa\n", &addr, &end); + return NULL; + } + + ret_val = devm_ioremap(dev, addr, length); + if (!ret_val) + dev_err(dev, "Failed to map region %pr\n", res); + + return ret_val; +} + +int cxl_map_component_regs(struct pci_dev *pdev, + struct cxl_component_regs *regs, + struct cxl_register_map *map) +{ + struct device *dev = &pdev->dev; + resource_size_t phys_addr; + resource_size_t length; + + phys_addr = pci_resource_start(pdev, map->barno); + phys_addr += map->block_offset; + + phys_addr += map->component_map.hdm_decoder.offset; + length = map->component_map.hdm_decoder.size; + regs->hdm_decoder = devm_cxl_iomap_block(dev, phys_addr, length); + if (!regs->hdm_decoder) + return -ENOMEM; + + return 0; +} +EXPORT_SYMBOL_GPL(cxl_map_component_regs); + +int cxl_map_device_regs(struct pci_dev *pdev, + struct cxl_device_regs *regs, + struct cxl_register_map *map) +{ + struct device *dev = &pdev->dev; + resource_size_t phys_addr; + + phys_addr = pci_resource_start(pdev, map->barno); + phys_addr += map->block_offset; + + if (map->device_map.status.valid) { + resource_size_t addr; + resource_size_t length; + + addr = phys_addr + map->device_map.status.offset; + length = map->device_map.status.size; + regs->status = devm_cxl_iomap_block(dev, addr, length); + if (!regs->status) + return -ENOMEM; + } + + if (map->device_map.mbox.valid) { + resource_size_t addr; + resource_size_t length; + + addr = phys_addr + map->device_map.mbox.offset; + length = map->device_map.mbox.size; + regs->mbox = devm_cxl_iomap_block(dev, addr, length); + if (!regs->mbox) + return -ENOMEM; + } + + if (map->device_map.memdev.valid) { + resource_size_t addr; + resource_size_t length; + + addr = phys_addr + map->device_map.memdev.offset; + length = map->device_map.memdev.size; + regs->memdev = devm_cxl_iomap_block(dev, addr, length); + if (!regs->memdev) + return -ENOMEM; + } + + return 0; +} +EXPORT_SYMBOL_GPL(cxl_map_device_regs); + +/** + * __cxl_driver_register - register a driver for the cxl bus + * @cxl_drv: cxl driver structure to attach + * @owner: owning module/driver + * @modname: KBUILD_MODNAME for parent driver + */ +int __cxl_driver_register(struct cxl_driver *cxl_drv, struct module *owner, + const char *modname) +{ + if (!cxl_drv->probe) { + pr_debug("%s ->probe() must be specified\n", modname); + return -EINVAL; + } + + if (!cxl_drv->name) { + pr_debug("%s ->name must be specified\n", modname); + return -EINVAL; + } + + if (!cxl_drv->id) { + pr_debug("%s ->id must be specified\n", modname); + return -EINVAL; + } + + cxl_drv->drv.bus = &cxl_bus_type; + cxl_drv->drv.owner = owner; + cxl_drv->drv.mod_name = modname; + cxl_drv->drv.name = cxl_drv->name; + + return driver_register(&cxl_drv->drv); +} +EXPORT_SYMBOL_GPL(__cxl_driver_register); + +void cxl_driver_unregister(struct cxl_driver *cxl_drv) +{ + driver_unregister(&cxl_drv->drv); +} +EXPORT_SYMBOL_GPL(cxl_driver_unregister); + +static int cxl_device_id(struct device *dev) +{ + if (dev->type == &cxl_nvdimm_bridge_type) + return CXL_DEVICE_NVDIMM_BRIDGE; + if (dev->type == &cxl_nvdimm_type) + return CXL_DEVICE_NVDIMM; + return 0; +} + +static int cxl_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + return add_uevent_var(env, "MODALIAS=" CXL_MODALIAS_FMT, + cxl_device_id(dev)); +} + +static int cxl_bus_match(struct device *dev, struct device_driver *drv) +{ + return cxl_device_id(dev) == to_cxl_drv(drv)->id; +} + +static int cxl_bus_probe(struct device *dev) +{ + return to_cxl_drv(dev->driver)->probe(dev); +} + +static int cxl_bus_remove(struct device *dev) +{ + struct cxl_driver *cxl_drv = to_cxl_drv(dev->driver); + + if (cxl_drv->remove) + cxl_drv->remove(dev); + return 0; +} + +struct bus_type cxl_bus_type = { + .name = "cxl", + .uevent = cxl_bus_uevent, + .match = cxl_bus_match, + .probe = cxl_bus_probe, + .remove = cxl_bus_remove, +}; +EXPORT_SYMBOL_GPL(cxl_bus_type); + +static __init int cxl_core_init(void) +{ + return bus_register(&cxl_bus_type); +} + +static void cxl_core_exit(void) +{ + bus_unregister(&cxl_bus_type); +} + +module_init(cxl_core_init); +module_exit(cxl_core_exit); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index 6f14838c2d25..b6bda39a59e3 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -4,10 +4,51 @@ #ifndef __CXL_H__ #define __CXL_H__ +#include <linux/libnvdimm.h> #include <linux/bitfield.h> #include <linux/bitops.h> #include <linux/io.h> +/** + * DOC: cxl objects + * + * The CXL core objects like ports, decoders, and regions are shared + * between the subsystem drivers cxl_acpi, cxl_pci, and core drivers + * (port-driver, region-driver, nvdimm object-drivers... etc). + */ + +/* CXL 2.0 8.2.5 CXL.cache and CXL.mem Registers*/ +#define CXL_CM_OFFSET 0x1000 +#define CXL_CM_CAP_HDR_OFFSET 0x0 +#define CXL_CM_CAP_HDR_ID_MASK GENMASK(15, 0) +#define CM_CAP_HDR_CAP_ID 1 +#define CXL_CM_CAP_HDR_VERSION_MASK GENMASK(19, 16) +#define CM_CAP_HDR_CAP_VERSION 1 +#define CXL_CM_CAP_HDR_CACHE_MEM_VERSION_MASK GENMASK(23, 20) +#define CM_CAP_HDR_CACHE_MEM_VERSION 1 +#define CXL_CM_CAP_HDR_ARRAY_SIZE_MASK GENMASK(31, 24) +#define CXL_CM_CAP_PTR_MASK GENMASK(31, 20) + +#define CXL_CM_CAP_CAP_ID_HDM 0x5 +#define CXL_CM_CAP_CAP_HDM_VERSION 1 + +/* HDM decoders CXL 2.0 8.2.5.12 CXL HDM Decoder Capability Structure */ +#define CXL_HDM_DECODER_CAP_OFFSET 0x0 +#define CXL_HDM_DECODER_COUNT_MASK GENMASK(3, 0) +#define CXL_HDM_DECODER_TARGET_COUNT_MASK GENMASK(7, 4) +#define CXL_HDM_DECODER0_BASE_LOW_OFFSET 0x10 +#define CXL_HDM_DECODER0_BASE_HIGH_OFFSET 0x14 +#define CXL_HDM_DECODER0_SIZE_LOW_OFFSET 0x18 +#define CXL_HDM_DECODER0_SIZE_HIGH_OFFSET 0x1c +#define CXL_HDM_DECODER0_CTRL_OFFSET 0x20 + +static inline int cxl_hdm_decoder_count(u32 cap_hdr) +{ + int val = FIELD_GET(CXL_HDM_DECODER_COUNT_MASK, cap_hdr); + + return val ? val * 2 : 1; +} + /* CXL 2.0 8.2.8.1 Device Capabilities Array Register */ #define CXLDEV_CAP_ARRAY_OFFSET 0x0 #define CXLDEV_CAP_ARRAY_CAP_ID 0 @@ -34,62 +75,253 @@ #define CXLDEV_MBOX_BG_CMD_STATUS_OFFSET 0x18 #define CXLDEV_MBOX_PAYLOAD_OFFSET 0x20 -/* CXL 2.0 8.2.8.5.1.1 Memory Device Status Register */ -#define CXLMDEV_STATUS_OFFSET 0x0 -#define CXLMDEV_DEV_FATAL BIT(0) -#define CXLMDEV_FW_HALT BIT(1) -#define CXLMDEV_STATUS_MEDIA_STATUS_MASK GENMASK(3, 2) -#define CXLMDEV_MS_NOT_READY 0 -#define CXLMDEV_MS_READY 1 -#define CXLMDEV_MS_ERROR 2 -#define CXLMDEV_MS_DISABLED 3 -#define CXLMDEV_READY(status) \ - (FIELD_GET(CXLMDEV_STATUS_MEDIA_STATUS_MASK, status) == \ - CXLMDEV_MS_READY) -#define CXLMDEV_MBOX_IF_READY BIT(4) -#define CXLMDEV_RESET_NEEDED_MASK GENMASK(7, 5) -#define CXLMDEV_RESET_NEEDED_NOT 0 -#define CXLMDEV_RESET_NEEDED_COLD 1 -#define CXLMDEV_RESET_NEEDED_WARM 2 -#define CXLMDEV_RESET_NEEDED_HOT 3 -#define CXLMDEV_RESET_NEEDED_CXL 4 -#define CXLMDEV_RESET_NEEDED(status) \ - (FIELD_GET(CXLMDEV_RESET_NEEDED_MASK, status) != \ - CXLMDEV_RESET_NEEDED_NOT) - -struct cxl_memdev; +#define CXL_COMPONENT_REGS() \ + void __iomem *hdm_decoder + +#define CXL_DEVICE_REGS() \ + void __iomem *status; \ + void __iomem *mbox; \ + void __iomem *memdev + +/* See note for 'struct cxl_regs' for the rationale of this organization */ +/* + * CXL_COMPONENT_REGS - Common set of CXL Component register block base pointers + * @hdm_decoder: CXL 2.0 8.2.5.12 CXL HDM Decoder Capability Structure + */ +struct cxl_component_regs { + CXL_COMPONENT_REGS(); +}; + +/* See note for 'struct cxl_regs' for the rationale of this organization */ +/* + * CXL_DEVICE_REGS - Common set of CXL Device register block base pointers + * @status: CXL 2.0 8.2.8.3 Device Status Registers + * @mbox: CXL 2.0 8.2.8.4 Mailbox Registers + * @memdev: CXL 2.0 8.2.8.5 Memory Device Registers + */ +struct cxl_device_regs { + CXL_DEVICE_REGS(); +}; + +/* + * Note, the anonymous union organization allows for per + * register-block-type helper routines, without requiring block-type + * agnostic code to include the prefix. + */ +struct cxl_regs { + union { + struct { + CXL_COMPONENT_REGS(); + }; + struct cxl_component_regs component; + }; + union { + struct { + CXL_DEVICE_REGS(); + }; + struct cxl_device_regs device_regs; + }; +}; + +struct cxl_reg_map { + bool valid; + unsigned long offset; + unsigned long size; +}; + +struct cxl_component_reg_map { + struct cxl_reg_map hdm_decoder; +}; + +struct cxl_device_reg_map { + struct cxl_reg_map status; + struct cxl_reg_map mbox; + struct cxl_reg_map memdev; +}; + +struct cxl_register_map { + struct list_head list; + u64 block_offset; + u8 reg_type; + u8 barno; + union { + struct cxl_component_reg_map component_map; + struct cxl_device_reg_map device_map; + }; +}; + +void cxl_probe_component_regs(struct device *dev, void __iomem *base, + struct cxl_component_reg_map *map); +void cxl_probe_device_regs(struct device *dev, void __iomem *base, + struct cxl_device_reg_map *map); +int cxl_map_component_regs(struct pci_dev *pdev, + struct cxl_component_regs *regs, + struct cxl_register_map *map); +int cxl_map_device_regs(struct pci_dev *pdev, + struct cxl_device_regs *regs, + struct cxl_register_map *map); + +#define CXL_RESOURCE_NONE ((resource_size_t) -1) +#define CXL_TARGET_STRLEN 20 + +/* + * cxl_decoder flags that define the type of memory / devices this + * decoder supports as well as configuration lock status See "CXL 2.0 + * 8.2.5.12.7 CXL HDM Decoder 0 Control Register" for details. + */ +#define CXL_DECODER_F_RAM BIT(0) +#define CXL_DECODER_F_PMEM BIT(1) +#define CXL_DECODER_F_TYPE2 BIT(2) +#define CXL_DECODER_F_TYPE3 BIT(3) +#define CXL_DECODER_F_LOCK BIT(4) +#define CXL_DECODER_F_MASK GENMASK(4, 0) + +enum cxl_decoder_type { + CXL_DECODER_ACCELERATOR = 2, + CXL_DECODER_EXPANDER = 3, +}; + /** - * struct cxl_mem - A CXL memory device - * @pdev: The PCI device associated with this CXL device. - * @regs: IO mappings to the device's MMIO - * @status_regs: CXL 2.0 8.2.8.3 Device Status Registers - * @mbox_regs: CXL 2.0 8.2.8.4 Mailbox Registers - * @memdev_regs: CXL 2.0 8.2.8.5 Memory Device Registers - * @payload_size: Size of space for payload - * (CXL 2.0 8.2.8.4.3 Mailbox Capabilities Register) - * @mbox_mutex: Mutex to synchronize mailbox access. - * @firmware_version: Firmware version for the memory device. - * @enabled_commands: Hardware commands found enabled in CEL. - * @pmem_range: Persistent memory capacity information. - * @ram_range: Volatile memory capacity information. + * struct cxl_decoder - CXL address range decode configuration + * @dev: this decoder's device + * @id: kernel device name id + * @range: address range considered by this decoder + * @interleave_ways: number of cxl_dports in this decode + * @interleave_granularity: data stride per dport + * @target_type: accelerator vs expander (type2 vs type3) selector + * @flags: memory type capabilities and locking + * @target: active ordered target list in current decoder configuration */ -struct cxl_mem { - struct pci_dev *pdev; - void __iomem *regs; - struct cxl_memdev *cxlmd; +struct cxl_decoder { + struct device dev; + int id; + struct range range; + int interleave_ways; + int interleave_granularity; + enum cxl_decoder_type target_type; + unsigned long flags; + struct cxl_dport *target[]; +}; - void __iomem *status_regs; - void __iomem *mbox_regs; - void __iomem *memdev_regs; - size_t payload_size; - struct mutex mbox_mutex; /* Protects device mailbox and firmware */ - char firmware_version[0x10]; - unsigned long *enabled_cmds; +enum cxl_nvdimm_brige_state { + CXL_NVB_NEW, + CXL_NVB_DEAD, + CXL_NVB_ONLINE, + CXL_NVB_OFFLINE, +}; - struct range pmem_range; - struct range ram_range; +struct cxl_nvdimm_bridge { + struct device dev; + struct cxl_port *port; + struct nvdimm_bus *nvdimm_bus; + struct nvdimm_bus_descriptor nd_desc; + struct work_struct state_work; + enum cxl_nvdimm_brige_state state; }; +struct cxl_nvdimm { + struct device dev; + struct cxl_memdev *cxlmd; + struct nvdimm *nvdimm; +}; + +/** + * struct cxl_port - logical collection of upstream port devices and + * downstream port devices to construct a CXL memory + * decode hierarchy. + * @dev: this port's device + * @uport: PCI or platform device implementing the upstream port capability + * @id: id for port device-name + * @dports: cxl_dport instances referenced by decoders + * @decoder_ida: allocator for decoder ids + * @component_reg_phys: component register capability base address (optional) + */ +struct cxl_port { + struct device dev; + struct device *uport; + int id; + struct list_head dports; + struct ida decoder_ida; + resource_size_t component_reg_phys; +}; + +/** + * struct cxl_dport - CXL downstream port + * @dport: PCI bridge or firmware device representing the downstream link + * @port_id: unique hardware identifier for dport in decoder target list + * @component_reg_phys: downstream port component registers + * @port: reference to cxl_port that contains this downstream port + * @list: node for a cxl_port's list of cxl_dport instances + */ +struct cxl_dport { + struct device *dport; + int port_id; + resource_size_t component_reg_phys; + struct cxl_port *port; + struct list_head list; +}; + +struct cxl_port *to_cxl_port(struct device *dev); +struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport, + resource_size_t component_reg_phys, + struct cxl_port *parent_port); + +int cxl_add_dport(struct cxl_port *port, struct device *dport, int port_id, + resource_size_t component_reg_phys); + +struct cxl_decoder *to_cxl_decoder(struct device *dev); +bool is_root_decoder(struct device *dev); +struct cxl_decoder * +devm_cxl_add_decoder(struct device *host, struct cxl_port *port, int nr_targets, + resource_size_t base, resource_size_t len, + int interleave_ways, int interleave_granularity, + enum cxl_decoder_type type, unsigned long flags); + +/* + * Per the CXL specification (8.2.5.12 CXL HDM Decoder Capability Structure) + * single ported host-bridges need not publish a decoder capability when a + * passthrough decode can be assumed, i.e. all transactions that the uport sees + * are claimed and passed to the single dport. Default the range a 0-base + * 0-length until the first CXL region is activated. + */ +static inline struct cxl_decoder * +devm_cxl_add_passthrough_decoder(struct device *host, struct cxl_port *port) +{ + return devm_cxl_add_decoder(host, port, 1, 0, 0, 1, PAGE_SIZE, + CXL_DECODER_EXPANDER, 0); +} + extern struct bus_type cxl_bus_type; + +struct cxl_driver { + const char *name; + int (*probe)(struct device *dev); + void (*remove)(struct device *dev); + struct device_driver drv; + int id; +}; + +static inline struct cxl_driver *to_cxl_drv(struct device_driver *drv) +{ + return container_of(drv, struct cxl_driver, drv); +} + +int __cxl_driver_register(struct cxl_driver *cxl_drv, struct module *owner, + const char *modname); +#define cxl_driver_register(x) __cxl_driver_register(x, THIS_MODULE, KBUILD_MODNAME) +void cxl_driver_unregister(struct cxl_driver *cxl_drv); + +#define CXL_DEVICE_NVDIMM_BRIDGE 1 +#define CXL_DEVICE_NVDIMM 2 + +#define MODULE_ALIAS_CXL(type) MODULE_ALIAS("cxl:t" __stringify(type) "*") +#define CXL_MODALIAS_FMT "cxl:t%d" + +struct cxl_nvdimm_bridge *to_cxl_nvdimm_bridge(struct device *dev); +struct cxl_nvdimm_bridge *devm_cxl_add_nvdimm_bridge(struct device *host, + struct cxl_port *port); +struct cxl_nvdimm *to_cxl_nvdimm(struct device *dev); +bool is_cxl_nvdimm(struct device *dev); +int devm_cxl_add_nvdimm(struct device *host, struct cxl_memdev *cxlmd); #endif /* __CXL_H__ */ diff --git a/drivers/cxl/mem.h b/drivers/cxl/mem.h new file mode 100644 index 000000000000..8f02d02b26b4 --- /dev/null +++ b/drivers/cxl/mem.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright(c) 2020-2021 Intel Corporation. */ +#ifndef __CXL_MEM_H__ +#define __CXL_MEM_H__ +#include <linux/cdev.h> +#include "cxl.h" + +/* CXL 2.0 8.2.8.5.1.1 Memory Device Status Register */ +#define CXLMDEV_STATUS_OFFSET 0x0 +#define CXLMDEV_DEV_FATAL BIT(0) +#define CXLMDEV_FW_HALT BIT(1) +#define CXLMDEV_STATUS_MEDIA_STATUS_MASK GENMASK(3, 2) +#define CXLMDEV_MS_NOT_READY 0 +#define CXLMDEV_MS_READY 1 +#define CXLMDEV_MS_ERROR 2 +#define CXLMDEV_MS_DISABLED 3 +#define CXLMDEV_READY(status) \ + (FIELD_GET(CXLMDEV_STATUS_MEDIA_STATUS_MASK, status) == \ + CXLMDEV_MS_READY) +#define CXLMDEV_MBOX_IF_READY BIT(4) +#define CXLMDEV_RESET_NEEDED_MASK GENMASK(7, 5) +#define CXLMDEV_RESET_NEEDED_NOT 0 +#define CXLMDEV_RESET_NEEDED_COLD 1 +#define CXLMDEV_RESET_NEEDED_WARM 2 +#define CXLMDEV_RESET_NEEDED_HOT 3 +#define CXLMDEV_RESET_NEEDED_CXL 4 +#define CXLMDEV_RESET_NEEDED(status) \ + (FIELD_GET(CXLMDEV_RESET_NEEDED_MASK, status) != \ + CXLMDEV_RESET_NEEDED_NOT) + +/* + * An entire PCI topology full of devices should be enough for any + * config + */ +#define CXL_MEM_MAX_DEVS 65536 + +/** + * struct cxl_memdev - CXL bus object representing a Type-3 Memory Device + * @dev: driver core device object + * @cdev: char dev core object for ioctl operations + * @cxlm: pointer to the parent device driver data + * @id: id number of this memdev instance. + */ +struct cxl_memdev { + struct device dev; + struct cdev cdev; + struct cxl_mem *cxlm; + int id; +}; + +/** + * struct cxl_mem - A CXL memory device + * @pdev: The PCI device associated with this CXL device. + * @cxlmd: Logical memory device chardev / interface + * @regs: Parsed register blocks + * @payload_size: Size of space for payload + * (CXL 2.0 8.2.8.4.3 Mailbox Capabilities Register) + * @lsa_size: Size of Label Storage Area + * (CXL 2.0 8.2.9.5.1.1 Identify Memory Device) + * @mbox_mutex: Mutex to synchronize mailbox access. + * @firmware_version: Firmware version for the memory device. + * @enabled_cmds: Hardware commands found enabled in CEL. + * @pmem_range: Persistent memory capacity information. + * @ram_range: Volatile memory capacity information. + */ +struct cxl_mem { + struct pci_dev *pdev; + struct cxl_memdev *cxlmd; + + struct cxl_regs regs; + + size_t payload_size; + size_t lsa_size; + struct mutex mbox_mutex; /* Protects device mailbox and firmware */ + char firmware_version[0x10]; + unsigned long *enabled_cmds; + + struct range pmem_range; + struct range ram_range; +}; +#endif /* __CXL_MEM_H__ */ diff --git a/drivers/cxl/mem.c b/drivers/cxl/pci.c index 2acc6173da36..4cf351a3cf99 100644 --- a/drivers/cxl/mem.c +++ b/drivers/cxl/pci.c @@ -6,6 +6,7 @@ #include <linux/module.h> #include <linux/sizes.h> #include <linux/mutex.h> +#include <linux/list.h> #include <linux/cdev.h> #include <linux/idr.h> #include <linux/pci.h> @@ -13,12 +14,14 @@ #include <linux/io-64-nonatomic-lo-hi.h> #include "pci.h" #include "cxl.h" +#include "mem.h" /** - * DOC: cxl mem + * DOC: cxl pci * - * This implements a CXL memory device ("type-3") as it is defined by the - * Compute Express Link specification. + * This implements the PCI exclusive functionality for a CXL device as it is + * defined by the Compute Express Link specification. CXL devices may surface + * certain functionality even if it isn't CXL enabled. * * The driver has several responsibilities, mainly: * - Create the memX device and register on the CXL bus. @@ -26,18 +29,10 @@ * - Probe the device attributes to establish sysfs interface. * - Provide an IOCTL interface to userspace to communicate with the device for * things like firmware update. - * - Support management of interleave sets. - * - Handle and manage error conditions. */ -/* - * An entire PCI topology full of devices should be enough for any - * config - */ -#define CXL_MEM_MAX_DEVS 65536 - #define cxl_doorbell_busy(cxlm) \ - (readl((cxlm)->mbox_regs + CXLDEV_MBOX_CTRL_OFFSET) & \ + (readl((cxlm)->regs.mbox + CXLDEV_MBOX_CTRL_OFFSET) & \ CXLDEV_MBOX_CTRL_DOORBELL) /* CXL 2.0 - 8.2.8.4 */ @@ -56,7 +51,14 @@ enum opcode { CXL_MBOX_OP_GET_LSA = 0x4102, CXL_MBOX_OP_SET_LSA = 0x4103, CXL_MBOX_OP_GET_HEALTH_INFO = 0x4200, + CXL_MBOX_OP_GET_ALERT_CONFIG = 0x4201, + CXL_MBOX_OP_SET_ALERT_CONFIG = 0x4202, + CXL_MBOX_OP_GET_SHUTDOWN_STATE = 0x4203, CXL_MBOX_OP_SET_SHUTDOWN_STATE = 0x4204, + CXL_MBOX_OP_GET_POISON = 0x4300, + CXL_MBOX_OP_INJECT_POISON = 0x4301, + CXL_MBOX_OP_CLEAR_POISON = 0x4302, + CXL_MBOX_OP_GET_SCAN_MEDIA_CAPS = 0x4303, CXL_MBOX_OP_SCAN_MEDIA = 0x4304, CXL_MBOX_OP_GET_SCAN_MEDIA = 0x4305, CXL_MBOX_OP_MAX = 0x10000 @@ -92,20 +94,6 @@ struct mbox_cmd { #define CXL_MBOX_SUCCESS 0 }; -/** - * struct cxl_memdev - CXL bus object representing a Type-3 Memory Device - * @dev: driver core device object - * @cdev: char dev core object for ioctl operations - * @cxlm: pointer to the parent device driver data - * @id: id number of this memdev instance. - */ -struct cxl_memdev { - struct device dev; - struct cdev cdev; - struct cxl_mem *cxlm; - int id; -}; - static int cxl_mem_major; static DEFINE_IDA(cxl_memdev_ida); static DECLARE_RWSEM(cxl_memdev_rwsem); @@ -178,6 +166,18 @@ static struct cxl_mem_command mem_commands[CXL_MEM_COMMAND_ID_MAX] = { CXL_CMD(GET_LSA, 0x8, ~0, 0), CXL_CMD(GET_HEALTH_INFO, 0, 0x12, 0), CXL_CMD(GET_LOG, 0x18, ~0, CXL_CMD_FLAG_FORCE_ENABLE), + CXL_CMD(SET_PARTITION_INFO, 0x0a, 0, 0), + CXL_CMD(SET_LSA, ~0, 0, 0), + CXL_CMD(GET_ALERT_CONFIG, 0, 0x10, 0), + CXL_CMD(SET_ALERT_CONFIG, 0xc, 0, 0), + CXL_CMD(GET_SHUTDOWN_STATE, 0, 0x1, 0), + CXL_CMD(SET_SHUTDOWN_STATE, 0x1, 0, 0), + CXL_CMD(GET_POISON, 0x10, ~0, 0), + CXL_CMD(INJECT_POISON, 0x8, 0, 0), + CXL_CMD(CLEAR_POISON, 0x48, 0, 0), + CXL_CMD(GET_SCAN_MEDIA_CAPS, 0x10, 0x4, 0), + CXL_CMD(SCAN_MEDIA, 0x11, 0, 0), + CXL_CMD(GET_SCAN_MEDIA, 0, ~0, 0), }; /* @@ -292,7 +292,7 @@ static void cxl_mem_mbox_timeout(struct cxl_mem *cxlm, static int __cxl_mem_mbox_send_cmd(struct cxl_mem *cxlm, struct mbox_cmd *mbox_cmd) { - void __iomem *payload = cxlm->mbox_regs + CXLDEV_MBOX_PAYLOAD_OFFSET; + void __iomem *payload = cxlm->regs.mbox + CXLDEV_MBOX_PAYLOAD_OFFSET; u64 cmd_reg, status_reg; size_t out_len; int rc; @@ -335,12 +335,12 @@ static int __cxl_mem_mbox_send_cmd(struct cxl_mem *cxlm, } /* #2, #3 */ - writeq(cmd_reg, cxlm->mbox_regs + CXLDEV_MBOX_CMD_OFFSET); + writeq(cmd_reg, cxlm->regs.mbox + CXLDEV_MBOX_CMD_OFFSET); /* #4 */ dev_dbg(&cxlm->pdev->dev, "Sending command\n"); writel(CXLDEV_MBOX_CTRL_DOORBELL, - cxlm->mbox_regs + CXLDEV_MBOX_CTRL_OFFSET); + cxlm->regs.mbox + CXLDEV_MBOX_CTRL_OFFSET); /* #5 */ rc = cxl_mem_wait_for_doorbell(cxlm); @@ -350,7 +350,7 @@ static int __cxl_mem_mbox_send_cmd(struct cxl_mem *cxlm, } /* #6 */ - status_reg = readq(cxlm->mbox_regs + CXLDEV_MBOX_STATUS_OFFSET); + status_reg = readq(cxlm->regs.mbox + CXLDEV_MBOX_STATUS_OFFSET); mbox_cmd->return_code = FIELD_GET(CXLDEV_MBOX_STATUS_RET_CODE_MASK, status_reg); @@ -360,7 +360,7 @@ static int __cxl_mem_mbox_send_cmd(struct cxl_mem *cxlm, } /* #7 */ - cmd_reg = readq(cxlm->mbox_regs + CXLDEV_MBOX_CMD_OFFSET); + cmd_reg = readq(cxlm->regs.mbox + CXLDEV_MBOX_CMD_OFFSET); out_len = FIELD_GET(CXLDEV_MBOX_CMD_PAYLOAD_LENGTH_MASK, cmd_reg); /* #8 */ @@ -421,7 +421,7 @@ static int cxl_mem_mbox_get(struct cxl_mem *cxlm) goto out; } - md_status = readq(cxlm->memdev_regs + CXLMDEV_STATUS_OFFSET); + md_status = readq(cxlm->regs.memdev + CXLMDEV_STATUS_OFFSET); if (!(md_status & CXLMDEV_MBOX_IF_READY && CXLMDEV_READY(md_status))) { dev_err(dev, "mbox: reported doorbell ready, but not mbox ready\n"); rc = -EBUSY; @@ -890,75 +890,9 @@ static int cxl_mem_mbox_send_cmd(struct cxl_mem *cxlm, u16 opcode, return 0; } -/** - * cxl_mem_setup_regs() - Setup necessary MMIO. - * @cxlm: The CXL memory device to communicate with. - * - * Return: 0 if all necessary registers mapped. - * - * A memory device is required by spec to implement a certain set of MMIO - * regions. The purpose of this function is to enumerate and map those - * registers. - */ -static int cxl_mem_setup_regs(struct cxl_mem *cxlm) -{ - struct device *dev = &cxlm->pdev->dev; - int cap, cap_count; - u64 cap_array; - - cap_array = readq(cxlm->regs + CXLDEV_CAP_ARRAY_OFFSET); - if (FIELD_GET(CXLDEV_CAP_ARRAY_ID_MASK, cap_array) != - CXLDEV_CAP_ARRAY_CAP_ID) - return -ENODEV; - - cap_count = FIELD_GET(CXLDEV_CAP_ARRAY_COUNT_MASK, cap_array); - - for (cap = 1; cap <= cap_count; cap++) { - void __iomem *register_block; - u32 offset; - u16 cap_id; - - cap_id = FIELD_GET(CXLDEV_CAP_HDR_CAP_ID_MASK, - readl(cxlm->regs + cap * 0x10)); - offset = readl(cxlm->regs + cap * 0x10 + 0x4); - register_block = cxlm->regs + offset; - - switch (cap_id) { - case CXLDEV_CAP_CAP_ID_DEVICE_STATUS: - dev_dbg(dev, "found Status capability (0x%x)\n", offset); - cxlm->status_regs = register_block; - break; - case CXLDEV_CAP_CAP_ID_PRIMARY_MAILBOX: - dev_dbg(dev, "found Mailbox capability (0x%x)\n", offset); - cxlm->mbox_regs = register_block; - break; - case CXLDEV_CAP_CAP_ID_SECONDARY_MAILBOX: - dev_dbg(dev, "found Secondary Mailbox capability (0x%x)\n", offset); - break; - case CXLDEV_CAP_CAP_ID_MEMDEV: - dev_dbg(dev, "found Memory Device capability (0x%x)\n", offset); - cxlm->memdev_regs = register_block; - break; - default: - dev_dbg(dev, "Unknown cap ID: %d (0x%x)\n", cap_id, offset); - break; - } - } - - if (!cxlm->status_regs || !cxlm->mbox_regs || !cxlm->memdev_regs) { - dev_err(dev, "registers not found: %s%s%s\n", - !cxlm->status_regs ? "status " : "", - !cxlm->mbox_regs ? "mbox " : "", - !cxlm->memdev_regs ? "memdev" : ""); - return -ENXIO; - } - - return 0; -} - static int cxl_mem_setup_mailbox(struct cxl_mem *cxlm) { - const int cap = readl(cxlm->mbox_regs + CXLDEV_MBOX_CAPS_OFFSET); + const int cap = readl(cxlm->regs.mbox + CXLDEV_MBOX_CAPS_OFFSET); cxlm->payload_size = 1 << FIELD_GET(CXLDEV_MBOX_CAP_PAYLOAD_SIZE_MASK, cap); @@ -983,55 +917,62 @@ static int cxl_mem_setup_mailbox(struct cxl_mem *cxlm) return 0; } -static struct cxl_mem *cxl_mem_create(struct pci_dev *pdev, u32 reg_lo, - u32 reg_hi) +static struct cxl_mem *cxl_mem_create(struct pci_dev *pdev) { struct device *dev = &pdev->dev; struct cxl_mem *cxlm; - void __iomem *regs; - u64 offset; - u8 bar; - int rc; - cxlm = devm_kzalloc(&pdev->dev, sizeof(*cxlm), GFP_KERNEL); + cxlm = devm_kzalloc(dev, sizeof(*cxlm), GFP_KERNEL); if (!cxlm) { dev_err(dev, "No memory available\n"); - return NULL; - } - - offset = ((u64)reg_hi << 32) | (reg_lo & CXL_REGLOC_ADDR_MASK); - bar = FIELD_GET(CXL_REGLOC_BIR_MASK, reg_lo); - - /* Basic sanity check that BAR is big enough */ - if (pci_resource_len(pdev, bar) < offset) { - dev_err(dev, "BAR%d: %pr: too small (offset: %#llx)\n", bar, - &pdev->resource[bar], (unsigned long long)offset); - return NULL; - } - - rc = pcim_iomap_regions(pdev, BIT(bar), pci_name(pdev)); - if (rc) { - dev_err(dev, "failed to map registers\n"); - return NULL; + return ERR_PTR(-ENOMEM); } - regs = pcim_iomap_table(pdev)[bar]; mutex_init(&cxlm->mbox_mutex); cxlm->pdev = pdev; - cxlm->regs = regs + offset; cxlm->enabled_cmds = devm_kmalloc_array(dev, BITS_TO_LONGS(cxl_cmd_count), sizeof(unsigned long), GFP_KERNEL | __GFP_ZERO); if (!cxlm->enabled_cmds) { dev_err(dev, "No memory available for bitmap\n"); - return NULL; + return ERR_PTR(-ENOMEM); } - dev_dbg(dev, "Mapped CXL Memory Device resource\n"); return cxlm; } +static void __iomem *cxl_mem_map_regblock(struct cxl_mem *cxlm, + u8 bar, u64 offset) +{ + struct pci_dev *pdev = cxlm->pdev; + struct device *dev = &pdev->dev; + void __iomem *addr; + + /* Basic sanity check that BAR is big enough */ + if (pci_resource_len(pdev, bar) < offset) { + dev_err(dev, "BAR%d: %pr: too small (offset: %#llx)\n", bar, + &pdev->resource[bar], (unsigned long long)offset); + return IOMEM_ERR_PTR(-ENXIO); + } + + addr = pci_iomap(pdev, bar, 0); + if (!addr) { + dev_err(dev, "failed to map registers\n"); + return addr; + } + + dev_dbg(dev, "Mapped CXL Memory Device resource bar %u @ %#llx\n", + bar, offset); + + return addr; +} + +static void cxl_mem_unmap_regblock(struct cxl_mem *cxlm, void __iomem *base) +{ + pci_iounmap(cxlm->pdev, base); +} + static int cxl_mem_dvsec(struct pci_dev *pdev, int dvsec) { int pos; @@ -1055,6 +996,171 @@ static int cxl_mem_dvsec(struct pci_dev *pdev, int dvsec) return 0; } +static int cxl_probe_regs(struct cxl_mem *cxlm, void __iomem *base, + struct cxl_register_map *map) +{ + struct pci_dev *pdev = cxlm->pdev; + struct device *dev = &pdev->dev; + struct cxl_component_reg_map *comp_map; + struct cxl_device_reg_map *dev_map; + + switch (map->reg_type) { + case CXL_REGLOC_RBI_COMPONENT: + comp_map = &map->component_map; + cxl_probe_component_regs(dev, base, comp_map); + if (!comp_map->hdm_decoder.valid) { + dev_err(dev, "HDM decoder registers not found\n"); + return -ENXIO; + } + + dev_dbg(dev, "Set up component registers\n"); + break; + case CXL_REGLOC_RBI_MEMDEV: + dev_map = &map->device_map; + cxl_probe_device_regs(dev, base, dev_map); + if (!dev_map->status.valid || !dev_map->mbox.valid || + !dev_map->memdev.valid) { + dev_err(dev, "registers not found: %s%s%s\n", + !dev_map->status.valid ? "status " : "", + !dev_map->mbox.valid ? "status " : "", + !dev_map->memdev.valid ? "status " : ""); + return -ENXIO; + } + + dev_dbg(dev, "Probing device registers...\n"); + break; + default: + break; + } + + return 0; +} + +static int cxl_map_regs(struct cxl_mem *cxlm, struct cxl_register_map *map) +{ + struct pci_dev *pdev = cxlm->pdev; + struct device *dev = &pdev->dev; + + switch (map->reg_type) { + case CXL_REGLOC_RBI_COMPONENT: + cxl_map_component_regs(pdev, &cxlm->regs.component, map); + dev_dbg(dev, "Mapping component registers...\n"); + break; + case CXL_REGLOC_RBI_MEMDEV: + cxl_map_device_regs(pdev, &cxlm->regs.device_regs, map); + dev_dbg(dev, "Probing device registers...\n"); + break; + default: + break; + } + + return 0; +} + +static void cxl_decode_register_block(u32 reg_lo, u32 reg_hi, + u8 *bar, u64 *offset, u8 *reg_type) +{ + *offset = ((u64)reg_hi << 32) | (reg_lo & CXL_REGLOC_ADDR_MASK); + *bar = FIELD_GET(CXL_REGLOC_BIR_MASK, reg_lo); + *reg_type = FIELD_GET(CXL_REGLOC_RBI_MASK, reg_lo); +} + +/** + * cxl_mem_setup_regs() - Setup necessary MMIO. + * @cxlm: The CXL memory device to communicate with. + * + * Return: 0 if all necessary registers mapped. + * + * A memory device is required by spec to implement a certain set of MMIO + * regions. The purpose of this function is to enumerate and map those + * registers. + */ +static int cxl_mem_setup_regs(struct cxl_mem *cxlm) +{ + struct pci_dev *pdev = cxlm->pdev; + struct device *dev = &pdev->dev; + u32 regloc_size, regblocks; + void __iomem *base; + int regloc, i; + struct cxl_register_map *map, *n; + LIST_HEAD(register_maps); + int ret = 0; + + regloc = cxl_mem_dvsec(pdev, PCI_DVSEC_ID_CXL_REGLOC_DVSEC_ID); + if (!regloc) { + dev_err(dev, "register location dvsec not found\n"); + return -ENXIO; + } + + if (pci_request_mem_regions(pdev, pci_name(pdev))) + return -ENODEV; + + /* Get the size of the Register Locator DVSEC */ + pci_read_config_dword(pdev, regloc + PCI_DVSEC_HEADER1, ®loc_size); + regloc_size = FIELD_GET(PCI_DVSEC_HEADER1_LENGTH_MASK, regloc_size); + + regloc += PCI_DVSEC_ID_CXL_REGLOC_BLOCK1_OFFSET; + regblocks = (regloc_size - PCI_DVSEC_ID_CXL_REGLOC_BLOCK1_OFFSET) / 8; + + for (i = 0; i < regblocks; i++, regloc += 8) { + u32 reg_lo, reg_hi; + u8 reg_type; + u64 offset; + u8 bar; + + map = kzalloc(sizeof(*map), GFP_KERNEL); + if (!map) { + ret = -ENOMEM; + goto free_maps; + } + + list_add(&map->list, ®ister_maps); + + pci_read_config_dword(pdev, regloc, ®_lo); + pci_read_config_dword(pdev, regloc + 4, ®_hi); + + cxl_decode_register_block(reg_lo, reg_hi, &bar, &offset, + ®_type); + + dev_dbg(dev, "Found register block in bar %u @ 0x%llx of type %u\n", + bar, offset, reg_type); + + base = cxl_mem_map_regblock(cxlm, bar, offset); + if (!base) { + ret = -ENOMEM; + goto free_maps; + } + + map->barno = bar; + map->block_offset = offset; + map->reg_type = reg_type; + + ret = cxl_probe_regs(cxlm, base + offset, map); + + /* Always unmap the regblock regardless of probe success */ + cxl_mem_unmap_regblock(cxlm, base); + + if (ret) + goto free_maps; + } + + pci_release_mem_regions(pdev); + + list_for_each_entry(map, ®ister_maps, list) { + ret = cxl_map_regs(cxlm, map); + if (ret) + goto free_maps; + } + +free_maps: + list_for_each_entry_safe(map, n, ®ister_maps, list) { + list_del(&map->list); + kfree(map); + } + + return ret; +} + static struct cxl_memdev *to_cxl_memdev(struct device *dev) { return container_of(dev, struct cxl_memdev, dev); @@ -1094,6 +1200,16 @@ static ssize_t payload_max_show(struct device *dev, } static DEVICE_ATTR_RO(payload_max); +static ssize_t label_storage_size_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct cxl_memdev *cxlmd = to_cxl_memdev(dev); + struct cxl_mem *cxlm = cxlmd->cxlm; + + return sysfs_emit(buf, "%zu\n", cxlm->lsa_size); +} +static DEVICE_ATTR_RO(label_storage_size); + static ssize_t ram_size_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1123,6 +1239,7 @@ static struct device_attribute dev_attr_pmem_size = static struct attribute *cxl_memdev_attributes[] = { &dev_attr_firmware_version.attr, &dev_attr_payload_max.attr, + &dev_attr_label_storage_size.attr, NULL, }; @@ -1215,7 +1332,8 @@ err: return ERR_PTR(rc); } -static int cxl_mem_add_memdev(struct cxl_mem *cxlm) +static struct cxl_memdev *devm_cxl_add_memdev(struct device *host, + struct cxl_mem *cxlm) { struct cxl_memdev *cxlmd; struct device *dev; @@ -1224,7 +1342,7 @@ static int cxl_mem_add_memdev(struct cxl_mem *cxlm) cxlmd = cxl_memdev_alloc(cxlm); if (IS_ERR(cxlmd)) - return PTR_ERR(cxlmd); + return cxlmd; dev = &cxlmd->dev; rc = dev_set_name(dev, "mem%d", cxlmd->id); @@ -1242,8 +1360,10 @@ static int cxl_mem_add_memdev(struct cxl_mem *cxlm) if (rc) goto err; - return devm_add_action_or_reset(dev->parent, cxl_memdev_unregister, - cxlmd); + rc = devm_add_action_or_reset(host, cxl_memdev_unregister, cxlmd); + if (rc) + return ERR_PTR(rc); + return cxlmd; err: /* @@ -1252,7 +1372,7 @@ err: */ cxl_memdev_shutdown(cxlmd); put_device(dev); - return rc; + return ERR_PTR(rc); } static int cxl_xfer_log(struct cxl_mem *cxlm, uuid_t *uuid, u32 size, u8 *out) @@ -1455,6 +1575,7 @@ static int cxl_mem_identify(struct cxl_mem *cxlm) cxlm->pmem_range.end = le64_to_cpu(id.persistent_capacity) * SZ_256M - 1; + cxlm->lsa_size = le32_to_cpu(id.lsa_size); memcpy(cxlm->firmware_version, id.fw_revision, sizeof(id.fw_revision)); return 0; @@ -1462,46 +1583,17 @@ static int cxl_mem_identify(struct cxl_mem *cxlm) static int cxl_mem_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - struct device *dev = &pdev->dev; - struct cxl_mem *cxlm = NULL; - u32 regloc_size, regblocks; - int rc, regloc, i; + struct cxl_memdev *cxlmd; + struct cxl_mem *cxlm; + int rc; rc = pcim_enable_device(pdev); if (rc) return rc; - regloc = cxl_mem_dvsec(pdev, PCI_DVSEC_ID_CXL_REGLOC_OFFSET); - if (!regloc) { - dev_err(dev, "register location dvsec not found\n"); - return -ENXIO; - } - - /* Get the size of the Register Locator DVSEC */ - pci_read_config_dword(pdev, regloc + PCI_DVSEC_HEADER1, ®loc_size); - regloc_size = FIELD_GET(PCI_DVSEC_HEADER1_LENGTH_MASK, regloc_size); - - regloc += PCI_DVSEC_ID_CXL_REGLOC_BLOCK1_OFFSET; - regblocks = (regloc_size - PCI_DVSEC_ID_CXL_REGLOC_BLOCK1_OFFSET) / 8; - - for (i = 0; i < regblocks; i++, regloc += 8) { - u32 reg_lo, reg_hi; - u8 reg_type; - - /* "register low and high" contain other bits */ - pci_read_config_dword(pdev, regloc, ®_lo); - pci_read_config_dword(pdev, regloc + 4, ®_hi); - - reg_type = FIELD_GET(CXL_REGLOC_RBI_MASK, reg_lo); - - if (reg_type == CXL_REGLOC_RBI_MEMDEV) { - cxlm = cxl_mem_create(pdev, reg_lo, reg_hi); - break; - } - } - - if (!cxlm) - return -ENODEV; + cxlm = cxl_mem_create(pdev); + if (IS_ERR(cxlm)) + return PTR_ERR(cxlm); rc = cxl_mem_setup_regs(cxlm); if (rc) @@ -1519,7 +1611,14 @@ static int cxl_mem_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (rc) return rc; - return cxl_mem_add_memdev(cxlm); + cxlmd = devm_cxl_add_memdev(&pdev->dev, cxlm); + if (IS_ERR(cxlmd)) + return PTR_ERR(cxlmd); + + if (range_len(&cxlm->pmem_range) && IS_ENABLED(CONFIG_CXL_PMEM)) + rc = devm_cxl_add_nvdimm(&pdev->dev, cxlmd); + + return rc; } static const struct pci_device_id cxl_mem_pci_tbl[] = { @@ -1544,6 +1643,10 @@ static __init int cxl_mem_init(void) dev_t devt; int rc; + /* Double check the anonymous union trickery in struct cxl_regs */ + BUILD_BUG_ON(offsetof(struct cxl_regs, memdev) != + offsetof(struct cxl_regs, device_regs.memdev)); + rc = alloc_chrdev_region(&devt, 0, CXL_MEM_MAX_DEVS, "cxl"); if (rc) return rc; diff --git a/drivers/cxl/pci.h b/drivers/cxl/pci.h index af3ec078cf6c..dad7a831f65f 100644 --- a/drivers/cxl/pci.h +++ b/drivers/cxl/pci.h @@ -13,7 +13,7 @@ #define PCI_DVSEC_VENDOR_ID_CXL 0x1E98 #define PCI_DVSEC_ID_CXL 0x0 -#define PCI_DVSEC_ID_CXL_REGLOC_OFFSET 0x8 +#define PCI_DVSEC_ID_CXL_REGLOC_DVSEC_ID 0x8 #define PCI_DVSEC_ID_CXL_REGLOC_BLOCK1_OFFSET 0xC /* BAR Indicator Register (BIR) */ diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c new file mode 100644 index 000000000000..0088e41dd2f3 --- /dev/null +++ b/drivers/cxl/pmem.c @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2021 Intel Corporation. All rights reserved. */ +#include <linux/libnvdimm.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/ndctl.h> +#include <linux/async.h> +#include <linux/slab.h> +#include "mem.h" +#include "cxl.h" + +/* + * Ordered workqueue for cxl nvdimm device arrival and departure + * to coordinate bus rescans when a bridge arrives and trigger remove + * operations when the bridge is removed. + */ +static struct workqueue_struct *cxl_pmem_wq; + +static void unregister_nvdimm(void *nvdimm) +{ + nvdimm_delete(nvdimm); +} + +static int match_nvdimm_bridge(struct device *dev, const void *data) +{ + return strcmp(dev_name(dev), "nvdimm-bridge") == 0; +} + +static struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(void) +{ + struct device *dev; + + dev = bus_find_device(&cxl_bus_type, NULL, NULL, match_nvdimm_bridge); + if (!dev) + return NULL; + return to_cxl_nvdimm_bridge(dev); +} + +static int cxl_nvdimm_probe(struct device *dev) +{ + struct cxl_nvdimm *cxl_nvd = to_cxl_nvdimm(dev); + struct cxl_nvdimm_bridge *cxl_nvb; + unsigned long flags = 0; + struct nvdimm *nvdimm; + int rc = -ENXIO; + + cxl_nvb = cxl_find_nvdimm_bridge(); + if (!cxl_nvb) + return -ENXIO; + + device_lock(&cxl_nvb->dev); + if (!cxl_nvb->nvdimm_bus) + goto out; + + set_bit(NDD_LABELING, &flags); + nvdimm = nvdimm_create(cxl_nvb->nvdimm_bus, cxl_nvd, NULL, flags, 0, 0, + NULL); + if (!nvdimm) + goto out; + + rc = devm_add_action_or_reset(dev, unregister_nvdimm, nvdimm); +out: + device_unlock(&cxl_nvb->dev); + put_device(&cxl_nvb->dev); + + return rc; +} + +static struct cxl_driver cxl_nvdimm_driver = { + .name = "cxl_nvdimm", + .probe = cxl_nvdimm_probe, + .id = CXL_DEVICE_NVDIMM, +}; + +static int cxl_pmem_ctl(struct nvdimm_bus_descriptor *nd_desc, + struct nvdimm *nvdimm, unsigned int cmd, void *buf, + unsigned int buf_len, int *cmd_rc) +{ + return -ENOTTY; +} + +static bool online_nvdimm_bus(struct cxl_nvdimm_bridge *cxl_nvb) +{ + if (cxl_nvb->nvdimm_bus) + return true; + cxl_nvb->nvdimm_bus = + nvdimm_bus_register(&cxl_nvb->dev, &cxl_nvb->nd_desc); + return cxl_nvb->nvdimm_bus != NULL; +} + +static int cxl_nvdimm_release_driver(struct device *dev, void *data) +{ + if (!is_cxl_nvdimm(dev)) + return 0; + device_release_driver(dev); + return 0; +} + +static void offline_nvdimm_bus(struct nvdimm_bus *nvdimm_bus) +{ + if (!nvdimm_bus) + return; + + /* + * Set the state of cxl_nvdimm devices to unbound / idle before + * nvdimm_bus_unregister() rips the nvdimm objects out from + * underneath them. + */ + bus_for_each_dev(&cxl_bus_type, NULL, NULL, cxl_nvdimm_release_driver); + nvdimm_bus_unregister(nvdimm_bus); +} + +static void cxl_nvb_update_state(struct work_struct *work) +{ + struct cxl_nvdimm_bridge *cxl_nvb = + container_of(work, typeof(*cxl_nvb), state_work); + struct nvdimm_bus *victim_bus = NULL; + bool release = false, rescan = false; + + device_lock(&cxl_nvb->dev); + switch (cxl_nvb->state) { + case CXL_NVB_ONLINE: + if (!online_nvdimm_bus(cxl_nvb)) { + dev_err(&cxl_nvb->dev, + "failed to establish nvdimm bus\n"); + release = true; + } else + rescan = true; + break; + case CXL_NVB_OFFLINE: + case CXL_NVB_DEAD: + victim_bus = cxl_nvb->nvdimm_bus; + cxl_nvb->nvdimm_bus = NULL; + break; + default: + break; + } + device_unlock(&cxl_nvb->dev); + + if (release) + device_release_driver(&cxl_nvb->dev); + if (rescan) { + int rc = bus_rescan_devices(&cxl_bus_type); + + dev_dbg(&cxl_nvb->dev, "rescan: %d\n", rc); + } + offline_nvdimm_bus(victim_bus); + + put_device(&cxl_nvb->dev); +} + +static void cxl_nvdimm_bridge_remove(struct device *dev) +{ + struct cxl_nvdimm_bridge *cxl_nvb = to_cxl_nvdimm_bridge(dev); + + if (cxl_nvb->state == CXL_NVB_ONLINE) + cxl_nvb->state = CXL_NVB_OFFLINE; + if (queue_work(cxl_pmem_wq, &cxl_nvb->state_work)) + get_device(&cxl_nvb->dev); +} + +static int cxl_nvdimm_bridge_probe(struct device *dev) +{ + struct cxl_nvdimm_bridge *cxl_nvb = to_cxl_nvdimm_bridge(dev); + + if (cxl_nvb->state == CXL_NVB_DEAD) + return -ENXIO; + + if (cxl_nvb->state == CXL_NVB_NEW) { + cxl_nvb->nd_desc = (struct nvdimm_bus_descriptor) { + .provider_name = "CXL", + .module = THIS_MODULE, + .ndctl = cxl_pmem_ctl, + }; + + INIT_WORK(&cxl_nvb->state_work, cxl_nvb_update_state); + } + + cxl_nvb->state = CXL_NVB_ONLINE; + if (queue_work(cxl_pmem_wq, &cxl_nvb->state_work)) + get_device(&cxl_nvb->dev); + + return 0; +} + +static struct cxl_driver cxl_nvdimm_bridge_driver = { + .name = "cxl_nvdimm_bridge", + .probe = cxl_nvdimm_bridge_probe, + .remove = cxl_nvdimm_bridge_remove, + .id = CXL_DEVICE_NVDIMM_BRIDGE, +}; + +static __init int cxl_pmem_init(void) +{ + int rc; + + cxl_pmem_wq = alloc_ordered_workqueue("cxl_pmem", 0); + if (!cxl_pmem_wq) + return -ENXIO; + + rc = cxl_driver_register(&cxl_nvdimm_bridge_driver); + if (rc) + goto err_bridge; + + rc = cxl_driver_register(&cxl_nvdimm_driver); + if (rc) + goto err_nvdimm; + + return 0; + +err_nvdimm: + cxl_driver_unregister(&cxl_nvdimm_bridge_driver); +err_bridge: + destroy_workqueue(cxl_pmem_wq); + return rc; +} + +static __exit void cxl_pmem_exit(void) +{ + cxl_driver_unregister(&cxl_nvdimm_driver); + cxl_driver_unregister(&cxl_nvdimm_bridge_driver); + destroy_workqueue(cxl_pmem_wq); +} + +MODULE_LICENSE("GPL v2"); +module_init(cxl_pmem_init); +module_exit(cxl_pmem_exit); +MODULE_IMPORT_NS(CXL); +MODULE_ALIAS_CXL(CXL_DEVICE_NVDIMM_BRIDGE); +MODULE_ALIAS_CXL(CXL_DEVICE_NVDIMM); diff --git a/drivers/dma/altera-msgdma.c b/drivers/dma/altera-msgdma.c index 9a841ce5f0c5..0fe0676f8e1d 100644 --- a/drivers/dma/altera-msgdma.c +++ b/drivers/dma/altera-msgdma.c @@ -19,6 +19,7 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/of_dma.h> #include "dmaengine.h" @@ -888,6 +889,13 @@ static int msgdma_probe(struct platform_device *pdev) if (ret) goto fail; + ret = of_dma_controller_register(pdev->dev.of_node, + of_dma_xlate_by_chan_id, dma_dev); + if (ret == -EINVAL) + dev_warn(&pdev->dev, "device was not probed from DT"); + else if (ret && ret != -ENODEV) + goto fail; + dev_notice(&pdev->dev, "Altera mSGDMA driver probe success\n"); return 0; @@ -908,6 +916,8 @@ static int msgdma_remove(struct platform_device *pdev) { struct msgdma_device *mdev = platform_get_drvdata(pdev); + if (pdev->dev.of_node) + of_dma_controller_free(pdev->dev.of_node); dma_async_device_unregister(&mdev->dmadev); msgdma_dev_remove(mdev); @@ -916,9 +926,19 @@ static int msgdma_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id msgdma_match[] = { + { .compatible = "altr,socfpga-msgdma", }, + { } +}; + +MODULE_DEVICE_TABLE(of, msgdma_match); +#endif + static struct platform_driver msgdma_driver = { .driver = { .name = "altera-msgdma", + .of_match_table = of_match_ptr(msgdma_match), }, .probe = msgdma_probe, .remove = msgdma_remove, diff --git a/drivers/dma/fsl-qdma.c b/drivers/dma/fsl-qdma.c index ed2ab46b15e7..045ead46ec8f 100644 --- a/drivers/dma/fsl-qdma.c +++ b/drivers/dma/fsl-qdma.c @@ -1235,7 +1235,11 @@ static int fsl_qdma_probe(struct platform_device *pdev) fsl_qdma->dma_dev.device_synchronize = fsl_qdma_synchronize; fsl_qdma->dma_dev.device_terminate_all = fsl_qdma_terminate_all; - dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)); + ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)); + if (ret) { + dev_err(&pdev->dev, "dma_set_mask failure.\n"); + return ret; + } platform_set_drvdata(pdev, fsl_qdma); diff --git a/drivers/dma/hsu/hsu.c b/drivers/dma/hsu/hsu.c index 025d8ad5a63c..92caae55aece 100644 --- a/drivers/dma/hsu/hsu.c +++ b/drivers/dma/hsu/hsu.c @@ -201,6 +201,7 @@ EXPORT_SYMBOL_GPL(hsu_dma_get_status); */ int hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr, u32 status) { + struct dma_chan_percpu *stat; struct hsu_dma_chan *hsuc; struct hsu_dma_desc *desc; unsigned long flags; @@ -210,6 +211,7 @@ int hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr, u32 status) return 0; hsuc = &chip->hsu->chan[nr]; + stat = this_cpu_ptr(hsuc->vchan.chan.local); spin_lock_irqsave(&hsuc->vchan.lock, flags); desc = hsuc->desc; @@ -221,6 +223,7 @@ int hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr, u32 status) } else { vchan_cookie_complete(&desc->vdesc); desc->status = DMA_COMPLETE; + stat->bytes_transferred += desc->length; hsu_dma_start_transfer(hsuc); } } diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c index d4419bf1fede..e9def577c697 100644 --- a/drivers/dma/idxd/cdev.c +++ b/drivers/dma/idxd/cdev.c @@ -296,9 +296,7 @@ int idxd_wq_add_cdev(struct idxd_wq *wq) void idxd_wq_del_cdev(struct idxd_wq *wq) { struct idxd_cdev *idxd_cdev; - struct idxd_cdev_context *cdev_ctx; - cdev_ctx = &ictx[wq->idxd->data->type]; idxd_cdev = wq->idxd_cdev; wq->idxd_cdev = NULL; cdev_device_del(&idxd_cdev->cdev, &idxd_cdev->dev); diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index 442d55c11a5f..c8ae41d36040 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -351,7 +351,8 @@ static int idxd_setup_internals(struct idxd_device *idxd) init_waitqueue_head(&idxd->cmd_waitq); if (idxd->hw.cmd_cap & BIT(IDXD_CMD_REQUEST_INT_HANDLE)) { - idxd->int_handles = devm_kcalloc(dev, idxd->max_wqs, sizeof(int), GFP_KERNEL); + idxd->int_handles = kcalloc_node(idxd->max_wqs, sizeof(int), GFP_KERNEL, + dev_to_node(dev)); if (!idxd->int_handles) return -ENOMEM; } diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index d5590c08db51..8070fd664bfc 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -35,7 +35,6 @@ #include <linux/workqueue.h> #include <asm/irq.h> -#include <linux/platform_data/dma-imx-sdma.h> #include <linux/platform_data/dma-imx.h> #include <linux/regmap.h> #include <linux/mfd/syscon.h> @@ -181,6 +180,61 @@ BIT(DMA_MEM_TO_DEV) | \ BIT(DMA_DEV_TO_DEV)) +/** + * struct sdma_script_start_addrs - SDMA script start pointers + * + * start addresses of the different functions in the physical + * address space of the SDMA engine. + */ +struct sdma_script_start_addrs { + s32 ap_2_ap_addr; + s32 ap_2_bp_addr; + s32 ap_2_ap_fixed_addr; + s32 bp_2_ap_addr; + s32 loopback_on_dsp_side_addr; + s32 mcu_interrupt_only_addr; + s32 firi_2_per_addr; + s32 firi_2_mcu_addr; + s32 per_2_firi_addr; + s32 mcu_2_firi_addr; + s32 uart_2_per_addr; + s32 uart_2_mcu_addr; + s32 per_2_app_addr; + s32 mcu_2_app_addr; + s32 per_2_per_addr; + s32 uartsh_2_per_addr; + s32 uartsh_2_mcu_addr; + s32 per_2_shp_addr; + s32 mcu_2_shp_addr; + s32 ata_2_mcu_addr; + s32 mcu_2_ata_addr; + s32 app_2_per_addr; + s32 app_2_mcu_addr; + s32 shp_2_per_addr; + s32 shp_2_mcu_addr; + s32 mshc_2_mcu_addr; + s32 mcu_2_mshc_addr; + s32 spdif_2_mcu_addr; + s32 mcu_2_spdif_addr; + s32 asrc_2_mcu_addr; + s32 ext_mem_2_ipu_addr; + s32 descrambler_addr; + s32 dptc_dvfs_addr; + s32 utra_addr; + s32 ram_code_start_addr; + /* End of v1 array */ + s32 mcu_2_ssish_addr; + s32 ssish_2_mcu_addr; + s32 hdmi_dma_addr; + /* End of v2 array */ + s32 zcanfd_2_mcu_addr; + s32 zqspi_2_mcu_addr; + s32 mcu_2_ecspi_addr; + /* End of v3 array */ + s32 mcu_2_zqspi_addr; + /* End of v4 array */ +}; + /* * Mode/Count of data node descriptors - IPCv2 */ @@ -1829,7 +1883,7 @@ static int sdma_get_firmware(struct sdma_engine *sdma, int ret; ret = request_firmware_nowait(THIS_MODULE, - FW_ACTION_HOTPLUG, fw_name, sdma->dev, + FW_ACTION_UEVENT, fw_name, sdma->dev, GFP_KERNEL, sdma, sdma_load_firmware); return ret; diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c index 43ac3ab23d4c..1a1b7d8458c9 100644 --- a/drivers/dma/qcom/gpi.c +++ b/drivers/dma/qcom/gpi.c @@ -2282,6 +2282,7 @@ static int gpi_probe(struct platform_device *pdev) static const struct of_device_id gpi_of_match[] = { { .compatible = "qcom,sdm845-gpi-dma" }, { .compatible = "qcom,sm8150-gpi-dma" }, + { .compatible = "qcom,sm8250-gpi-dma" }, { }, }; MODULE_DEVICE_TABLE(of, gpi_of_match); diff --git a/drivers/dma/sf-pdma/sf-pdma.c b/drivers/dma/sf-pdma/sf-pdma.c index c4c4e8575764..f12606aeff87 100644 --- a/drivers/dma/sf-pdma/sf-pdma.c +++ b/drivers/dma/sf-pdma/sf-pdma.c @@ -94,6 +94,7 @@ sf_pdma_prep_dma_memcpy(struct dma_chan *dchan, dma_addr_t dest, dma_addr_t src, { struct sf_pdma_chan *chan = to_sf_pdma_chan(dchan); struct sf_pdma_desc *desc; + unsigned long iflags; if (chan && (!len || !dest || !src)) { dev_err(chan->pdma->dma_dev.dev, @@ -109,10 +110,10 @@ sf_pdma_prep_dma_memcpy(struct dma_chan *dchan, dma_addr_t dest, dma_addr_t src, desc->dirn = DMA_MEM_TO_MEM; desc->async_tx = vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); - spin_lock_irqsave(&chan->vchan.lock, flags); + spin_lock_irqsave(&chan->vchan.lock, iflags); chan->desc = desc; sf_pdma_fill_desc(desc, dest, src, len); - spin_unlock_irqrestore(&chan->vchan.lock, flags); + spin_unlock_irqrestore(&chan->vchan.lock, iflags); return desc->async_tx; } diff --git a/drivers/dma/sh/Makefile b/drivers/dma/sh/Makefile index 112fbd22bb3f..abdf10341725 100644 --- a/drivers/dma/sh/Makefile +++ b/drivers/dma/sh/Makefile @@ -3,7 +3,7 @@ # DMA Engine Helpers # -obj-$(CONFIG_SH_DMAE_BASE) += shdma-base.o shdma-of.o +obj-$(CONFIG_SH_DMAE_BASE) += shdma-base.o # # DMA Controllers diff --git a/drivers/dma/sh/shdma-of.c b/drivers/dma/sh/shdma-of.c deleted file mode 100644 index be89dd894328..000000000000 --- a/drivers/dma/sh/shdma-of.c +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * SHDMA Device Tree glue - * - * Copyright (C) 2013 Renesas Electronics Inc. - * Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de> - */ - -#include <linux/dmaengine.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/of_dma.h> -#include <linux/of_platform.h> -#include <linux/platform_device.h> -#include <linux/shdma-base.h> - -#define to_shdma_chan(c) container_of(c, struct shdma_chan, dma_chan) - -static struct dma_chan *shdma_of_xlate(struct of_phandle_args *dma_spec, - struct of_dma *ofdma) -{ - u32 id = dma_spec->args[0]; - dma_cap_mask_t mask; - struct dma_chan *chan; - - if (dma_spec->args_count != 1) - return NULL; - - dma_cap_zero(mask); - /* Only slave DMA channels can be allocated via DT */ - dma_cap_set(DMA_SLAVE, mask); - - chan = dma_request_channel(mask, shdma_chan_filter, - (void *)(uintptr_t)id); - if (chan) - to_shdma_chan(chan)->hw_req = id; - - return chan; -} - -static int shdma_of_probe(struct platform_device *pdev) -{ - const struct of_dev_auxdata *lookup = dev_get_platdata(&pdev->dev); - int ret; - - ret = of_dma_controller_register(pdev->dev.of_node, - shdma_of_xlate, pdev); - if (ret < 0) - return ret; - - ret = of_platform_populate(pdev->dev.of_node, NULL, lookup, &pdev->dev); - if (ret < 0) - of_dma_controller_free(pdev->dev.of_node); - - return ret; -} - -static const struct of_device_id shdma_of_match[] = { - { .compatible = "renesas,shdma-mux", }, - { } -}; -MODULE_DEVICE_TABLE(of, sh_dmae_of_match); - -static struct platform_driver shdma_of = { - .driver = { - .name = "shdma-of", - .of_match_table = shdma_of_match, - }, - .probe = shdma_of_probe, -}; - -module_platform_driver(shdma_of); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("SH-DMA driver DT glue"); -MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c index e8b6633ae661..93f1645ae928 100644 --- a/drivers/dma/sun4i-dma.c +++ b/drivers/dma/sun4i-dma.c @@ -1042,9 +1042,8 @@ handle_pending: * Move the promise into the completed list now that * we're done with it */ - list_del(&vchan->processing->list); - list_add_tail(&vchan->processing->list, - &contract->completed_demands); + list_move_tail(&vchan->processing->list, + &contract->completed_demands); /* * Cyclic DMA transfers are special: diff --git a/drivers/dma/ti/omap-dma.c b/drivers/dma/ti/omap-dma.c index 268a08058714..7cb577e6587b 100644 --- a/drivers/dma/ti/omap-dma.c +++ b/drivers/dma/ti/omap-dma.c @@ -1608,7 +1608,8 @@ static int omap_dma_context_notifier(struct notifier_block *nb, return NOTIFY_BAD; omap_dma_context_save(od); break; - case CPU_CLUSTER_PM_ENTER_FAILED: + case CPU_CLUSTER_PM_ENTER_FAILED: /* No need to restore context */ + break; case CPU_CLUSTER_PM_EXIT: omap_dma_context_restore(od); break; diff --git a/drivers/dma/xilinx/xilinx_dpdma.c b/drivers/dma/xilinx/xilinx_dpdma.c index 6c709803203a..b280a53e8570 100644 --- a/drivers/dma/xilinx/xilinx_dpdma.c +++ b/drivers/dma/xilinx/xilinx_dpdma.c @@ -531,7 +531,7 @@ static void xilinx_dpdma_sw_desc_set_dma_addrs(struct xilinx_dpdma_device *xdev, for (i = 1; i < num_src_addr; i++) { u32 *addr = &hw_desc->src_addr2; - addr[i-1] = lower_32_bits(dma_addr[i]); + addr[i - 1] = lower_32_bits(dma_addr[i]); if (xdev->ext_addr) { u32 *addr_ext = &hw_desc->addr_ext_23; @@ -703,8 +703,9 @@ xilinx_dpdma_chan_prep_interleaved_dma(struct xilinx_dpdma_chan *chan, size_t stride = hsize + xt->sgl[0].icg; if (!IS_ALIGNED(xt->src_start, XILINX_DPDMA_ALIGN_BYTES)) { - dev_err(chan->xdev->dev, "buffer should be aligned at %d B\n", - XILINX_DPDMA_ALIGN_BYTES); + dev_err(chan->xdev->dev, + "chan%u: buffer should be aligned at %d B\n", + chan->id, XILINX_DPDMA_ALIGN_BYTES); return NULL; } @@ -917,7 +918,7 @@ static u32 xilinx_dpdma_chan_ostand(struct xilinx_dpdma_chan *chan) } /** - * xilinx_dpdma_chan_no_ostand - Notify no outstanding transaction event + * xilinx_dpdma_chan_notify_no_ostand - Notify no outstanding transaction event * @chan: DPDMA channel * * Notify waiters for no outstanding event, so waiters can stop the channel @@ -936,7 +937,9 @@ static int xilinx_dpdma_chan_notify_no_ostand(struct xilinx_dpdma_chan *chan) cnt = xilinx_dpdma_chan_ostand(chan); if (cnt) { - dev_dbg(chan->xdev->dev, "%d outstanding transactions\n", cnt); + dev_dbg(chan->xdev->dev, + "chan%u: %d outstanding transactions\n", + chan->id, cnt); return -EWOULDBLOCK; } @@ -972,8 +975,8 @@ static int xilinx_dpdma_chan_wait_no_ostand(struct xilinx_dpdma_chan *chan) return 0; } - dev_err(chan->xdev->dev, "not ready to stop: %d trans\n", - xilinx_dpdma_chan_ostand(chan)); + dev_err(chan->xdev->dev, "chan%u: not ready to stop: %d trans\n", + chan->id, xilinx_dpdma_chan_ostand(chan)); if (ret == 0) return -ETIMEDOUT; @@ -1007,8 +1010,8 @@ static int xilinx_dpdma_chan_poll_no_ostand(struct xilinx_dpdma_chan *chan) return 0; } - dev_err(chan->xdev->dev, "not ready to stop: %d trans\n", - xilinx_dpdma_chan_ostand(chan)); + dev_err(chan->xdev->dev, "chan%u: not ready to stop: %d trans\n", + chan->id, xilinx_dpdma_chan_ostand(chan)); return -ETIMEDOUT; } @@ -1062,7 +1065,8 @@ static void xilinx_dpdma_chan_done_irq(struct xilinx_dpdma_chan *chan) vchan_cyclic_callback(&active->vdesc); else dev_warn(chan->xdev->dev, - "DONE IRQ with no active descriptor!\n"); + "chan%u: DONE IRQ with no active descriptor!\n", + chan->id); spin_unlock_irqrestore(&chan->lock, flags); } @@ -1094,8 +1098,12 @@ static void xilinx_dpdma_chan_vsync_irq(struct xilinx_dpdma_chan *chan) /* If the retrigger raced with vsync, retry at the next frame. */ sw_desc = list_first_entry(&pending->descriptors, struct xilinx_dpdma_sw_desc, node); - if (sw_desc->hw.desc_id != desc_id) + if (sw_desc->hw.desc_id != desc_id) { + dev_dbg(chan->xdev->dev, + "chan%u: vsync race lost (%u != %u), retrying\n", + chan->id, sw_desc->hw.desc_id, desc_id); goto out; + } /* * Complete the active descriptor, if any, promote the pending @@ -1151,10 +1159,12 @@ static void xilinx_dpdma_chan_handle_err(struct xilinx_dpdma_chan *chan) spin_lock_irqsave(&chan->lock, flags); - dev_dbg(xdev->dev, "cur desc addr = 0x%04x%08x\n", + dev_dbg(xdev->dev, "chan%u: cur desc addr = 0x%04x%08x\n", + chan->id, dpdma_read(chan->reg, XILINX_DPDMA_CH_DESC_START_ADDRE), dpdma_read(chan->reg, XILINX_DPDMA_CH_DESC_START_ADDR)); - dev_dbg(xdev->dev, "cur payload addr = 0x%04x%08x\n", + dev_dbg(xdev->dev, "chan%u: cur payload addr = 0x%04x%08x\n", + chan->id, dpdma_read(chan->reg, XILINX_DPDMA_CH_PYLD_CUR_ADDRE), dpdma_read(chan->reg, XILINX_DPDMA_CH_PYLD_CUR_ADDR)); @@ -1170,7 +1180,8 @@ static void xilinx_dpdma_chan_handle_err(struct xilinx_dpdma_chan *chan) xilinx_dpdma_chan_dump_tx_desc(chan, active); if (active->error) - dev_dbg(xdev->dev, "repeated error on desc\n"); + dev_dbg(xdev->dev, "chan%u: repeated error on desc\n", + chan->id); /* Reschedule if there's no new descriptor */ if (!chan->desc.pending && @@ -1235,7 +1246,8 @@ static int xilinx_dpdma_alloc_chan_resources(struct dma_chan *dchan) align, 0); if (!chan->desc_pool) { dev_err(chan->xdev->dev, - "failed to allocate a descriptor pool\n"); + "chan%u: failed to allocate a descriptor pool\n", + chan->id); return -ENOMEM; } @@ -1588,7 +1600,7 @@ static struct dma_chan *of_dma_xilinx_xlate(struct of_phandle_args *dma_spec, struct of_dma *ofdma) { struct xilinx_dpdma_device *xdev = ofdma->of_dma_data; - uint32_t chan_id = dma_spec->args[0]; + u32 chan_id = dma_spec->args[0]; if (chan_id >= ARRAY_SIZE(xdev->chan)) return NULL; diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index d9a16ba2ccc2..65bffde137e3 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -155,34 +155,29 @@ void eisa_driver_unregister(struct eisa_driver *edrv) } EXPORT_SYMBOL(eisa_driver_unregister); -static ssize_t eisa_show_sig(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t signature_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct eisa_device *edev = to_eisa_device(dev); return sprintf(buf, "%s\n", edev->id.sig); } +static DEVICE_ATTR_RO(signature); -static DEVICE_ATTR(signature, S_IRUGO, eisa_show_sig, NULL); - -static ssize_t eisa_show_state(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t enabled_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct eisa_device *edev = to_eisa_device(dev); return sprintf(buf, "%d\n", edev->state & EISA_CONFIG_ENABLED); } +static DEVICE_ATTR_RO(enabled); -static DEVICE_ATTR(enabled, S_IRUGO, eisa_show_state, NULL); - -static ssize_t eisa_show_modalias(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t modalias_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct eisa_device *edev = to_eisa_device(dev); return sprintf(buf, EISA_DEVICE_MODALIAS_FMT "\n", edev->id.sig); } - -static DEVICE_ATTR(modalias, S_IRUGO, eisa_show_modalias, NULL); +static DEVICE_ATTR_RO(modalias); static int __init eisa_init_device(struct eisa_root_device *root, struct eisa_device *edev, diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index e3db936becfd..c69d40ae5619 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig @@ -154,7 +154,7 @@ config EXTCON_RT8973A from abnormal high input voltage (up to 28V). config EXTCON_SM5502 - tristate "Silicon Mitus SM5502 EXTCON support" + tristate "Silicon Mitus SM5502/SM5504 EXTCON support" depends on I2C select IRQ_DOMAIN select REGMAP_I2C diff --git a/drivers/extcon/extcon-intel-mrfld.c b/drivers/extcon/extcon-intel-mrfld.c index f47016fb28a8..cd1a5f230077 100644 --- a/drivers/extcon/extcon-intel-mrfld.c +++ b/drivers/extcon/extcon-intel-mrfld.c @@ -197,6 +197,7 @@ static int mrfld_extcon_probe(struct platform_device *pdev) struct intel_soc_pmic *pmic = dev_get_drvdata(dev->parent); struct regmap *regmap = pmic->regmap; struct mrfld_extcon_data *data; + unsigned int status; unsigned int id; int irq, ret; @@ -244,6 +245,14 @@ static int mrfld_extcon_probe(struct platform_device *pdev) /* Get initial state */ mrfld_extcon_role_detect(data); + /* + * Cached status value is used for cable detection, see comments + * in mrfld_extcon_cable_detect(), we need to sync cached value + * with a real state of the hardware. + */ + regmap_read(regmap, BCOVE_SCHGRIRQ1, &status); + data->status = status; + mrfld_extcon_clear(data, BCOVE_MIRQLVL1, BCOVE_LVL1_CHGR); mrfld_extcon_clear(data, BCOVE_MCHGRIRQ1, BCOVE_CHGRIRQ_ALL); diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c index bbc592823570..9cddf08e0696 100644 --- a/drivers/extcon/extcon-max8997.c +++ b/drivers/extcon/extcon-max8997.c @@ -773,3 +773,4 @@ module_platform_driver(max8997_muic_driver); MODULE_DESCRIPTION("Maxim MAX8997 Extcon driver"); MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:max8997-muic"); diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c index db41d1c58efd..93da2d8379b1 100644 --- a/drivers/extcon/extcon-sm5502.c +++ b/drivers/extcon/extcon-sm5502.c @@ -40,17 +40,13 @@ struct sm5502_muic_info { struct i2c_client *i2c; struct regmap *regmap; + const struct sm5502_type *type; struct regmap_irq_chip_data *irq_data; - struct muic_irq *muic_irqs; - unsigned int num_muic_irqs; int irq; bool irq_attach; bool irq_detach; struct work_struct irq_work; - struct reg_data *reg_data; - unsigned int num_reg_data; - struct mutex mutex; /* @@ -62,6 +58,18 @@ struct sm5502_muic_info { struct delayed_work wq_detcable; }; +struct sm5502_type { + struct muic_irq *muic_irqs; + unsigned int num_muic_irqs; + const struct regmap_irq_chip *irq_chip; + + struct reg_data *reg_data; + unsigned int num_reg_data; + + unsigned int otg_dev_type1; + int (*parse_irq)(struct sm5502_muic_info *info, int irq_type); +}; + /* Default value of SM5502 register to bring up MUIC device. */ static struct reg_data sm5502_reg_data[] = { { @@ -88,7 +96,33 @@ static struct reg_data sm5502_reg_data[] = { | SM5502_REG_INTM2_MHL_MASK, .invert = true, }, - { } +}; + +/* Default value of SM5504 register to bring up MUIC device. */ +static struct reg_data sm5504_reg_data[] = { + { + .reg = SM5502_REG_RESET, + .val = SM5502_REG_RESET_MASK, + .invert = true, + }, { + .reg = SM5502_REG_INTMASK1, + .val = SM5504_REG_INTM1_ATTACH_MASK + | SM5504_REG_INTM1_DETACH_MASK, + .invert = false, + }, { + .reg = SM5502_REG_INTMASK2, + .val = SM5504_REG_INTM2_RID_CHG_MASK + | SM5504_REG_INTM2_UVLO_MASK + | SM5504_REG_INTM2_POR_MASK, + .invert = true, + }, { + .reg = SM5502_REG_CONTROL, + .val = SM5502_REG_CONTROL_MANUAL_SW_MASK + | SM5504_REG_CONTROL_CHGTYP_MASK + | SM5504_REG_CONTROL_USBCHDEN_MASK + | SM5504_REG_CONTROL_ADC_EN_MASK, + .invert = true, + }, }; /* List of detectable cables */ @@ -199,6 +233,55 @@ static const struct regmap_irq_chip sm5502_muic_irq_chip = { .num_irqs = ARRAY_SIZE(sm5502_irqs), }; +/* List of supported interrupt for SM5504 */ +static struct muic_irq sm5504_muic_irqs[] = { + { SM5504_IRQ_INT1_ATTACH, "muic-attach" }, + { SM5504_IRQ_INT1_DETACH, "muic-detach" }, + { SM5504_IRQ_INT1_CHG_DET, "muic-chg-det" }, + { SM5504_IRQ_INT1_DCD_OUT, "muic-dcd-out" }, + { SM5504_IRQ_INT1_OVP_EVENT, "muic-ovp-event" }, + { SM5504_IRQ_INT1_CONNECT, "muic-connect" }, + { SM5504_IRQ_INT1_ADC_CHG, "muic-adc-chg" }, + { SM5504_IRQ_INT2_RID_CHG, "muic-rid-chg" }, + { SM5504_IRQ_INT2_UVLO, "muic-uvlo" }, + { SM5504_IRQ_INT2_POR, "muic-por" }, + { SM5504_IRQ_INT2_OVP_FET, "muic-ovp-fet" }, + { SM5504_IRQ_INT2_OCP_LATCH, "muic-ocp-latch" }, + { SM5504_IRQ_INT2_OCP_EVENT, "muic-ocp-event" }, + { SM5504_IRQ_INT2_OVP_OCP_EVENT, "muic-ovp-ocp-event" }, +}; + +/* Define interrupt list of SM5504 to register regmap_irq */ +static const struct regmap_irq sm5504_irqs[] = { + /* INT1 interrupts */ + { .reg_offset = 0, .mask = SM5504_IRQ_INT1_ATTACH_MASK, }, + { .reg_offset = 0, .mask = SM5504_IRQ_INT1_DETACH_MASK, }, + { .reg_offset = 0, .mask = SM5504_IRQ_INT1_CHG_DET_MASK, }, + { .reg_offset = 0, .mask = SM5504_IRQ_INT1_DCD_OUT_MASK, }, + { .reg_offset = 0, .mask = SM5504_IRQ_INT1_OVP_MASK, }, + { .reg_offset = 0, .mask = SM5504_IRQ_INT1_CONNECT_MASK, }, + { .reg_offset = 0, .mask = SM5504_IRQ_INT1_ADC_CHG_MASK, }, + + /* INT2 interrupts */ + { .reg_offset = 1, .mask = SM5504_IRQ_INT2_RID_CHG_MASK,}, + { .reg_offset = 1, .mask = SM5504_IRQ_INT2_UVLO_MASK, }, + { .reg_offset = 1, .mask = SM5504_IRQ_INT2_POR_MASK, }, + { .reg_offset = 1, .mask = SM5504_IRQ_INT2_OVP_FET_MASK, }, + { .reg_offset = 1, .mask = SM5504_IRQ_INT2_OCP_LATCH_MASK, }, + { .reg_offset = 1, .mask = SM5504_IRQ_INT2_OCP_EVENT_MASK, }, + { .reg_offset = 1, .mask = SM5504_IRQ_INT2_OVP_OCP_EVENT_MASK, }, +}; + +static const struct regmap_irq_chip sm5504_muic_irq_chip = { + .name = "sm5504", + .status_base = SM5502_REG_INT1, + .mask_base = SM5502_REG_INTMASK1, + .mask_invert = false, + .num_regs = 2, + .irqs = sm5504_irqs, + .num_irqs = ARRAY_SIZE(sm5504_irqs), +}; + /* Define regmap configuration of SM5502 for I2C communication */ static bool sm5502_muic_volatile_reg(struct device *dev, unsigned int reg) { @@ -302,11 +385,9 @@ static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info) return ret; } - switch (dev_type1) { - case SM5502_REG_DEV_TYPE1_USB_OTG_MASK: + if (dev_type1 == info->type->otg_dev_type1) { cable_type = SM5502_MUIC_ADC_GROUND_USB_OTG; - break; - default: + } else { dev_dbg(info->dev, "cannot identify the cable type: adc(0x%x), dev_type1(0x%x)\n", adc, dev_type1); @@ -359,6 +440,11 @@ static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info) return ret; } + if (dev_type1 == info->type->otg_dev_type1) { + cable_type = SM5502_MUIC_ADC_OPEN_USB_OTG; + break; + } + switch (dev_type1) { case SM5502_REG_DEV_TYPE1_USB_SDP_MASK: cable_type = SM5502_MUIC_ADC_OPEN_USB; @@ -366,9 +452,6 @@ static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info) case SM5502_REG_DEV_TYPE1_DEDICATED_CHG_MASK: cable_type = SM5502_MUIC_ADC_OPEN_TA; break; - case SM5502_REG_DEV_TYPE1_USB_OTG_MASK: - cable_type = SM5502_MUIC_ADC_OPEN_USB_OTG; - break; default: dev_dbg(info->dev, "cannot identify the cable type: adc(0x%x)\n", @@ -498,16 +581,44 @@ static int sm5502_parse_irq(struct sm5502_muic_info *info, int irq_type) return 0; } +static int sm5504_parse_irq(struct sm5502_muic_info *info, int irq_type) +{ + switch (irq_type) { + case SM5504_IRQ_INT1_ATTACH: + info->irq_attach = true; + break; + case SM5504_IRQ_INT1_DETACH: + info->irq_detach = true; + break; + case SM5504_IRQ_INT1_CHG_DET: + case SM5504_IRQ_INT1_DCD_OUT: + case SM5504_IRQ_INT1_OVP_EVENT: + case SM5504_IRQ_INT1_CONNECT: + case SM5504_IRQ_INT1_ADC_CHG: + case SM5504_IRQ_INT2_RID_CHG: + case SM5504_IRQ_INT2_UVLO: + case SM5504_IRQ_INT2_POR: + case SM5504_IRQ_INT2_OVP_FET: + case SM5504_IRQ_INT2_OCP_LATCH: + case SM5504_IRQ_INT2_OCP_EVENT: + case SM5504_IRQ_INT2_OVP_OCP_EVENT: + default: + break; + } + + return 0; +} + static irqreturn_t sm5502_muic_irq_handler(int irq, void *data) { struct sm5502_muic_info *info = data; int i, irq_type = -1, ret; - for (i = 0; i < info->num_muic_irqs; i++) - if (irq == info->muic_irqs[i].virq) - irq_type = info->muic_irqs[i].irq; + for (i = 0; i < info->type->num_muic_irqs; i++) + if (irq == info->type->muic_irqs[i].virq) + irq_type = info->type->muic_irqs[i].irq; - ret = sm5502_parse_irq(info, irq_type); + ret = info->type->parse_irq(info, irq_type); if (ret < 0) { dev_warn(info->dev, "cannot handle is interrupt:%d\n", irq_type); @@ -552,19 +663,18 @@ static void sm5502_init_dev_type(struct sm5502_muic_info *info) version_id, vendor_id); /* Initiazle the register of SM5502 device to bring-up */ - for (i = 0; i < info->num_reg_data; i++) { + for (i = 0; i < info->type->num_reg_data; i++) { unsigned int val = 0; - if (!info->reg_data[i].invert) - val |= ~info->reg_data[i].val; + if (!info->type->reg_data[i].invert) + val |= ~info->type->reg_data[i].val; else - val = info->reg_data[i].val; - regmap_write(info->regmap, info->reg_data[i].reg, val); + val = info->type->reg_data[i].val; + regmap_write(info->regmap, info->type->reg_data[i].reg, val); } } -static int sm5022_muic_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int sm5022_muic_i2c_probe(struct i2c_client *i2c) { struct device_node *np = i2c->dev.of_node; struct sm5502_muic_info *info; @@ -581,10 +691,13 @@ static int sm5022_muic_i2c_probe(struct i2c_client *i2c, info->dev = &i2c->dev; info->i2c = i2c; info->irq = i2c->irq; - info->muic_irqs = sm5502_muic_irqs; - info->num_muic_irqs = ARRAY_SIZE(sm5502_muic_irqs); - info->reg_data = sm5502_reg_data; - info->num_reg_data = ARRAY_SIZE(sm5502_reg_data); + info->type = device_get_match_data(info->dev); + if (!info->type) + return -EINVAL; + if (!info->type->parse_irq) { + dev_err(info->dev, "parse_irq missing in struct sm5502_type\n"); + return -EINVAL; + } mutex_init(&info->mutex); @@ -600,16 +713,17 @@ static int sm5022_muic_i2c_probe(struct i2c_client *i2c, /* Support irq domain for SM5502 MUIC device */ irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED; - ret = regmap_add_irq_chip(info->regmap, info->irq, irq_flags, 0, - &sm5502_muic_irq_chip, &info->irq_data); + ret = devm_regmap_add_irq_chip(info->dev, info->regmap, info->irq, + irq_flags, 0, info->type->irq_chip, + &info->irq_data); if (ret != 0) { dev_err(info->dev, "failed to request IRQ %d: %d\n", info->irq, ret); return ret; } - for (i = 0; i < info->num_muic_irqs; i++) { - struct muic_irq *muic_irq = &info->muic_irqs[i]; + for (i = 0; i < info->type->num_muic_irqs; i++) { + struct muic_irq *muic_irq = &info->type->muic_irqs[i]; int virq = 0; virq = regmap_irq_get_virq(info->irq_data, muic_irq->irq); @@ -661,17 +775,29 @@ static int sm5022_muic_i2c_probe(struct i2c_client *i2c, return 0; } -static int sm5502_muic_i2c_remove(struct i2c_client *i2c) -{ - struct sm5502_muic_info *info = i2c_get_clientdata(i2c); - - regmap_del_irq_chip(info->irq, info->irq_data); +static const struct sm5502_type sm5502_data = { + .muic_irqs = sm5502_muic_irqs, + .num_muic_irqs = ARRAY_SIZE(sm5502_muic_irqs), + .irq_chip = &sm5502_muic_irq_chip, + .reg_data = sm5502_reg_data, + .num_reg_data = ARRAY_SIZE(sm5502_reg_data), + .otg_dev_type1 = SM5502_REG_DEV_TYPE1_USB_OTG_MASK, + .parse_irq = sm5502_parse_irq, +}; - return 0; -} +static const struct sm5502_type sm5504_data = { + .muic_irqs = sm5504_muic_irqs, + .num_muic_irqs = ARRAY_SIZE(sm5504_muic_irqs), + .irq_chip = &sm5504_muic_irq_chip, + .reg_data = sm5504_reg_data, + .num_reg_data = ARRAY_SIZE(sm5504_reg_data), + .otg_dev_type1 = SM5504_REG_DEV_TYPE1_USB_OTG_MASK, + .parse_irq = sm5504_parse_irq, +}; static const struct of_device_id sm5502_dt_match[] = { - { .compatible = "siliconmitus,sm5502-muic" }, + { .compatible = "siliconmitus,sm5502-muic", .data = &sm5502_data }, + { .compatible = "siliconmitus,sm5504-muic", .data = &sm5504_data }, { }, }; MODULE_DEVICE_TABLE(of, sm5502_dt_match); @@ -702,7 +828,8 @@ static SIMPLE_DEV_PM_OPS(sm5502_muic_pm_ops, sm5502_muic_suspend, sm5502_muic_resume); static const struct i2c_device_id sm5502_i2c_id[] = { - { "sm5502", TYPE_SM5502 }, + { "sm5502", (kernel_ulong_t)&sm5502_data }, + { "sm5504", (kernel_ulong_t)&sm5504_data }, { } }; MODULE_DEVICE_TABLE(i2c, sm5502_i2c_id); @@ -713,8 +840,7 @@ static struct i2c_driver sm5502_muic_i2c_driver = { .pm = &sm5502_muic_pm_ops, .of_match_table = sm5502_dt_match, }, - .probe = sm5022_muic_i2c_probe, - .remove = sm5502_muic_i2c_remove, + .probe_new = sm5022_muic_i2c_probe, .id_table = sm5502_i2c_id, }; diff --git a/drivers/extcon/extcon-sm5502.h b/drivers/extcon/extcon-sm5502.h index ce1f1ec310c4..9c04315d48e2 100644 --- a/drivers/extcon/extcon-sm5502.h +++ b/drivers/extcon/extcon-sm5502.h @@ -8,10 +8,6 @@ #ifndef __LINUX_EXTCON_SM5502_H #define __LINUX_EXTCON_SM5502_H -enum sm5502_types { - TYPE_SM5502, -}; - /* SM5502 registers */ enum sm5502_reg { SM5502_REG_DEVICE_ID = 0x01, @@ -93,6 +89,13 @@ enum sm5502_reg { #define SM5502_REG_CONTROL_RAW_DATA_MASK (0x1 << SM5502_REG_CONTROL_RAW_DATA_SHIFT) #define SM5502_REG_CONTROL_SW_OPEN_MASK (0x1 << SM5502_REG_CONTROL_SW_OPEN_SHIFT) +#define SM5504_REG_CONTROL_CHGTYP_SHIFT 5 +#define SM5504_REG_CONTROL_USBCHDEN_SHIFT 6 +#define SM5504_REG_CONTROL_ADC_EN_SHIFT 7 +#define SM5504_REG_CONTROL_CHGTYP_MASK (0x1 << SM5504_REG_CONTROL_CHGTYP_SHIFT) +#define SM5504_REG_CONTROL_USBCHDEN_MASK (0x1 << SM5504_REG_CONTROL_USBCHDEN_SHIFT) +#define SM5504_REG_CONTROL_ADC_EN_MASK (0x1 << SM5504_REG_CONTROL_ADC_EN_SHIFT) + #define SM5502_REG_INTM1_ATTACH_SHIFT 0 #define SM5502_REG_INTM1_DETACH_SHIFT 1 #define SM5502_REG_INTM1_KP_SHIFT 2 @@ -123,6 +126,36 @@ enum sm5502_reg { #define SM5502_REG_INTM2_STUCK_KEY_RCV_MASK (0x1 << SM5502_REG_INTM2_STUCK_KEY_RCV_SHIFT) #define SM5502_REG_INTM2_MHL_MASK (0x1 << SM5502_REG_INTM2_MHL_SHIFT) +#define SM5504_REG_INTM1_ATTACH_SHIFT 0 +#define SM5504_REG_INTM1_DETACH_SHIFT 1 +#define SM5504_REG_INTM1_CHG_DET_SHIFT 2 +#define SM5504_REG_INTM1_DCD_OUT_SHIFT 3 +#define SM5504_REG_INTM1_OVP_EVENT_SHIFT 4 +#define SM5504_REG_INTM1_CONNECT_SHIFT 5 +#define SM5504_REG_INTM1_ADC_CHG_SHIFT 6 +#define SM5504_REG_INTM1_ATTACH_MASK (0x1 << SM5504_REG_INTM1_ATTACH_SHIFT) +#define SM5504_REG_INTM1_DETACH_MASK (0x1 << SM5504_REG_INTM1_DETACH_SHIFT) +#define SM5504_REG_INTM1_CHG_DET_MASK (0x1 << SM5504_REG_INTM1_CHG_DET_SHIFT) +#define SM5504_REG_INTM1_DCD_OUT_MASK (0x1 << SM5504_REG_INTM1_DCD_OUT_SHIFT) +#define SM5504_REG_INTM1_OVP_EVENT_MASK (0x1 << SM5504_REG_INTM1_OVP_EVENT_SHIFT) +#define SM5504_REG_INTM1_CONNECT_MASK (0x1 << SM5504_REG_INTM1_CONNECT_SHIFT) +#define SM5504_REG_INTM1_ADC_CHG_MASK (0x1 << SM5504_REG_INTM1_ADC_CHG_SHIFT) + +#define SM5504_REG_INTM2_RID_CHG_SHIFT 0 +#define SM5504_REG_INTM2_UVLO_SHIFT 1 +#define SM5504_REG_INTM2_POR_SHIFT 2 +#define SM5504_REG_INTM2_OVP_FET_SHIFT 4 +#define SM5504_REG_INTM2_OCP_LATCH_SHIFT 5 +#define SM5504_REG_INTM2_OCP_EVENT_SHIFT 6 +#define SM5504_REG_INTM2_OVP_OCP_EVENT_SHIFT 7 +#define SM5504_REG_INTM2_RID_CHG_MASK (0x1 << SM5504_REG_INTM2_RID_CHG_SHIFT) +#define SM5504_REG_INTM2_UVLO_MASK (0x1 << SM5504_REG_INTM2_UVLO_SHIFT) +#define SM5504_REG_INTM2_POR_MASK (0x1 << SM5504_REG_INTM2_POR_SHIFT) +#define SM5504_REG_INTM2_OVP_FET_MASK (0x1 << SM5504_REG_INTM2_OVP_FET_SHIFT) +#define SM5504_REG_INTM2_OCP_LATCH_MASK (0x1 << SM5504_REG_INTM2_OCP_LATCH_SHIFT) +#define SM5504_REG_INTM2_OCP_EVENT_MASK (0x1 << SM5504_REG_INTM2_OCP_EVENT_SHIFT) +#define SM5504_REG_INTM2_OVP_OCP_EVENT_MASK (0x1 << SM5504_REG_INTM2_OVP_OCP_EVENT_SHIFT) + #define SM5502_REG_ADC_SHIFT 0 #define SM5502_REG_ADC_MASK (0x1f << SM5502_REG_ADC_SHIFT) @@ -199,6 +232,9 @@ enum sm5502_reg { #define SM5502_REG_DEV_TYPE1_DEDICATED_CHG_MASK (0x1 << SM5502_REG_DEV_TYPE1_DEDICATED_CHG_SHIFT) #define SM5502_REG_DEV_TYPE1_USB_OTG_MASK (0x1 << SM5502_REG_DEV_TYPE1_USB_OTG_SHIFT) +#define SM5504_REG_DEV_TYPE1_USB_OTG_SHIFT 0 +#define SM5504_REG_DEV_TYPE1_USB_OTG_MASK (0x1 << SM5504_REG_DEV_TYPE1_USB_OTG_SHIFT) + #define SM5502_REG_DEV_TYPE2_JIG_USB_ON_SHIFT 0 #define SM5502_REG_DEV_TYPE2_JIG_USB_OFF_SHIFT 1 #define SM5502_REG_DEV_TYPE2_JIG_UART_ON_SHIFT 2 @@ -277,4 +313,42 @@ enum sm5502_irq { #define SM5502_IRQ_INT2_STUCK_KEY_RCV_MASK BIT(4) #define SM5502_IRQ_INT2_MHL_MASK BIT(5) +/* SM5504 Interrupts */ +enum sm5504_irq { + /* INT1 */ + SM5504_IRQ_INT1_ATTACH, + SM5504_IRQ_INT1_DETACH, + SM5504_IRQ_INT1_CHG_DET, + SM5504_IRQ_INT1_DCD_OUT, + SM5504_IRQ_INT1_OVP_EVENT, + SM5504_IRQ_INT1_CONNECT, + SM5504_IRQ_INT1_ADC_CHG, + + /* INT2 */ + SM5504_IRQ_INT2_RID_CHG, + SM5504_IRQ_INT2_UVLO, + SM5504_IRQ_INT2_POR, + SM5504_IRQ_INT2_OVP_FET, + SM5504_IRQ_INT2_OCP_LATCH, + SM5504_IRQ_INT2_OCP_EVENT, + SM5504_IRQ_INT2_OVP_OCP_EVENT, + + SM5504_IRQ_NUM, +}; + +#define SM5504_IRQ_INT1_ATTACH_MASK BIT(0) +#define SM5504_IRQ_INT1_DETACH_MASK BIT(1) +#define SM5504_IRQ_INT1_CHG_DET_MASK BIT(2) +#define SM5504_IRQ_INT1_DCD_OUT_MASK BIT(3) +#define SM5504_IRQ_INT1_OVP_MASK BIT(4) +#define SM5504_IRQ_INT1_CONNECT_MASK BIT(5) +#define SM5504_IRQ_INT1_ADC_CHG_MASK BIT(6) +#define SM5504_IRQ_INT2_RID_CHG_MASK BIT(0) +#define SM5504_IRQ_INT2_UVLO_MASK BIT(1) +#define SM5504_IRQ_INT2_POR_MASK BIT(2) +#define SM5504_IRQ_INT2_OVP_FET_MASK BIT(4) +#define SM5504_IRQ_INT2_OCP_LATCH_MASK BIT(5) +#define SM5504_IRQ_INT2_OCP_EVENT_MASK BIT(6) +#define SM5504_IRQ_INT2_OVP_OCP_EVENT_MASK BIT(7) + #endif /* __LINUX_EXTCON_SM5502_H */ diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c index 88ed971e32c0..b0d671db178a 100644 --- a/drivers/firewire/nosy.c +++ b/drivers/firewire/nosy.c @@ -511,12 +511,12 @@ remove_card(struct pci_dev *dev) wake_up_interruptible(&client->buffer.wait); spin_unlock_irq(&lynx->client_list_lock); - pci_free_consistent(lynx->pci_device, sizeof(struct pcl), - lynx->rcv_start_pcl, lynx->rcv_start_pcl_bus); - pci_free_consistent(lynx->pci_device, sizeof(struct pcl), - lynx->rcv_pcl, lynx->rcv_pcl_bus); - pci_free_consistent(lynx->pci_device, PAGE_SIZE, - lynx->rcv_buffer, lynx->rcv_buffer_bus); + dma_free_coherent(&lynx->pci_device->dev, sizeof(struct pcl), + lynx->rcv_start_pcl, lynx->rcv_start_pcl_bus); + dma_free_coherent(&lynx->pci_device->dev, sizeof(struct pcl), + lynx->rcv_pcl, lynx->rcv_pcl_bus); + dma_free_coherent(&lynx->pci_device->dev, PAGE_SIZE, lynx->rcv_buffer, + lynx->rcv_buffer_bus); iounmap(lynx->registers); pci_disable_device(dev); @@ -532,7 +532,7 @@ add_card(struct pci_dev *dev, const struct pci_device_id *unused) u32 p, end; int ret, i; - if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) { + if (dma_set_mask(&dev->dev, DMA_BIT_MASK(32))) { dev_err(&dev->dev, "DMA address limits not supported for PCILynx hardware\n"); return -ENXIO; @@ -564,12 +564,16 @@ add_card(struct pci_dev *dev, const struct pci_device_id *unused) goto fail_deallocate_lynx; } - lynx->rcv_start_pcl = pci_alloc_consistent(lynx->pci_device, - sizeof(struct pcl), &lynx->rcv_start_pcl_bus); - lynx->rcv_pcl = pci_alloc_consistent(lynx->pci_device, - sizeof(struct pcl), &lynx->rcv_pcl_bus); - lynx->rcv_buffer = pci_alloc_consistent(lynx->pci_device, - RCV_BUFFER_SIZE, &lynx->rcv_buffer_bus); + lynx->rcv_start_pcl = dma_alloc_coherent(&lynx->pci_device->dev, + sizeof(struct pcl), + &lynx->rcv_start_pcl_bus, + GFP_KERNEL); + lynx->rcv_pcl = dma_alloc_coherent(&lynx->pci_device->dev, + sizeof(struct pcl), + &lynx->rcv_pcl_bus, GFP_KERNEL); + lynx->rcv_buffer = dma_alloc_coherent(&lynx->pci_device->dev, + RCV_BUFFER_SIZE, + &lynx->rcv_buffer_bus, GFP_KERNEL); if (lynx->rcv_start_pcl == NULL || lynx->rcv_pcl == NULL || lynx->rcv_buffer == NULL) { @@ -667,14 +671,15 @@ fail_free_irq: fail_deallocate_buffers: if (lynx->rcv_start_pcl) - pci_free_consistent(lynx->pci_device, sizeof(struct pcl), - lynx->rcv_start_pcl, lynx->rcv_start_pcl_bus); + dma_free_coherent(&lynx->pci_device->dev, sizeof(struct pcl), + lynx->rcv_start_pcl, + lynx->rcv_start_pcl_bus); if (lynx->rcv_pcl) - pci_free_consistent(lynx->pci_device, sizeof(struct pcl), - lynx->rcv_pcl, lynx->rcv_pcl_bus); + dma_free_coherent(&lynx->pci_device->dev, sizeof(struct pcl), + lynx->rcv_pcl, lynx->rcv_pcl_bus); if (lynx->rcv_buffer) - pci_free_consistent(lynx->pci_device, PAGE_SIZE, - lynx->rcv_buffer, lynx->rcv_buffer_bus); + dma_free_coherent(&lynx->pci_device->dev, PAGE_SIZE, + lynx->rcv_buffer, lynx->rcv_buffer_bus); iounmap(lynx->registers); fail_deallocate_lynx: diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c index e3da38e15c5b..cfb448eabdaa 100644 --- a/drivers/firmware/psci/psci.c +++ b/drivers/firmware/psci/psci.c @@ -296,7 +296,8 @@ static int get_set_conduit_method(struct device_node *np) return 0; } -static void psci_sys_reset(enum reboot_mode reboot_mode, const char *cmd) +static int psci_sys_reset(struct notifier_block *nb, unsigned long action, + void *data) { if ((reboot_mode == REBOOT_WARM || reboot_mode == REBOOT_SOFT) && psci_system_reset2_supported) { @@ -309,8 +310,15 @@ static void psci_sys_reset(enum reboot_mode reboot_mode, const char *cmd) } else { invoke_psci_fn(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0); } + + return NOTIFY_DONE; } +static struct notifier_block psci_sys_reset_nb = { + .notifier_call = psci_sys_reset, + .priority = 129, +}; + static void psci_sys_poweroff(void) { invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0); @@ -477,7 +485,7 @@ static void __init psci_0_2_set_functions(void) .migrate_info_type = psci_migrate_info_type, }; - arm_pm_restart = psci_sys_reset; + register_restart_handler(&psci_sys_reset_nb); pm_power_off = psci_sys_poweroff; } diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-svc.c index 3aa489dba30a..2a7687911c09 100644 --- a/drivers/firmware/stratix10-svc.c +++ b/drivers/firmware/stratix10-svc.c @@ -1034,24 +1034,32 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev) /* add svc client device(s) */ svc = devm_kzalloc(dev, sizeof(*svc), GFP_KERNEL); - if (!svc) - return -ENOMEM; + if (!svc) { + ret = -ENOMEM; + goto err_free_kfifo; + } svc->stratix10_svc_rsu = platform_device_alloc(STRATIX10_RSU, 0); if (!svc->stratix10_svc_rsu) { dev_err(dev, "failed to allocate %s device\n", STRATIX10_RSU); - return -ENOMEM; + ret = -ENOMEM; + goto err_free_kfifo; } ret = platform_device_add(svc->stratix10_svc_rsu); - if (ret) { - platform_device_put(svc->stratix10_svc_rsu); - return ret; - } + if (ret) + goto err_put_device; + dev_set_drvdata(dev, svc); pr_info("Intel Service Layer Driver Initialized\n"); + return 0; + +err_put_device: + platform_device_put(svc->stratix10_svc_rsu); +err_free_kfifo: + kfifo_free(&controller->svc_fifo); return ret; } diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 33e15058d0dc..8cd454ee20c0 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -7,7 +7,7 @@ menuconfig FPGA tristate "FPGA Configuration Framework" help Say Y here if you want support for configuring FPGAs from the - kernel. The FPGA framework adds a FPGA manager class and FPGA + kernel. The FPGA framework adds an FPGA manager class and FPGA manager drivers. if FPGA @@ -134,7 +134,7 @@ config FPGA_REGION tristate "FPGA Region" depends on FPGA_BRIDGE help - FPGA Region common code. A FPGA Region controls a FPGA Manager + FPGA Region common code. An FPGA Region controls an FPGA Manager and the FPGA Bridges associated with either a reconfigurable region of an FPGA or a whole FPGA. diff --git a/drivers/fpga/altera-pr-ip-core.c b/drivers/fpga/altera-pr-ip-core.c index 5b130c4d9882..dfdf21ed34c4 100644 --- a/drivers/fpga/altera-pr-ip-core.c +++ b/drivers/fpga/altera-pr-ip-core.c @@ -199,16 +199,6 @@ int alt_pr_register(struct device *dev, void __iomem *reg_base) } EXPORT_SYMBOL_GPL(alt_pr_register); -void alt_pr_unregister(struct device *dev) -{ - struct fpga_manager *mgr = dev_get_drvdata(dev); - - dev_dbg(dev, "%s\n", __func__); - - fpga_mgr_unregister(mgr); -} -EXPORT_SYMBOL_GPL(alt_pr_unregister); - MODULE_AUTHOR("Matthew Gerlach <matthew.gerlach@linux.intel.com>"); MODULE_DESCRIPTION("Altera Partial Reconfiguration IP Core"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c index e9266b2a357f..2bfb2ff86930 100644 --- a/drivers/fpga/fpga-bridge.c +++ b/drivers/fpga/fpga-bridge.c @@ -85,14 +85,14 @@ err_dev: } /** - * of_fpga_bridge_get - get an exclusive reference to a fpga bridge + * of_fpga_bridge_get - get an exclusive reference to an fpga bridge * - * @np: node pointer of a FPGA bridge + * @np: node pointer of an FPGA bridge * @info: fpga image specific information * * Return fpga_bridge struct if successful. * Return -EBUSY if someone already has a reference to the bridge. - * Return -ENODEV if @np is not a FPGA Bridge. + * Return -ENODEV if @np is not an FPGA Bridge. */ struct fpga_bridge *of_fpga_bridge_get(struct device_node *np, struct fpga_image_info *info) @@ -113,11 +113,11 @@ static int fpga_bridge_dev_match(struct device *dev, const void *data) } /** - * fpga_bridge_get - get an exclusive reference to a fpga bridge + * fpga_bridge_get - get an exclusive reference to an fpga bridge * @dev: parent device that fpga bridge was registered with * @info: fpga manager info * - * Given a device, get an exclusive reference to a fpga bridge. + * Given a device, get an exclusive reference to an fpga bridge. * * Return: fpga bridge struct or IS_ERR() condition containing error code. */ @@ -224,7 +224,7 @@ EXPORT_SYMBOL_GPL(fpga_bridges_put); /** * of_fpga_bridge_get_to_list - get a bridge, add it to a list * - * @np: node pointer of a FPGA bridge + * @np: node pointer of an FPGA bridge * @info: fpga image specific information * @bridge_list: list of FPGA bridges * @@ -313,7 +313,7 @@ ATTRIBUTE_GROUPS(fpga_bridge); /** * fpga_bridge_create - create and initialize a struct fpga_bridge - * @dev: FPGA bridge device from pdev + * @parent: FPGA bridge device from pdev * @name: FPGA bridge name * @br_ops: pointer to structure of fpga bridge ops * @priv: FPGA bridge private data @@ -323,7 +323,7 @@ ATTRIBUTE_GROUPS(fpga_bridge); * * Return: struct fpga_bridge or NULL */ -struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name, +struct fpga_bridge *fpga_bridge_create(struct device *parent, const char *name, const struct fpga_bridge_ops *br_ops, void *priv) { @@ -331,7 +331,7 @@ struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name, int id, ret; if (!name || !strlen(name)) { - dev_err(dev, "Attempt to register with no name!\n"); + dev_err(parent, "Attempt to register with no name!\n"); return NULL; } @@ -353,8 +353,8 @@ struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name, device_initialize(&bridge->dev); bridge->dev.groups = br_ops->groups; bridge->dev.class = fpga_bridge_class; - bridge->dev.parent = dev; - bridge->dev.of_node = dev->of_node; + bridge->dev.parent = parent; + bridge->dev.of_node = parent->of_node; bridge->dev.id = id; ret = dev_set_name(&bridge->dev, "br%d", id); @@ -373,7 +373,7 @@ error_kfree: EXPORT_SYMBOL_GPL(fpga_bridge_create); /** - * fpga_bridge_free - free a fpga bridge created by fpga_bridge_create() + * fpga_bridge_free - free an fpga bridge created by fpga_bridge_create() * @bridge: FPGA bridge struct */ void fpga_bridge_free(struct fpga_bridge *bridge) @@ -392,12 +392,12 @@ static void devm_fpga_bridge_release(struct device *dev, void *res) /** * devm_fpga_bridge_create - create and init a managed struct fpga_bridge - * @dev: FPGA bridge device from pdev + * @parent: FPGA bridge device from pdev * @name: FPGA bridge name * @br_ops: pointer to structure of fpga bridge ops * @priv: FPGA bridge private data * - * This function is intended for use in a FPGA bridge driver's probe function. + * This function is intended for use in an FPGA bridge driver's probe function. * After the bridge driver creates the struct with devm_fpga_bridge_create(), it * should register the bridge with fpga_bridge_register(). The bridge driver's * remove function should call fpga_bridge_unregister(). The bridge struct @@ -408,7 +408,7 @@ static void devm_fpga_bridge_release(struct device *dev, void *res) * Return: struct fpga_bridge or NULL */ struct fpga_bridge -*devm_fpga_bridge_create(struct device *dev, const char *name, +*devm_fpga_bridge_create(struct device *parent, const char *name, const struct fpga_bridge_ops *br_ops, void *priv) { struct fpga_bridge **ptr, *bridge; @@ -417,12 +417,12 @@ struct fpga_bridge if (!ptr) return NULL; - bridge = fpga_bridge_create(dev, name, br_ops, priv); + bridge = fpga_bridge_create(parent, name, br_ops, priv); if (!bridge) { devres_free(ptr); } else { *ptr = bridge; - devres_add(dev, ptr); + devres_add(parent, ptr); } return bridge; @@ -430,7 +430,7 @@ struct fpga_bridge EXPORT_SYMBOL_GPL(devm_fpga_bridge_create); /** - * fpga_bridge_register - register a FPGA bridge + * fpga_bridge_register - register an FPGA bridge * * @bridge: FPGA bridge struct * @@ -454,11 +454,11 @@ int fpga_bridge_register(struct fpga_bridge *bridge) EXPORT_SYMBOL_GPL(fpga_bridge_register); /** - * fpga_bridge_unregister - unregister a FPGA bridge + * fpga_bridge_unregister - unregister an FPGA bridge * * @bridge: FPGA bridge struct * - * This function is intended for use in a FPGA bridge driver's remove function. + * This function is intended for use in an FPGA bridge driver's remove function. */ void fpga_bridge_unregister(struct fpga_bridge *bridge) { diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index b85bc47c91a9..ecb4c3c795fa 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c @@ -26,7 +26,7 @@ struct fpga_mgr_devres { }; /** - * fpga_image_info_alloc - Allocate a FPGA image info struct + * fpga_image_info_alloc - Allocate an FPGA image info struct * @dev: owning device * * Return: struct fpga_image_info or NULL @@ -50,7 +50,7 @@ struct fpga_image_info *fpga_image_info_alloc(struct device *dev) EXPORT_SYMBOL_GPL(fpga_image_info_alloc); /** - * fpga_image_info_free - Free a FPGA image info struct + * fpga_image_info_free - Free an FPGA image info struct * @info: FPGA image info struct to free */ void fpga_image_info_free(struct fpga_image_info *info) @@ -470,7 +470,7 @@ static int fpga_mgr_dev_match(struct device *dev, const void *data) } /** - * fpga_mgr_get - Given a device, get a reference to a fpga mgr. + * fpga_mgr_get - Given a device, get a reference to an fpga mgr. * @dev: parent device that fpga mgr was registered with * * Return: fpga manager struct or IS_ERR() condition containing error code. @@ -487,7 +487,7 @@ struct fpga_manager *fpga_mgr_get(struct device *dev) EXPORT_SYMBOL_GPL(fpga_mgr_get); /** - * of_fpga_mgr_get - Given a device node, get a reference to a fpga mgr. + * of_fpga_mgr_get - Given a device node, get a reference to an fpga mgr. * * @node: device node * @@ -506,7 +506,7 @@ struct fpga_manager *of_fpga_mgr_get(struct device_node *node) EXPORT_SYMBOL_GPL(of_fpga_mgr_get); /** - * fpga_mgr_put - release a reference to a fpga manager + * fpga_mgr_put - release a reference to an fpga manager * @mgr: fpga manager structure */ void fpga_mgr_put(struct fpga_manager *mgr) @@ -550,8 +550,8 @@ void fpga_mgr_unlock(struct fpga_manager *mgr) EXPORT_SYMBOL_GPL(fpga_mgr_unlock); /** - * fpga_mgr_create - create and initialize a FPGA manager struct - * @dev: fpga manager device from pdev + * fpga_mgr_create - create and initialize an FPGA manager struct + * @parent: fpga manager device from pdev * @name: fpga manager name * @mops: pointer to structure of fpga manager ops * @priv: fpga manager private data @@ -561,7 +561,7 @@ EXPORT_SYMBOL_GPL(fpga_mgr_unlock); * * Return: pointer to struct fpga_manager or NULL */ -struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name, +struct fpga_manager *fpga_mgr_create(struct device *parent, const char *name, const struct fpga_manager_ops *mops, void *priv) { @@ -571,12 +571,12 @@ struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name, if (!mops || !mops->write_complete || !mops->state || !mops->write_init || (!mops->write && !mops->write_sg) || (mops->write && mops->write_sg)) { - dev_err(dev, "Attempt to register without fpga_manager_ops\n"); + dev_err(parent, "Attempt to register without fpga_manager_ops\n"); return NULL; } if (!name || !strlen(name)) { - dev_err(dev, "Attempt to register with no name!\n"); + dev_err(parent, "Attempt to register with no name!\n"); return NULL; } @@ -597,8 +597,8 @@ struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name, device_initialize(&mgr->dev); mgr->dev.class = fpga_mgr_class; mgr->dev.groups = mops->groups; - mgr->dev.parent = dev; - mgr->dev.of_node = dev->of_node; + mgr->dev.parent = parent; + mgr->dev.of_node = parent->of_node; mgr->dev.id = id; ret = dev_set_name(&mgr->dev, "fpga%d", id); @@ -617,7 +617,7 @@ error_kfree: EXPORT_SYMBOL_GPL(fpga_mgr_create); /** - * fpga_mgr_free - free a FPGA manager created with fpga_mgr_create() + * fpga_mgr_free - free an FPGA manager created with fpga_mgr_create() * @mgr: fpga manager struct */ void fpga_mgr_free(struct fpga_manager *mgr) @@ -636,12 +636,12 @@ static void devm_fpga_mgr_release(struct device *dev, void *res) /** * devm_fpga_mgr_create - create and initialize a managed FPGA manager struct - * @dev: fpga manager device from pdev + * @parent: fpga manager device from pdev * @name: fpga manager name * @mops: pointer to structure of fpga manager ops * @priv: fpga manager private data * - * This function is intended for use in a FPGA manager driver's probe function. + * This function is intended for use in an FPGA manager driver's probe function. * After the manager driver creates the manager struct with * devm_fpga_mgr_create(), it should register it with fpga_mgr_register(). The * manager driver's remove function should call fpga_mgr_unregister(). The @@ -651,7 +651,7 @@ static void devm_fpga_mgr_release(struct device *dev, void *res) * * Return: pointer to struct fpga_manager or NULL */ -struct fpga_manager *devm_fpga_mgr_create(struct device *dev, const char *name, +struct fpga_manager *devm_fpga_mgr_create(struct device *parent, const char *name, const struct fpga_manager_ops *mops, void *priv) { @@ -661,20 +661,20 @@ struct fpga_manager *devm_fpga_mgr_create(struct device *dev, const char *name, if (!dr) return NULL; - dr->mgr = fpga_mgr_create(dev, name, mops, priv); + dr->mgr = fpga_mgr_create(parent, name, mops, priv); if (!dr->mgr) { devres_free(dr); return NULL; } - devres_add(dev, dr); + devres_add(parent, dr); return dr->mgr; } EXPORT_SYMBOL_GPL(devm_fpga_mgr_create); /** - * fpga_mgr_register - register a FPGA manager + * fpga_mgr_register - register an FPGA manager * @mgr: fpga manager struct * * Return: 0 on success, negative error code otherwise. @@ -706,10 +706,10 @@ error_device: EXPORT_SYMBOL_GPL(fpga_mgr_register); /** - * fpga_mgr_unregister - unregister a FPGA manager + * fpga_mgr_unregister - unregister an FPGA manager * @mgr: fpga manager struct * - * This function is intended for use in a FPGA manager driver's remove function. + * This function is intended for use in an FPGA manager driver's remove function. */ void fpga_mgr_unregister(struct fpga_manager *mgr) { diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index c3134b89c3fe..a4838715221f 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -33,14 +33,14 @@ struct fpga_region *fpga_region_class_find( EXPORT_SYMBOL_GPL(fpga_region_class_find); /** - * fpga_region_get - get an exclusive reference to a fpga region + * fpga_region_get - get an exclusive reference to an fpga region * @region: FPGA Region struct * * Caller should call fpga_region_put() when done with region. * * Return fpga_region struct if successful. * Return -EBUSY if someone already has a reference to the region. - * Return -ENODEV if @np is not a FPGA Region. + * Return -ENODEV if @np is not an FPGA Region. */ static struct fpga_region *fpga_region_get(struct fpga_region *region) { @@ -181,7 +181,7 @@ ATTRIBUTE_GROUPS(fpga_region); /** * fpga_region_create - alloc and init a struct fpga_region - * @dev: device parent + * @parent: device parent * @mgr: manager that programs this region * @get_bridges: optional function to get bridges to a list * @@ -192,7 +192,7 @@ ATTRIBUTE_GROUPS(fpga_region); * Return: struct fpga_region or NULL */ struct fpga_region -*fpga_region_create(struct device *dev, +*fpga_region_create(struct device *parent, struct fpga_manager *mgr, int (*get_bridges)(struct fpga_region *)) { @@ -214,8 +214,8 @@ struct fpga_region device_initialize(®ion->dev); region->dev.class = fpga_region_class; - region->dev.parent = dev; - region->dev.of_node = dev->of_node; + region->dev.parent = parent; + region->dev.of_node = parent->of_node; region->dev.id = id; ret = dev_set_name(®ion->dev, "region%d", id); @@ -234,7 +234,7 @@ err_free: EXPORT_SYMBOL_GPL(fpga_region_create); /** - * fpga_region_free - free a FPGA region created by fpga_region_create() + * fpga_region_free - free an FPGA region created by fpga_region_create() * @region: FPGA region */ void fpga_region_free(struct fpga_region *region) @@ -253,11 +253,11 @@ static void devm_fpga_region_release(struct device *dev, void *res) /** * devm_fpga_region_create - create and initialize a managed FPGA region struct - * @dev: device parent + * @parent: device parent * @mgr: manager that programs this region * @get_bridges: optional function to get bridges to a list * - * This function is intended for use in a FPGA region driver's probe function. + * This function is intended for use in an FPGA region driver's probe function. * After the region driver creates the region struct with * devm_fpga_region_create(), it should register it with fpga_region_register(). * The region driver's remove function should call fpga_region_unregister(). @@ -268,7 +268,7 @@ static void devm_fpga_region_release(struct device *dev, void *res) * Return: struct fpga_region or NULL */ struct fpga_region -*devm_fpga_region_create(struct device *dev, +*devm_fpga_region_create(struct device *parent, struct fpga_manager *mgr, int (*get_bridges)(struct fpga_region *)) { @@ -278,12 +278,12 @@ struct fpga_region if (!ptr) return NULL; - region = fpga_region_create(dev, mgr, get_bridges); + region = fpga_region_create(parent, mgr, get_bridges); if (!region) { devres_free(ptr); } else { *ptr = region; - devres_add(dev, ptr); + devres_add(parent, ptr); } return region; @@ -291,7 +291,7 @@ struct fpga_region EXPORT_SYMBOL_GPL(devm_fpga_region_create); /** - * fpga_region_register - register a FPGA region + * fpga_region_register - register an FPGA region * @region: FPGA region * * Return: 0 or -errno @@ -303,10 +303,10 @@ int fpga_region_register(struct fpga_region *region) EXPORT_SYMBOL_GPL(fpga_region_register); /** - * fpga_region_unregister - unregister a FPGA region + * fpga_region_unregister - unregister an FPGA region * @region: FPGA region * - * This function is intended for use in a FPGA region driver's remove function. + * This function is intended for use in an FPGA region driver's remove function. */ void fpga_region_unregister(struct fpga_region *region) { diff --git a/drivers/fpga/machxo2-spi.c b/drivers/fpga/machxo2-spi.c index 114a64d2b7a4..1afb41aa20d7 100644 --- a/drivers/fpga/machxo2-spi.c +++ b/drivers/fpga/machxo2-spi.c @@ -374,11 +374,13 @@ static int machxo2_spi_probe(struct spi_device *spi) return devm_fpga_mgr_register(dev, mgr); } +#ifdef CONFIG_OF static const struct of_device_id of_match[] = { { .compatible = "lattice,machxo2-slave-spi", }, {} }; MODULE_DEVICE_TABLE(of, of_match); +#endif static const struct spi_device_id lattice_ids[] = { { "machxo2-slave-spi", 0 }, diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c index e405309baadc..e3c25576b6b9 100644 --- a/drivers/fpga/of-fpga-region.c +++ b/drivers/fpga/of-fpga-region.c @@ -181,7 +181,7 @@ static int child_regions_with_firmware(struct device_node *overlay) * @region: FPGA region * @overlay: overlay applied to the FPGA region * - * Given an overlay applied to a FPGA region, parse the FPGA image specific + * Given an overlay applied to an FPGA region, parse the FPGA image specific * info in the overlay and do some checking. * * Returns: @@ -273,7 +273,7 @@ ret_no_info: * @region: FPGA region that the overlay was applied to * @nd: overlay notification data * - * Called when an overlay targeted to a FPGA Region is about to be applied. + * Called when an overlay targeted to an FPGA Region is about to be applied. * Parses the overlay for properties that influence how the FPGA will be * programmed and does some checking. If the checks pass, programs the FPGA. * If the checks fail, overlay is rejected and does not get added to the @@ -336,8 +336,8 @@ static void of_fpga_region_notify_post_remove(struct fpga_region *region, * @action: notifier action * @arg: reconfig data * - * This notifier handles programming a FPGA when a "firmware-name" property is - * added to a fpga-region. + * This notifier handles programming an FPGA when a "firmware-name" property is + * added to an fpga-region. * * Returns NOTIFY_OK or error if FPGA programming fails. */ diff --git a/drivers/fpga/stratix10-soc.c b/drivers/fpga/stratix10-soc.c index 657a70c5fc99..a2cea500f7cc 100644 --- a/drivers/fpga/stratix10-soc.c +++ b/drivers/fpga/stratix10-soc.c @@ -271,7 +271,7 @@ static int s10_send_buf(struct fpga_manager *mgr, const char *buf, size_t count) } /* - * Send a FPGA image to privileged layers to write to the FPGA. When done + * Send an FPGA image to privileged layers to write to the FPGA. When done * sending, free all service layer buffers we allocated in write_init. */ static int s10_ops_write(struct fpga_manager *mgr, const char *buf, @@ -454,6 +454,7 @@ static int s10_remove(struct platform_device *pdev) struct s10_priv *priv = mgr->priv; fpga_mgr_unregister(mgr); + fpga_mgr_free(mgr); stratix10_svc_free_channel(priv->chan); return 0; diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c index 4e60e84cd17a..59ddc9fd5bca 100644 --- a/drivers/fsi/fsi-core.c +++ b/drivers/fsi/fsi-core.c @@ -724,7 +724,7 @@ static ssize_t cfam_read(struct file *filep, char __user *buf, size_t count, rc = count; fail: *offset = off; - return count; + return rc; } static ssize_t cfam_write(struct file *filep, const char __user *buf, @@ -761,7 +761,7 @@ static ssize_t cfam_write(struct file *filep, const char __user *buf, rc = count; fail: *offset = off; - return count; + return rc; } static loff_t cfam_llseek(struct file *file, loff_t offset, int whence) diff --git a/drivers/fsi/fsi-master-aspeed.c b/drivers/fsi/fsi-master-aspeed.c index 90dbe58ca1ed..8606e55c1721 100644 --- a/drivers/fsi/fsi-master-aspeed.c +++ b/drivers/fsi/fsi-master-aspeed.c @@ -92,7 +92,7 @@ static const u32 fsi_base = 0xa0000000; static u16 aspeed_fsi_divisor = FSI_DIVISOR_DEFAULT; module_param_named(bus_div,aspeed_fsi_divisor, ushort, 0); -#define OPB_POLL_TIMEOUT 10000 +#define OPB_POLL_TIMEOUT 500 static int __opb_write(struct fsi_master_aspeed *aspeed, u32 addr, u32 val, u32 transfer_size) @@ -101,11 +101,15 @@ static int __opb_write(struct fsi_master_aspeed *aspeed, u32 addr, u32 reg, status; int ret; - writel(CMD_WRITE, base + OPB0_RW); - writel(transfer_size, base + OPB0_XFER_SIZE); - writel(addr, base + OPB0_FSI_ADDR); - writel(val, base + OPB0_FSI_DATA_W); - writel(0x1, base + OPB_IRQ_CLEAR); + /* + * The ordering of these writes up until the trigger + * write does not matter, so use writel_relaxed. + */ + writel_relaxed(CMD_WRITE, base + OPB0_RW); + writel_relaxed(transfer_size, base + OPB0_XFER_SIZE); + writel_relaxed(addr, base + OPB0_FSI_ADDR); + writel_relaxed(val, base + OPB0_FSI_DATA_W); + writel_relaxed(0x1, base + OPB_IRQ_CLEAR); writel(0x1, base + OPB_TRIGGER); ret = readl_poll_timeout(base + OPB_IRQ_STATUS, reg, @@ -149,10 +153,14 @@ static int __opb_read(struct fsi_master_aspeed *aspeed, uint32_t addr, u32 result, reg; int status, ret; - writel(CMD_READ, base + OPB0_RW); - writel(transfer_size, base + OPB0_XFER_SIZE); - writel(addr, base + OPB0_FSI_ADDR); - writel(0x1, base + OPB_IRQ_CLEAR); + /* + * The ordering of these writes up until the trigger + * write does not matter, so use writel_relaxed. + */ + writel_relaxed(CMD_READ, base + OPB0_RW); + writel_relaxed(transfer_size, base + OPB0_XFER_SIZE); + writel_relaxed(addr, base + OPB0_FSI_ADDR); + writel_relaxed(0x1, base + OPB_IRQ_CLEAR); writel(0x1, base + OPB_TRIGGER); ret = readl_poll_timeout(base + OPB_IRQ_STATUS, reg, @@ -525,7 +533,6 @@ static int tacoma_cabled_fsi_fixup(struct device *dev) static int fsi_master_aspeed_probe(struct platform_device *pdev) { struct fsi_master_aspeed *aspeed; - struct resource *res; int rc, links, reg; __be32 raw; @@ -541,8 +548,7 @@ static int fsi_master_aspeed_probe(struct platform_device *pdev) aspeed->dev = &pdev->dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - aspeed->base = devm_ioremap_resource(&pdev->dev, res); + aspeed->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(aspeed->base)) return PTR_ERR(aspeed->base); @@ -645,6 +651,7 @@ static const struct of_device_id fsi_master_aspeed_match[] = { { .compatible = "aspeed,ast2600-fsi-master" }, { }, }; +MODULE_DEVICE_TABLE(of, fsi_master_aspeed_match); static struct platform_driver fsi_master_aspeed_driver = { .driver = { diff --git a/drivers/fsi/fsi-master-ast-cf.c b/drivers/fsi/fsi-master-ast-cf.c index 57a779a89b07..24292acdbaf8 100644 --- a/drivers/fsi/fsi-master-ast-cf.c +++ b/drivers/fsi/fsi-master-ast-cf.c @@ -1309,7 +1309,6 @@ static int fsi_master_acf_probe(struct platform_device *pdev) master->cf_mem = devm_ioremap_resource(&pdev->dev, &res); if (IS_ERR(master->cf_mem)) { rc = PTR_ERR(master->cf_mem); - dev_err(&pdev->dev, "Error %d mapping coldfire memory\n", rc); goto err_free; } dev_dbg(&pdev->dev, "DRAM allocation @%x\n", master->cf_mem_addr); @@ -1427,6 +1426,7 @@ static const struct of_device_id fsi_master_acf_match[] = { { .compatible = "aspeed,ast2500-cf-fsi-master" }, { }, }; +MODULE_DEVICE_TABLE(of, fsi_master_acf_match); static struct platform_driver fsi_master_acf = { .driver = { diff --git a/drivers/fsi/fsi-master-gpio.c b/drivers/fsi/fsi-master-gpio.c index aa97c4a250cb..7d5f29b4b595 100644 --- a/drivers/fsi/fsi-master-gpio.c +++ b/drivers/fsi/fsi-master-gpio.c @@ -882,6 +882,7 @@ static const struct of_device_id fsi_master_gpio_match[] = { { .compatible = "fsi-master-gpio" }, { }, }; +MODULE_DEVICE_TABLE(of, fsi_master_gpio_match); static struct platform_driver fsi_master_gpio_driver = { .driver = { diff --git a/drivers/fsi/fsi-occ.c b/drivers/fsi/fsi-occ.c index 10ca2e290655..b223f0ef337b 100644 --- a/drivers/fsi/fsi-occ.c +++ b/drivers/fsi/fsi-occ.c @@ -223,7 +223,8 @@ static const struct file_operations occ_fops = { .release = occ_release, }; -static int occ_verify_checksum(struct occ_response *resp, u16 data_length) +static int occ_verify_checksum(struct occ *occ, struct occ_response *resp, + u16 data_length) { /* Fetch the two bytes after the data for the checksum. */ u16 checksum_resp = get_unaligned_be16(&resp->data[data_length]); @@ -238,8 +239,11 @@ static int occ_verify_checksum(struct occ_response *resp, u16 data_length) for (i = 0; i < data_length; ++i) checksum += resp->data[i]; - if (checksum != checksum_resp) + if (checksum != checksum_resp) { + dev_err(occ->dev, "Bad checksum: %04x!=%04x\n", checksum, + checksum_resp); return -EBADMSG; + } return 0; } @@ -495,6 +499,7 @@ int fsi_occ_submit(struct device *dev, const void *request, size_t req_len, goto done; if (resp->return_status == OCC_RESP_CMD_IN_PRG || + resp->return_status == OCC_RESP_CRIT_INIT || resp->seq_no != seq_no) { rc = -ETIMEDOUT; @@ -532,7 +537,7 @@ int fsi_occ_submit(struct device *dev, const void *request, size_t req_len, } *resp_len = resp_data_length + 7; - rc = occ_verify_checksum(resp, resp_data_length); + rc = occ_verify_checksum(occ, resp, resp_data_length); done: mutex_unlock(&occ->occ_lock); @@ -635,6 +640,7 @@ static const struct of_device_id occ_match[] = { }, { }, }; +MODULE_DEVICE_TABLE(of, occ_match); static struct platform_driver occ_driver = { .driver = { diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c index bfd5e5da8020..84cb965bfed5 100644 --- a/drivers/fsi/fsi-sbefifo.c +++ b/drivers/fsi/fsi-sbefifo.c @@ -325,7 +325,8 @@ static int sbefifo_up_write(struct sbefifo *sbefifo, __be32 word) static int sbefifo_request_reset(struct sbefifo *sbefifo) { struct device *dev = &sbefifo->fsi_dev->dev; - u32 status, timeout; + unsigned long end_time; + u32 status; int rc; dev_dbg(dev, "Requesting FIFO reset\n"); @@ -341,7 +342,8 @@ static int sbefifo_request_reset(struct sbefifo *sbefifo) } /* Wait for it to complete */ - for (timeout = 0; timeout < SBEFIFO_RESET_TIMEOUT; timeout++) { + end_time = jiffies + msecs_to_jiffies(SBEFIFO_RESET_TIMEOUT); + while (!time_after(jiffies, end_time)) { rc = sbefifo_regr(sbefifo, SBEFIFO_UP | SBEFIFO_STS, &status); if (rc) { dev_err(dev, "Failed to read UP fifo status during reset" @@ -355,7 +357,7 @@ static int sbefifo_request_reset(struct sbefifo *sbefifo) return 0; } - msleep(1); + cond_resched(); } dev_err(dev, "FIFO reset timed out\n"); @@ -400,7 +402,7 @@ static int sbefifo_cleanup_hw(struct sbefifo *sbefifo) /* The FIFO already contains a reset request from the SBE ? */ if (down_status & SBEFIFO_STS_RESET_REQ) { dev_info(dev, "Cleanup: FIFO reset request set, resetting\n"); - rc = sbefifo_regw(sbefifo, SBEFIFO_UP, SBEFIFO_PERFORM_RESET); + rc = sbefifo_regw(sbefifo, SBEFIFO_DOWN, SBEFIFO_PERFORM_RESET); if (rc) { sbefifo->broken = true; dev_err(dev, "Cleanup: Reset reg write failed, rc=%d\n", rc); diff --git a/drivers/fsi/fsi-scom.c b/drivers/fsi/fsi-scom.c index b45bfab7b7f5..da1486bb6a14 100644 --- a/drivers/fsi/fsi-scom.c +++ b/drivers/fsi/fsi-scom.c @@ -38,9 +38,10 @@ #define SCOM_STATUS_PIB_RESP_MASK 0x00007000 #define SCOM_STATUS_PIB_RESP_SHIFT 12 -#define SCOM_STATUS_ANY_ERR (SCOM_STATUS_PROTECTION | \ - SCOM_STATUS_PARITY | \ - SCOM_STATUS_PIB_ABORT | \ +#define SCOM_STATUS_FSI2PIB_ERROR (SCOM_STATUS_PROTECTION | \ + SCOM_STATUS_PARITY | \ + SCOM_STATUS_PIB_ABORT) +#define SCOM_STATUS_ANY_ERR (SCOM_STATUS_FSI2PIB_ERROR | \ SCOM_STATUS_PIB_RESP_MASK) /* SCOM address encodings */ #define XSCOM_ADDR_IND_FLAG BIT_ULL(63) @@ -60,7 +61,6 @@ #define XSCOM_ADDR_FORM1_HI_SHIFT 20 /* Retries */ -#define SCOM_MAX_RETRIES 100 /* Retries on busy */ #define SCOM_MAX_IND_RETRIES 10 /* Retries indirect not ready */ struct scom_device { @@ -240,14 +240,15 @@ static int handle_fsi2pib_status(struct scom_device *scom, uint32_t status) { uint32_t dummy = -1; - if (status & SCOM_STATUS_PROTECTION) - return -EPERM; - if (status & SCOM_STATUS_PARITY) { + if (status & SCOM_STATUS_FSI2PIB_ERROR) fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy, sizeof(uint32_t)); + + if (status & SCOM_STATUS_PROTECTION) + return -EPERM; + if (status & SCOM_STATUS_PARITY) return -EIO; - } - /* Return -EBUSY on PIB abort to force a retry */ + if (status & SCOM_STATUS_PIB_ABORT) return -EBUSY; return 0; @@ -284,69 +285,39 @@ static int handle_pib_status(struct scom_device *scom, uint8_t status) static int put_scom(struct scom_device *scom, uint64_t value, uint64_t addr) { - uint32_t status, dummy = -1; - int rc, retries; - - for (retries = 0; retries < SCOM_MAX_RETRIES; retries++) { - rc = raw_put_scom(scom, value, addr, &status); - if (rc) { - /* Try resetting the bridge if FSI fails */ - if (rc != -ENODEV && retries == 0) { - fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, - &dummy, sizeof(uint32_t)); - rc = -EBUSY; - } else - return rc; - } else - rc = handle_fsi2pib_status(scom, status); - if (rc && rc != -EBUSY) - break; - if (rc == 0) { - rc = handle_pib_status(scom, - (status & SCOM_STATUS_PIB_RESP_MASK) - >> SCOM_STATUS_PIB_RESP_SHIFT); - if (rc && rc != -EBUSY) - break; - } - if (rc == 0) - break; - msleep(1); - } - return rc; + uint32_t status; + int rc; + + rc = raw_put_scom(scom, value, addr, &status); + if (rc == -ENODEV) + return rc; + + rc = handle_fsi2pib_status(scom, status); + if (rc) + return rc; + + return handle_pib_status(scom, + (status & SCOM_STATUS_PIB_RESP_MASK) + >> SCOM_STATUS_PIB_RESP_SHIFT); } static int get_scom(struct scom_device *scom, uint64_t *value, uint64_t addr) { - uint32_t status, dummy = -1; - int rc, retries; - - for (retries = 0; retries < SCOM_MAX_RETRIES; retries++) { - rc = raw_get_scom(scom, value, addr, &status); - if (rc) { - /* Try resetting the bridge if FSI fails */ - if (rc != -ENODEV && retries == 0) { - fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, - &dummy, sizeof(uint32_t)); - rc = -EBUSY; - } else - return rc; - } else - rc = handle_fsi2pib_status(scom, status); - if (rc && rc != -EBUSY) - break; - if (rc == 0) { - rc = handle_pib_status(scom, - (status & SCOM_STATUS_PIB_RESP_MASK) - >> SCOM_STATUS_PIB_RESP_SHIFT); - if (rc && rc != -EBUSY) - break; - } - if (rc == 0) - break; - msleep(1); - } - return rc; + uint32_t status; + int rc; + + rc = raw_get_scom(scom, value, addr, &status); + if (rc == -ENODEV) + return rc; + + rc = handle_fsi2pib_status(scom, status); + if (rc) + return rc; + + return handle_pib_status(scom, + (status & SCOM_STATUS_PIB_RESP_MASK) + >> SCOM_STATUS_PIB_RESP_SHIFT); } static ssize_t scom_read(struct file *filep, char __user *buf, size_t len, diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 63b84ba161dc..fab571016adf 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -782,6 +782,18 @@ config GPIO_MSC313 Say Y here to support the main GPIO block on MStar/SigmaStar ARMv7 based SoCs. +config GPIO_IDT3243X + tristate "IDT 79RC3243X GPIO support" + depends on MIKROTIK_RB532 || COMPILE_TEST + select GPIO_GENERIC + select GPIOLIB_IRQCHIP + help + Select this option to enable GPIO driver for + IDT 79RC3243X based devices like Mikrotik RB532. + + To compile this driver as a module, choose M here: the module will + be called gpio-idt3243x. + endmenu menu "Port-mapped I/O GPIO drivers" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index d7c81e1611a4..32a32659866a 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_GPIO_HISI) += gpio-hisi.o obj-$(CONFIG_GPIO_HLWD) += gpio-hlwd.o obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o obj-$(CONFIG_GPIO_ICH) += gpio-ich.o +obj-$(CONFIG_GPIO_IDT3243X) += gpio-idt3243x.o obj-$(CONFIG_GPIO_IOP) += gpio-iop.o obj-$(CONFIG_GPIO_IT87) += gpio-it87.o obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-16.c index 50ad0280fd78..55b40299ebfa 100644 --- a/drivers/gpio/gpio-104-idio-16.c +++ b/drivers/gpio/gpio-104-idio-16.c @@ -44,11 +44,12 @@ struct idio_16_gpio { struct gpio_chip chip; raw_spinlock_t lock; unsigned long irq_mask; - unsigned base; - unsigned out_state; + unsigned int base; + unsigned int out_state; }; -static int idio_16_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +static int idio_16_gpio_get_direction(struct gpio_chip *chip, + unsigned int offset) { if (offset > 15) return GPIO_LINE_DIRECTION_IN; @@ -56,22 +57,23 @@ static int idio_16_gpio_get_direction(struct gpio_chip *chip, unsigned offset) return GPIO_LINE_DIRECTION_OUT; } -static int idio_16_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +static int idio_16_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) { return 0; } static int idio_16_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int value) + unsigned int offset, int value) { chip->set(chip, offset, value); return 0; } -static int idio_16_gpio_get(struct gpio_chip *chip, unsigned offset) +static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset) { struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - const unsigned mask = BIT(offset-16); + const unsigned int mask = BIT(offset-16); if (offset < 16) return -EINVAL; @@ -96,10 +98,11 @@ static int idio_16_gpio_get_multiple(struct gpio_chip *chip, return 0; } -static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) { struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - const unsigned mask = BIT(offset); + const unsigned int mask = BIT(offset); unsigned long flags; if (offset > 15) @@ -180,7 +183,7 @@ static void idio_16_irq_unmask(struct irq_data *data) } } -static int idio_16_irq_set_type(struct irq_data *data, unsigned flow_type) +static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type) { /* The only valid irq types are none and both-edges */ if (flow_type != IRQ_TYPE_NONE && diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c index 0386ede53f3a..c55e821c63b6 100644 --- a/drivers/gpio/gpio-adp5520.c +++ b/drivers/gpio/gpio-adp5520.c @@ -113,10 +113,8 @@ static int adp5520_gpio_probe(struct platform_device *pdev) if (pdata->gpio_en_mask & (1 << i)) dev->lut[gpios++] = 1 << i; - if (gpios < 1) { - ret = -EINVAL; - goto err; - } + if (gpios < 1) + return -EINVAL; gc = &dev->gpio_chip; gc->direction_input = adp5520_gpio_direction_input; @@ -148,18 +146,10 @@ static int adp5520_gpio_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "failed to write\n"); - goto err; + return ret; } - ret = devm_gpiochip_add_data(&pdev->dev, &dev->gpio_chip, dev); - if (ret) - goto err; - - platform_set_drvdata(pdev, dev); - return 0; - -err: - return ret; + return devm_gpiochip_add_data(&pdev->dev, &dev->gpio_chip, dev); } static struct platform_driver adp5520_gpio_driver = { diff --git a/drivers/gpio/gpio-altera-a10sr.c b/drivers/gpio/gpio-altera-a10sr.c index b5917c48e4dc..6af51feda06f 100644 --- a/drivers/gpio/gpio-altera-a10sr.c +++ b/drivers/gpio/gpio-altera-a10sr.c @@ -78,7 +78,6 @@ static const struct gpio_chip altr_a10sr_gc = { static int altr_a10sr_gpio_probe(struct platform_device *pdev) { struct altr_a10sr_gpio *gpio; - int ret; struct altr_a10sr *a10sr = dev_get_drvdata(pdev->dev.parent); gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); @@ -91,15 +90,7 @@ static int altr_a10sr_gpio_probe(struct platform_device *pdev) gpio->gp.parent = pdev->dev.parent; gpio->gp.of_node = pdev->dev.of_node; - ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); } static const struct of_device_id altr_a10sr_gpio_of_match[] = { diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c index 678ddd375891..9b780dc5d390 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c @@ -234,7 +234,6 @@ static int ath79_gpio_probe(struct platform_device *pdev) ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); if (!ctrl) return -ENOMEM; - platform_set_drvdata(pdev, ctrl); if (np) { err = of_property_read_u32(np, "ngpios", &ath79_gpio_count); @@ -290,13 +289,7 @@ static int ath79_gpio_probe(struct platform_device *pdev) girq->handler = handle_simple_irq; } - err = devm_gpiochip_add_data(dev, &ctrl->gc, ctrl); - if (err) { - dev_err(dev, - "cannot add AR71xx GPIO chip, error=%d", err); - return err; - } - return 0; + return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl); } static struct platform_driver ath79_gpio_driver = { diff --git a/drivers/gpio/gpio-bd9571mwv.c b/drivers/gpio/gpio-bd9571mwv.c index df6102b57734..9a4d55f703bb 100644 --- a/drivers/gpio/gpio-bd9571mwv.c +++ b/drivers/gpio/gpio-bd9571mwv.c @@ -97,25 +97,16 @@ static const struct gpio_chip template_chip = { static int bd9571mwv_gpio_probe(struct platform_device *pdev) { struct bd9571mwv_gpio *gpio; - int ret; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) return -ENOMEM; - platform_set_drvdata(pdev, gpio); - gpio->regmap = dev_get_regmap(pdev->dev.parent, NULL); gpio->chip = template_chip; gpio->chip.parent = pdev->dev.parent; - ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); } static const struct platform_device_id bd9571mwv_gpio_id_table[] = { diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c index 9aa59afdcbbf..559188d80c2b 100644 --- a/drivers/gpio/gpio-da9052.c +++ b/drivers/gpio/gpio-da9052.c @@ -196,7 +196,6 @@ static int da9052_gpio_probe(struct platform_device *pdev) { struct da9052_gpio *gpio; struct da9052_pdata *pdata; - int ret; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) @@ -209,15 +208,7 @@ static int da9052_gpio_probe(struct platform_device *pdev) if (pdata && pdata->gpio_base) gpio->gp.base = pdata->gpio_base; - ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); } static struct platform_driver da9052_gpio_driver = { diff --git a/drivers/gpio/gpio-da9055.c b/drivers/gpio/gpio-da9055.c index 6ad0c37b862e..49446a030f10 100644 --- a/drivers/gpio/gpio-da9055.c +++ b/drivers/gpio/gpio-da9055.c @@ -133,7 +133,6 @@ static int da9055_gpio_probe(struct platform_device *pdev) { struct da9055_gpio *gpio; struct da9055_pdata *pdata; - int ret; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) @@ -146,15 +145,7 @@ static int da9055_gpio_probe(struct platform_device *pdev) if (pdata && pdata->gpio_base) gpio->gp.base = pdata->gpio_base; - ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); } static struct platform_driver da9055_gpio_driver = { diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index d3233cc4b76b..3eb13d6d31ef 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -13,17 +13,15 @@ #include <linux/io.h> #include <linux/ioport.h> #include <linux/irq.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> +#include <linux/platform_data/gpio-dwapb.h> #include <linux/platform_device.h> #include <linux/property.h> #include <linux/reset.h> -#include <linux/spinlock.h> -#include <linux/platform_data/gpio-dwapb.h> #include <linux/slab.h> +#include <linux/spinlock.h> #include "gpiolib.h" #include "gpiolib-acpi.h" @@ -297,9 +295,6 @@ static int dwapb_irq_set_type(struct irq_data *d, u32 type) irq_hw_number_t bit = irqd_to_hwirq(d); unsigned long level, polarity, flags; - if (type & ~IRQ_TYPE_SENSE_MASK) - return -EINVAL; - spin_lock_irqsave(&gc->bgpio_lock, flags); level = dwapb_read(gpio, GPIO_INTTYPE_LEVEL); polarity = dwapb_read(gpio, GPIO_INT_POLARITY); @@ -531,17 +526,13 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, static void dwapb_get_irq(struct device *dev, struct fwnode_handle *fwnode, struct dwapb_port_property *pp) { - struct device_node *np = NULL; - int irq = -ENXIO, j; - - if (fwnode_property_read_bool(fwnode, "interrupt-controller")) - np = to_of_node(fwnode); + int irq, j; for (j = 0; j < pp->ngpio; j++) { - if (np) - irq = of_irq_get(np, j); - else if (has_acpi_companion(dev)) + if (has_acpi_companion(dev)) irq = platform_get_irq_optional(to_platform_device(dev), j); + else + irq = fwnode_irq_get(fwnode, j); if (irq > 0) pp->irq[j] = irq; } diff --git a/drivers/gpio/gpio-idt3243x.c b/drivers/gpio/gpio-idt3243x.c new file mode 100644 index 000000000000..50003ad2e589 --- /dev/null +++ b/drivers/gpio/gpio-idt3243x.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Driver for IDT/Renesas 79RC3243x Interrupt Controller */ + +#include <linux/bitops.h> +#include <linux/gpio/driver.h> +#include <linux/irq.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/platform_device.h> +#include <linux/spinlock.h> + +#define IDT_PIC_IRQ_PEND 0x00 +#define IDT_PIC_IRQ_MASK 0x08 + +#define IDT_GPIO_DIR 0x00 +#define IDT_GPIO_DATA 0x04 +#define IDT_GPIO_ILEVEL 0x08 +#define IDT_GPIO_ISTAT 0x0C + +struct idt_gpio_ctrl { + struct gpio_chip gc; + void __iomem *pic; + void __iomem *gpio; + u32 mask_cache; +}; + +static void idt_gpio_dispatch(struct irq_desc *desc) +{ + struct gpio_chip *gc = irq_desc_get_handler_data(desc); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + struct irq_chip *host_chip = irq_desc_get_chip(desc); + unsigned int bit, virq; + unsigned long pending; + + chained_irq_enter(host_chip, desc); + + pending = readl(ctrl->pic + IDT_PIC_IRQ_PEND); + pending &= ~ctrl->mask_cache; + for_each_set_bit(bit, &pending, gc->ngpio) { + virq = irq_linear_revmap(gc->irq.domain, bit); + if (virq) + generic_handle_irq(virq); + } + + chained_irq_exit(host_chip, desc); +} + +static int idt_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + unsigned int sense = flow_type & IRQ_TYPE_SENSE_MASK; + unsigned long flags; + u32 ilevel; + + /* hardware only supports level triggered */ + if (sense == IRQ_TYPE_NONE || (sense & IRQ_TYPE_EDGE_BOTH)) + return -EINVAL; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + ilevel = readl(ctrl->gpio + IDT_GPIO_ILEVEL); + if (sense & IRQ_TYPE_LEVEL_HIGH) + ilevel |= BIT(d->hwirq); + else if (sense & IRQ_TYPE_LEVEL_LOW) + ilevel &= ~BIT(d->hwirq); + + writel(ilevel, ctrl->gpio + IDT_GPIO_ILEVEL); + irq_set_handler_locked(d, handle_level_irq); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); + return 0; +} + +static void idt_gpio_ack(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + + writel(~BIT(d->hwirq), ctrl->gpio + IDT_GPIO_ISTAT); +} + +static void idt_gpio_mask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + unsigned long flags; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + ctrl->mask_cache |= BIT(d->hwirq); + writel(ctrl->mask_cache, ctrl->pic + IDT_PIC_IRQ_MASK); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); +} + +static void idt_gpio_unmask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + unsigned long flags; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + ctrl->mask_cache &= ~BIT(d->hwirq); + writel(ctrl->mask_cache, ctrl->pic + IDT_PIC_IRQ_MASK); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); +} + +static int idt_gpio_irq_init_hw(struct gpio_chip *gc) +{ + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + + /* Mask interrupts. */ + ctrl->mask_cache = 0xffffffff; + writel(ctrl->mask_cache, ctrl->pic + IDT_PIC_IRQ_MASK); + + return 0; +} + +static struct irq_chip idt_gpio_irqchip = { + .name = "IDTGPIO", + .irq_mask = idt_gpio_mask, + .irq_ack = idt_gpio_ack, + .irq_unmask = idt_gpio_unmask, + .irq_set_type = idt_gpio_irq_set_type +}; + +static int idt_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct gpio_irq_chip *girq; + struct idt_gpio_ctrl *ctrl; + unsigned int parent_irq; + int ngpios; + int ret; + + + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); + if (!ctrl) + return -ENOMEM; + + ctrl->gpio = devm_platform_ioremap_resource_byname(pdev, "gpio"); + if (IS_ERR(ctrl->gpio)) + return PTR_ERR(ctrl->gpio); + + ctrl->gc.parent = dev; + + ret = bgpio_init(&ctrl->gc, &pdev->dev, 4, ctrl->gpio + IDT_GPIO_DATA, + NULL, NULL, ctrl->gpio + IDT_GPIO_DIR, NULL, 0); + if (ret) { + dev_err(dev, "bgpio_init failed\n"); + return ret; + } + + ret = device_property_read_u32(dev, "ngpios", &ngpios); + if (!ret) + ctrl->gc.ngpio = ngpios; + + if (device_property_read_bool(dev, "interrupt-controller")) { + ctrl->pic = devm_platform_ioremap_resource_byname(pdev, "pic"); + if (IS_ERR(ctrl->pic)) + return PTR_ERR(ctrl->pic); + + parent_irq = platform_get_irq(pdev, 0); + if (!parent_irq) + return -EINVAL; + + girq = &ctrl->gc.irq; + girq->chip = &idt_gpio_irqchip; + girq->init_hw = idt_gpio_irq_init_hw; + girq->parent_handler = idt_gpio_dispatch; + girq->num_parents = 1; + girq->parents = devm_kcalloc(dev, girq->num_parents, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + + girq->parents[0] = parent_irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + } + + return devm_gpiochip_add_data(&pdev->dev, &ctrl->gc, ctrl); +} + +static const struct of_device_id idt_gpio_of_match[] = { + { .compatible = "idt,32434-gpio" }, + { } +}; +MODULE_DEVICE_TABLE(of, idt_gpio_of_match); + +static struct platform_driver idt_gpio_driver = { + .probe = idt_gpio_probe, + .driver = { + .name = "idt3243x-gpio", + .of_match_table = idt_gpio_of_match, + }, +}; +module_platform_driver(idt_gpio_driver); + +MODULE_DESCRIPTION("IDT 79RC3243x GPIO/PIC Driver"); +MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-logicvc.c b/drivers/gpio/gpio-logicvc.c index 015632cf159f..992cc958a43f 100644 --- a/drivers/gpio/gpio-logicvc.c +++ b/drivers/gpio/gpio-logicvc.c @@ -114,10 +114,8 @@ static int logicvc_gpio_probe(struct platform_device *pdev) } base = devm_ioremap_resource(dev, &res); - if (IS_ERR(base)) { - dev_err(dev, "Failed to map I/O base\n"); + if (IS_ERR(base)) return PTR_ERR(base); - } logicvc_gpio_regmap_config.max_register = resource_size(&res) - logicvc_gpio_regmap_config.reg_stride; diff --git a/drivers/gpio/gpio-lp87565.c b/drivers/gpio/gpio-lp87565.c index e1244520cf7d..fcde6708b5df 100644 --- a/drivers/gpio/gpio-lp87565.c +++ b/drivers/gpio/gpio-lp87565.c @@ -123,14 +123,14 @@ static int lp87565_gpio_set_config(struct gpio_chip *gc, unsigned int offset, return regmap_update_bits(gpio->map, LP87565_REG_GPIO_CONFIG, BIT(offset + - __ffs(LP87565_GOIO1_OD)), + __ffs(LP87565_GPIO1_OD)), BIT(offset + - __ffs(LP87565_GOIO1_OD))); + __ffs(LP87565_GPIO1_OD))); case PIN_CONFIG_DRIVE_PUSH_PULL: return regmap_update_bits(gpio->map, LP87565_REG_GPIO_CONFIG, BIT(offset + - __ffs(LP87565_GOIO1_OD)), 0); + __ffs(LP87565_GPIO1_OD)), 0); default: return -ENOTSUPP; } diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index d7e73876a3b9..0a9d746a0fe0 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -144,12 +144,9 @@ static void gpio_mockup_set_multiple(struct gpio_chip *gc, static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip, unsigned int offset, int value) { + struct gpio_chip *gc = &chip->gc; + struct gpio_desc *desc = gpiochip_get_desc(gc, offset); int curr, irq, irq_type, ret = 0; - struct gpio_desc *desc; - struct gpio_chip *gc; - - gc = &chip->gc; - desc = &gc->gpiodev->descs[offset]; mutex_lock(&chip->lock); @@ -369,7 +366,7 @@ static void gpio_mockup_debugfs_setup(struct device *dev, priv->chip = chip; priv->offset = i; - priv->desc = &gc->gpiodev->descs[i]; + priv->desc = gpiochip_get_desc(gc, i); debugfs_create_file(name, 0200, chip->dbg_dir, priv, &gpio_mockup_debugfs_ops); diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 524b668eb1ac..31a336b86ff2 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -229,14 +229,14 @@ static int mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base) return rv; } -static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset) +static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned int offset) { struct mxs_gpio_port *port = gpiochip_get_data(gc); return irq_find_mapping(port->domain, offset); } -static int mxs_gpio_get_direction(struct gpio_chip *gc, unsigned offset) +static int mxs_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) { struct mxs_gpio_port *port = gpiochip_get_data(gc); u32 mask = 1 << offset; diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index c91d05651596..f5cfc0698799 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -1241,6 +1241,7 @@ static const struct of_device_id pca953x_dt_ids[] = { { .compatible = "onnn,cat9554", .data = OF_953X( 8, PCA_INT), }, { .compatible = "onnn,pca9654", .data = OF_953X( 8, PCA_INT), }, + { .compatible = "onnn,pca9655", .data = OF_953X(16, PCA_INT), }, { .compatible = "exar,xra1202", .data = OF_953X( 8, 0), }, { } diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c index 134cedf151a7..69c219742083 100644 --- a/drivers/gpio/gpio-regmap.c +++ b/drivers/gpio/gpio-regmap.c @@ -178,12 +178,6 @@ static int gpio_regmap_direction_output(struct gpio_chip *chip, return gpio_regmap_set_direction(chip, offset, true); } -void gpio_regmap_set_drvdata(struct gpio_regmap *gpio, void *data) -{ - gpio->driver_data = data; -} -EXPORT_SYMBOL_GPL(gpio_regmap_set_drvdata); - void *gpio_regmap_get_drvdata(struct gpio_regmap *gpio) { return gpio->driver_data; @@ -226,6 +220,7 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config return ERR_PTR(-ENOMEM); gpio->parent = config->parent; + gpio->driver_data = config->drvdata; gpio->regmap = config->regmap; gpio->ngpio_per_reg = config->ngpio_per_reg; gpio->reg_stride = config->reg_stride; @@ -311,9 +306,9 @@ void gpio_regmap_unregister(struct gpio_regmap *gpio) } EXPORT_SYMBOL_GPL(gpio_regmap_unregister); -static void devm_gpio_regmap_unregister(struct device *dev, void *res) +static void devm_gpio_regmap_unregister(void *res) { - gpio_regmap_unregister(*(struct gpio_regmap **)res); + gpio_regmap_unregister(res); } /** @@ -330,20 +325,17 @@ static void devm_gpio_regmap_unregister(struct device *dev, void *res) struct gpio_regmap *devm_gpio_regmap_register(struct device *dev, const struct gpio_regmap_config *config) { - struct gpio_regmap **ptr, *gpio; - - ptr = devres_alloc(devm_gpio_regmap_unregister, sizeof(*ptr), - GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); + struct gpio_regmap *gpio; + int ret; gpio = gpio_regmap_register(config); - if (!IS_ERR(gpio)) { - *ptr = gpio; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } + + if (IS_ERR(gpio)) + return gpio; + + ret = devm_add_action_or_reset(dev, devm_gpio_regmap_unregister, gpio); + if (ret) + return ERR_PTR(ret); return gpio; } diff --git a/drivers/gpio/gpio-spear-spics.c b/drivers/gpio/gpio-spear-spics.c index 6eca531b7d96..49aac2bb8d2c 100644 --- a/drivers/gpio/gpio-spear-spics.c +++ b/drivers/gpio/gpio-spear-spics.c @@ -122,7 +122,6 @@ static int spics_gpio_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct spear_spics *spics; - int ret; spics = devm_kzalloc(&pdev->dev, sizeof(*spics), GFP_KERNEL); if (!spics) @@ -148,8 +147,6 @@ static int spics_gpio_probe(struct platform_device *pdev) &spics->cs_enable_shift)) goto err_dt_data; - platform_set_drvdata(pdev, spics); - spics->chip.ngpio = NUM_OF_GPIO; spics->chip.base = -1; spics->chip.request = spics_request; @@ -163,14 +160,7 @@ static int spics_gpio_probe(struct platform_device *pdev) spics->chip.owner = THIS_MODULE; spics->last_off = -1; - ret = devm_gpiochip_add_data(&pdev->dev, &spics->chip, spics); - if (ret) { - dev_err(&pdev->dev, "unable to add gpio chip\n"); - return ret; - } - - dev_info(&pdev->dev, "spear spics registered\n"); - return 0; + return devm_gpiochip_add_data(&pdev->dev, &spics->chip, spics); err_dt_data: dev_err(&pdev->dev, "DT probe failed\n"); diff --git a/drivers/gpio/gpio-sprd.c b/drivers/gpio/gpio-sprd.c index 36ea8a3bd451..25c37edcbc6c 100644 --- a/drivers/gpio/gpio-sprd.c +++ b/drivers/gpio/gpio-sprd.c @@ -222,7 +222,6 @@ static int sprd_gpio_probe(struct platform_device *pdev) { struct gpio_irq_chip *irq; struct sprd_gpio *sprd_gpio; - int ret; sprd_gpio = devm_kzalloc(&pdev->dev, sizeof(*sprd_gpio), GFP_KERNEL); if (!sprd_gpio) @@ -259,14 +258,7 @@ static int sprd_gpio_probe(struct platform_device *pdev) irq->num_parents = 1; irq->parents = &sprd_gpio->irq; - ret = devm_gpiochip_add_data(&pdev->dev, &sprd_gpio->chip, sprd_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, sprd_gpio); - return 0; + return devm_gpiochip_add_data(&pdev->dev, &sprd_gpio->chip, sprd_gpio); } static const struct of_device_id sprd_gpio_of_match[] = { diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c index a74bb97a41e2..392fcab06ab8 100644 --- a/drivers/gpio/gpio-sta2x11.c +++ b/drivers/gpio/gpio-sta2x11.c @@ -398,15 +398,7 @@ static int gsta_probe(struct platform_device *dev) return err; } - err = devm_gpiochip_add_data(&dev->dev, &chip->gpio, chip); - if (err < 0) { - dev_err(&dev->dev, "sta2x11 gpio: Can't register (%i)\n", - -err); - return err; - } - - platform_set_drvdata(dev, chip); - return 0; + return devm_gpiochip_add_data(&dev->dev, &chip->gpio, chip); } static struct platform_driver sta2x11_gpio_platform_driver = { diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index b94ef8181428..dd4d58b4ae49 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c @@ -449,6 +449,11 @@ static void stmpe_init_irq_valid_mask(struct gpio_chip *gc, } } +static void stmpe_gpio_disable(void *stmpe) +{ + stmpe_disable(stmpe, STMPE_BLOCK_GPIO); +} + static int stmpe_gpio_probe(struct platform_device *pdev) { struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); @@ -461,7 +466,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev) return -EINVAL; } - stmpe_gpio = kzalloc(sizeof(*stmpe_gpio), GFP_KERNEL); + stmpe_gpio = devm_kzalloc(&pdev->dev, sizeof(*stmpe_gpio), GFP_KERNEL); if (!stmpe_gpio) return -ENOMEM; @@ -489,7 +494,11 @@ static int stmpe_gpio_probe(struct platform_device *pdev) ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO); if (ret) - goto out_free; + return ret; + + ret = devm_add_action_or_reset(&pdev->dev, stmpe_gpio_disable, stmpe); + if (ret) + return ret; if (irq > 0) { struct gpio_irq_chip *girq; @@ -499,7 +508,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev) "stmpe-gpio", stmpe_gpio); if (ret) { dev_err(&pdev->dev, "unable to get irq: %d\n", ret); - goto out_disable; + return ret; } girq = &stmpe_gpio->chip.irq; @@ -514,22 +523,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev) girq->init_valid_mask = stmpe_init_irq_valid_mask; } - ret = gpiochip_add_data(&stmpe_gpio->chip, stmpe_gpio); - if (ret) { - dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); - goto out_disable; - } - - platform_set_drvdata(pdev, stmpe_gpio); - - return 0; - -out_disable: - stmpe_disable(stmpe, STMPE_BLOCK_GPIO); - gpiochip_remove(&stmpe_gpio->chip); -out_free: - kfree(stmpe_gpio); - return ret; + return devm_gpiochip_add_data(&pdev->dev, &stmpe_gpio->chip, stmpe_gpio); } static struct platform_driver stmpe_gpio_driver = { diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 55b8dbd13d11..8d158492488f 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c @@ -357,16 +357,7 @@ static int tc3589x_gpio_probe(struct platform_device *pdev) return ret; } - ret = devm_gpiochip_add_data(&pdev->dev, &tc3589x_gpio->chip, - tc3589x_gpio); - if (ret) { - dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tc3589x_gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &tc3589x_gpio->chip, tc3589x_gpio); } static struct platform_driver tc3589x_gpio_driver = { diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index 05974b760796..d38980b9923a 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -730,18 +730,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev) offset += port->pins; } - platform_set_drvdata(pdev, gpio); - - err = devm_gpiochip_add_data(&pdev->dev, &gpio->gpio, gpio); - if (err < 0) - return err; - - return 0; -} - -static int tegra186_gpio_remove(struct platform_device *pdev) -{ - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gpio, gpio); } #define TEGRA186_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \ @@ -913,7 +902,6 @@ static struct platform_driver tegra186_gpio_driver = { .of_match_table = tegra186_gpio_of_match, }, .probe = tegra186_gpio_probe, - .remove = tegra186_gpio_remove, }; module_platform_driver(tegra186_gpio_driver); diff --git a/drivers/gpio/gpio-tps65218.c b/drivers/gpio/gpio-tps65218.c index 43a1150055ce..3517debe2b0b 100644 --- a/drivers/gpio/gpio-tps65218.c +++ b/drivers/gpio/gpio-tps65218.c @@ -187,7 +187,6 @@ static int tps65218_gpio_probe(struct platform_device *pdev) { struct tps65218 *tps65218 = dev_get_drvdata(pdev->dev.parent); struct tps65218_gpio *tps65218_gpio; - int ret; tps65218_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps65218_gpio), GFP_KERNEL); @@ -201,16 +200,8 @@ static int tps65218_gpio_probe(struct platform_device *pdev) tps65218_gpio->gpio_chip.of_node = pdev->dev.of_node; #endif - ret = devm_gpiochip_add_data(&pdev->dev, &tps65218_gpio->gpio_chip, - tps65218_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tps65218_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &tps65218_gpio->gpio_chip, + tps65218_gpio); } static const struct of_device_id tps65218_dt_match[] = { diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c index 9b6cc74f47c8..da0304b764a5 100644 --- a/drivers/gpio/gpio-tps6586x.c +++ b/drivers/gpio/gpio-tps6586x.c @@ -76,7 +76,6 @@ static int tps6586x_gpio_probe(struct platform_device *pdev) { struct tps6586x_platform_data *pdata; struct tps6586x_gpio *tps6586x_gpio; - int ret; pdata = dev_get_platdata(pdev->dev.parent); tps6586x_gpio = devm_kzalloc(&pdev->dev, @@ -106,16 +105,8 @@ static int tps6586x_gpio_probe(struct platform_device *pdev) else tps6586x_gpio->gpio_chip.base = -1; - ret = devm_gpiochip_add_data(&pdev->dev, &tps6586x_gpio->gpio_chip, - tps6586x_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tps6586x_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &tps6586x_gpio->gpio_chip, + tps6586x_gpio); } static struct platform_driver tps6586x_gpio_driver = { diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c index 0c0b445c75c0..7fa8c841081f 100644 --- a/drivers/gpio/gpio-tps65910.c +++ b/drivers/gpio/gpio-tps65910.c @@ -165,16 +165,8 @@ static int tps65910_gpio_probe(struct platform_device *pdev) } skip_init: - ret = devm_gpiochip_add_data(&pdev->dev, &tps65910_gpio->gpio_chip, - tps65910_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tps65910_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &tps65910_gpio->gpio_chip, + tps65910_gpio); } static struct platform_driver tps65910_gpio_driver = { diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c index 510d9ed9fd2a..fab771cb6a87 100644 --- a/drivers/gpio/gpio-tps65912.c +++ b/drivers/gpio/gpio-tps65912.c @@ -99,7 +99,6 @@ static int tps65912_gpio_probe(struct platform_device *pdev) { struct tps65912 *tps = dev_get_drvdata(pdev->dev.parent); struct tps65912_gpio *gpio; - int ret; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) @@ -109,16 +108,7 @@ static int tps65912_gpio_probe(struct platform_device *pdev) gpio->gpio_chip = template_chip; gpio->gpio_chip.parent = tps->dev; - ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gpio_chip, - gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gpio_chip, gpio); } static const struct platform_device_id tps65912_gpio_id_table[] = { diff --git a/drivers/gpio/gpio-tps68470.c b/drivers/gpio/gpio-tps68470.c index f7f5f770e0fb..423b7bc30ae8 100644 --- a/drivers/gpio/gpio-tps68470.c +++ b/drivers/gpio/gpio-tps68470.c @@ -125,7 +125,6 @@ static const char *tps68470_names[TPS68470_N_GPIO] = { static int tps68470_gpio_probe(struct platform_device *pdev) { struct tps68470_gpio_data *tps68470_gpio; - int ret; tps68470_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps68470_gpio), GFP_KERNEL); @@ -146,16 +145,7 @@ static int tps68470_gpio_probe(struct platform_device *pdev) tps68470_gpio->gc.base = -1; tps68470_gpio->gc.parent = &pdev->dev; - ret = devm_gpiochip_add_data(&pdev->dev, &tps68470_gpio->gc, - tps68470_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to register gpio_chip: %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tps68470_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &tps68470_gpio->gc, tps68470_gpio); } static struct platform_driver tps68470_gpio_driver = { diff --git a/drivers/gpio/gpio-visconti.c b/drivers/gpio/gpio-visconti.c index 0e3d19828eb1..47455810bdb9 100644 --- a/drivers/gpio/gpio-visconti.c +++ b/drivers/gpio/gpio-visconti.c @@ -187,15 +187,7 @@ static int visconti_gpio_probe(struct platform_device *pdev) girq->default_type = IRQ_TYPE_NONE; girq->handler = handle_level_irq; - ret = devm_gpiochip_add_data(dev, &priv->gpio_chip, priv); - if (ret) { - dev_err(dev, "failed to add GPIO chip\n"); - return ret; - } - - platform_set_drvdata(pdev, priv); - - return ret; + return devm_gpiochip_add_data(dev, &priv->gpio_chip, priv); } static const struct of_device_id visconti_gpio_of_match[] = { diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c index a3a32a77041f..9cf1e5ebb352 100644 --- a/drivers/gpio/gpio-wm831x.c +++ b/drivers/gpio/gpio-wm831x.c @@ -261,7 +261,6 @@ static int wm831x_gpio_probe(struct platform_device *pdev) struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = &wm831x->pdata; struct wm831x_gpio *wm831x_gpio; - int ret; wm831x_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm831x_gpio), GFP_KERNEL); @@ -280,16 +279,7 @@ static int wm831x_gpio_probe(struct platform_device *pdev) wm831x_gpio->gpio_chip.of_node = wm831x->dev->of_node; #endif - ret = devm_gpiochip_add_data(&pdev->dev, &wm831x_gpio->gpio_chip, - wm831x_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, wm831x_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &wm831x_gpio->gpio_chip, wm831x_gpio); } static struct platform_driver wm831x_gpio_driver = { diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c index 460f0a4b04bd..b1b131fb9804 100644 --- a/drivers/gpio/gpio-wm8350.c +++ b/drivers/gpio/gpio-wm8350.c @@ -105,7 +105,6 @@ static int wm8350_gpio_probe(struct platform_device *pdev) struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent); struct wm8350_platform_data *pdata = dev_get_platdata(wm8350->dev); struct wm8350_gpio_data *wm8350_gpio; - int ret; wm8350_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm8350_gpio), GFP_KERNEL); @@ -121,16 +120,7 @@ static int wm8350_gpio_probe(struct platform_device *pdev) else wm8350_gpio->gpio_chip.base = -1; - ret = devm_gpiochip_add_data(&pdev->dev, &wm8350_gpio->gpio_chip, - wm8350_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, wm8350_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &wm8350_gpio->gpio_chip, wm8350_gpio); } static struct platform_driver wm8350_gpio_driver = { diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c index 9af89cf7f6bc..f4a474cef32d 100644 --- a/drivers/gpio/gpio-wm8994.c +++ b/drivers/gpio/gpio-wm8994.c @@ -263,7 +263,6 @@ static int wm8994_gpio_probe(struct platform_device *pdev) struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent); struct wm8994_pdata *pdata = dev_get_platdata(wm8994->dev); struct wm8994_gpio *wm8994_gpio; - int ret; wm8994_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm8994_gpio), GFP_KERNEL); @@ -279,17 +278,7 @@ static int wm8994_gpio_probe(struct platform_device *pdev) else wm8994_gpio->gpio_chip.base = -1; - ret = devm_gpiochip_add_data(&pdev->dev, &wm8994_gpio->gpio_chip, - wm8994_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", - ret); - return ret; - } - - platform_set_drvdata(pdev, wm8994_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &wm8994_gpio->gpio_chip, wm8994_gpio); } static struct platform_driver wm8994_gpio_driver = { diff --git a/drivers/gpio/gpio-xgene.c b/drivers/gpio/gpio-xgene.c index 532b0df8a1f2..fb4b0c67aeef 100644 --- a/drivers/gpio/gpio-xgene.c +++ b/drivers/gpio/gpio-xgene.c @@ -159,7 +159,6 @@ static SIMPLE_DEV_PM_OPS(xgene_gpio_pm, xgene_gpio_suspend, xgene_gpio_resume); static int xgene_gpio_probe(struct platform_device *pdev) { struct xgene_gpio *gpio; - int err = 0; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) @@ -183,15 +182,7 @@ static int xgene_gpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, gpio); - err = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); - if (err) { - dev_err(&pdev->dev, - "failed to register gpiochip.\n"); - return err; - } - - dev_info(&pdev->dev, "X-Gene GPIO driver registered.\n"); - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); } static const struct of_device_id xgene_gpio_of_match[] = { diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index 136557e7dd3c..c329c3a606e8 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -5,6 +5,7 @@ * Copyright 2008 - 2013 Xilinx, Inc. */ +#include <linux/bitmap.h> #include <linux/bitops.h> #include <linux/clk.h> #include <linux/errno.h> @@ -23,7 +24,8 @@ #define XGPIO_DATA_OFFSET (0x0) /* Data register */ #define XGPIO_TRI_OFFSET (0x4) /* I/O direction register */ -#define XGPIO_CHANNEL_OFFSET 0x8 +#define XGPIO_CHANNEL0_OFFSET 0x0 +#define XGPIO_CHANNEL1_OFFSET 0x8 #define XGPIO_GIER_OFFSET 0x11c /* Global Interrupt Enable */ #define XGPIO_GIER_IE BIT(31) @@ -43,56 +45,101 @@ * struct xgpio_instance - Stores information about GPIO device * @gc: GPIO chip * @regs: register block - * @gpio_width: GPIO width for every channel - * @gpio_state: GPIO write state shadow register - * @gpio_last_irq_read: GPIO read state register from last interrupt - * @gpio_dir: GPIO direction shadow register + * @hw_map: GPIO pin mapping on hardware side + * @sw_map: GPIO pin mapping on software side + * @state: GPIO write state shadow register + * @last_irq_read: GPIO read state register from last interrupt + * @dir: GPIO direction shadow register * @gpio_lock: Lock used for synchronization * @irq: IRQ used by GPIO device * @irqchip: IRQ chip - * @irq_enable: GPIO IRQ enable/disable bitfield - * @irq_rising_edge: GPIO IRQ rising edge enable/disable bitfield - * @irq_falling_edge: GPIO IRQ falling edge enable/disable bitfield + * @enable: GPIO IRQ enable/disable bitfield + * @rising_edge: GPIO IRQ rising edge enable/disable bitfield + * @falling_edge: GPIO IRQ falling edge enable/disable bitfield * @clk: clock resource for this driver */ struct xgpio_instance { struct gpio_chip gc; void __iomem *regs; - unsigned int gpio_width[2]; - u32 gpio_state[2]; - u32 gpio_last_irq_read[2]; - u32 gpio_dir[2]; + DECLARE_BITMAP(hw_map, 64); + DECLARE_BITMAP(sw_map, 64); + DECLARE_BITMAP(state, 64); + DECLARE_BITMAP(last_irq_read, 64); + DECLARE_BITMAP(dir, 64); spinlock_t gpio_lock; /* For serializing operations */ int irq; struct irq_chip irqchip; - u32 irq_enable[2]; - u32 irq_rising_edge[2]; - u32 irq_falling_edge[2]; + DECLARE_BITMAP(enable, 64); + DECLARE_BITMAP(rising_edge, 64); + DECLARE_BITMAP(falling_edge, 64); struct clk *clk; }; -static inline int xgpio_index(struct xgpio_instance *chip, int gpio) +static inline int xgpio_from_bit(struct xgpio_instance *chip, int bit) { - if (gpio >= chip->gpio_width[0]) - return 1; + return bitmap_bitremap(bit, chip->hw_map, chip->sw_map, 64); +} - return 0; +static inline int xgpio_to_bit(struct xgpio_instance *chip, int gpio) +{ + return bitmap_bitremap(gpio, chip->sw_map, chip->hw_map, 64); } -static inline int xgpio_regoffset(struct xgpio_instance *chip, int gpio) +static inline u32 xgpio_get_value32(const unsigned long *map, int bit) { - if (xgpio_index(chip, gpio)) - return XGPIO_CHANNEL_OFFSET; + const size_t index = BIT_WORD(bit); + const unsigned long offset = (bit % BITS_PER_LONG) & BIT(5); - return 0; + return (map[index] >> offset) & 0xFFFFFFFFul; +} + +static inline void xgpio_set_value32(unsigned long *map, int bit, u32 v) +{ + const size_t index = BIT_WORD(bit); + const unsigned long offset = (bit % BITS_PER_LONG) & BIT(5); + + map[index] &= ~(0xFFFFFFFFul << offset); + map[index] |= v << offset; +} + +static inline int xgpio_regoffset(struct xgpio_instance *chip, int ch) +{ + switch (ch) { + case 0: + return XGPIO_CHANNEL0_OFFSET; + case 1: + return XGPIO_CHANNEL1_OFFSET; + default: + return -EINVAL; + } } -static inline int xgpio_offset(struct xgpio_instance *chip, int gpio) +static void xgpio_read_ch(struct xgpio_instance *chip, int reg, int bit, unsigned long *a) { - if (xgpio_index(chip, gpio)) - return gpio - chip->gpio_width[0]; + void __iomem *addr = chip->regs + reg + xgpio_regoffset(chip, bit / 32); + xgpio_set_value32(a, bit, xgpio_readreg(addr)); +} + +static void xgpio_write_ch(struct xgpio_instance *chip, int reg, int bit, unsigned long *a) +{ + void __iomem *addr = chip->regs + reg + xgpio_regoffset(chip, bit / 32); + xgpio_writereg(addr, xgpio_get_value32(a, bit)); +} + +static void xgpio_read_ch_all(struct xgpio_instance *chip, int reg, unsigned long *a) +{ + int bit, lastbit = xgpio_to_bit(chip, chip->gc.ngpio - 1); + + for (bit = 0; bit <= lastbit ; bit += 32) + xgpio_read_ch(chip, reg, bit, a); +} + +static void xgpio_write_ch_all(struct xgpio_instance *chip, int reg, unsigned long *a) +{ + int bit, lastbit = xgpio_to_bit(chip, chip->gc.ngpio - 1); - return gpio; + for (bit = 0; bit <= lastbit ; bit += 32) + xgpio_write_ch(chip, reg, bit, a); } /** @@ -109,12 +156,12 @@ static inline int xgpio_offset(struct xgpio_instance *chip, int gpio) static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) { struct xgpio_instance *chip = gpiochip_get_data(gc); - u32 val; + int bit = xgpio_to_bit(chip, gpio); + DECLARE_BITMAP(state, 64); - val = xgpio_readreg(chip->regs + XGPIO_DATA_OFFSET + - xgpio_regoffset(chip, gpio)); + xgpio_read_ch(chip, XGPIO_DATA_OFFSET, bit, state); - return !!(val & BIT(xgpio_offset(chip, gpio))); + return test_bit(bit, state); } /** @@ -130,19 +177,14 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { unsigned long flags; struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, gpio); - int offset = xgpio_offset(chip, gpio); + int bit = xgpio_to_bit(chip, gpio); spin_lock_irqsave(&chip->gpio_lock, flags); /* Write to GPIO signal and set its direction to output */ - if (val) - chip->gpio_state[index] |= BIT(offset); - else - chip->gpio_state[index] &= ~BIT(offset); + __assign_bit(bit, chip->state, val); - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_state[index]); + xgpio_write_ch(chip, XGPIO_DATA_OFFSET, bit, chip->state); spin_unlock_irqrestore(&chip->gpio_lock, flags); } @@ -159,37 +201,22 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, unsigned long *bits) { + DECLARE_BITMAP(hw_mask, 64); + DECLARE_BITMAP(hw_bits, 64); + DECLARE_BITMAP(state, 64); unsigned long flags; struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, 0); - int offset, i; + + bitmap_remap(hw_mask, mask, chip->sw_map, chip->hw_map, 64); + bitmap_remap(hw_bits, bits, chip->sw_map, chip->hw_map, 64); spin_lock_irqsave(&chip->gpio_lock, flags); - /* Write to GPIO signals */ - for (i = 0; i < gc->ngpio; i++) { - if (*mask == 0) - break; - /* Once finished with an index write it out to the register */ - if (index != xgpio_index(chip, i)) { - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + - index * XGPIO_CHANNEL_OFFSET, - chip->gpio_state[index]); - spin_unlock_irqrestore(&chip->gpio_lock, flags); - index = xgpio_index(chip, i); - spin_lock_irqsave(&chip->gpio_lock, flags); - } - if (__test_and_clear_bit(i, mask)) { - offset = xgpio_offset(chip, i); - if (test_bit(i, bits)) - chip->gpio_state[index] |= BIT(offset); - else - chip->gpio_state[index] &= ~BIT(offset); - } - } + bitmap_replace(state, chip->state, hw_bits, hw_mask, 64); + + xgpio_write_ch_all(chip, XGPIO_DATA_OFFSET, state); - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + - index * XGPIO_CHANNEL_OFFSET, chip->gpio_state[index]); + bitmap_copy(chip->state, state, 64); spin_unlock_irqrestore(&chip->gpio_lock, flags); } @@ -207,15 +234,13 @@ static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) { unsigned long flags; struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, gpio); - int offset = xgpio_offset(chip, gpio); + int bit = xgpio_to_bit(chip, gpio); spin_lock_irqsave(&chip->gpio_lock, flags); /* Set the GPIO bit in shadow register and set direction as input */ - chip->gpio_dir[index] |= BIT(offset); - xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_dir[index]); + __set_bit(bit, chip->dir); + xgpio_write_ch(chip, XGPIO_TRI_OFFSET, bit, chip->dir); spin_unlock_irqrestore(&chip->gpio_lock, flags); @@ -238,23 +263,17 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { unsigned long flags; struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, gpio); - int offset = xgpio_offset(chip, gpio); + int bit = xgpio_to_bit(chip, gpio); spin_lock_irqsave(&chip->gpio_lock, flags); /* Write state of GPIO signal */ - if (val) - chip->gpio_state[index] |= BIT(offset); - else - chip->gpio_state[index] &= ~BIT(offset); - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_state[index]); + __assign_bit(bit, chip->state, val); + xgpio_write_ch(chip, XGPIO_DATA_OFFSET, bit, chip->state); /* Clear the GPIO bit in shadow register and set direction as output */ - chip->gpio_dir[index] &= ~BIT(offset); - xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_dir[index]); + __clear_bit(bit, chip->dir); + xgpio_write_ch(chip, XGPIO_TRI_OFFSET, bit, chip->dir); spin_unlock_irqrestore(&chip->gpio_lock, flags); @@ -267,16 +286,8 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) */ static void xgpio_save_regs(struct xgpio_instance *chip) { - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET, chip->gpio_state[0]); - xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET, chip->gpio_dir[0]); - - if (!chip->gpio_width[1]) - return; - - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + XGPIO_CHANNEL_OFFSET, - chip->gpio_state[1]); - xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET + XGPIO_CHANNEL_OFFSET, - chip->gpio_dir[1]); + xgpio_write_ch_all(chip, XGPIO_DATA_OFFSET, chip->state); + xgpio_write_ch_all(chip, XGPIO_TRI_OFFSET, chip->dir); } static int xgpio_request(struct gpio_chip *chip, unsigned int offset) @@ -302,8 +313,8 @@ static int __maybe_unused xgpio_suspend(struct device *dev) struct irq_data *data = irq_get_irq_data(gpio->irq); if (!data) { - dev_err(dev, "irq_get_irq_data() failed\n"); - return -EINVAL; + dev_dbg(dev, "IRQ not connected\n"); + return pm_runtime_force_suspend(dev); } if (!irqd_is_wakeup_set(data)) @@ -348,8 +359,8 @@ static int __maybe_unused xgpio_resume(struct device *dev) struct irq_data *data = irq_get_irq_data(gpio->irq); if (!data) { - dev_err(dev, "irq_get_irq_data() failed\n"); - return -EINVAL; + dev_dbg(dev, "IRQ not connected\n"); + return pm_runtime_force_resume(dev); } if (!irqd_is_wakeup_set(data)) @@ -391,18 +402,17 @@ static void xgpio_irq_mask(struct irq_data *irq_data) unsigned long flags; struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data); int irq_offset = irqd_to_hwirq(irq_data); - int index = xgpio_index(chip, irq_offset); - int offset = xgpio_offset(chip, irq_offset); + int bit = xgpio_to_bit(chip, irq_offset); + u32 mask = BIT(bit / 32), temp; spin_lock_irqsave(&chip->gpio_lock, flags); - chip->irq_enable[index] &= ~BIT(offset); + __clear_bit(bit, chip->enable); - if (!chip->irq_enable[index]) { + if (xgpio_get_value32(chip->enable, bit) == 0) { /* Disable per channel interrupt */ - u32 temp = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET); - - temp &= ~BIT(index); + temp = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET); + temp &= ~mask; xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, temp); } spin_unlock_irqrestore(&chip->gpio_lock, flags); @@ -417,30 +427,26 @@ static void xgpio_irq_unmask(struct irq_data *irq_data) unsigned long flags; struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data); int irq_offset = irqd_to_hwirq(irq_data); - int index = xgpio_index(chip, irq_offset); - int offset = xgpio_offset(chip, irq_offset); - u32 old_enable = chip->irq_enable[index]; + int bit = xgpio_to_bit(chip, irq_offset); + u32 old_enable = xgpio_get_value32(chip->enable, bit); + u32 mask = BIT(bit / 32), val; spin_lock_irqsave(&chip->gpio_lock, flags); - chip->irq_enable[index] |= BIT(offset); + __set_bit(bit, chip->enable); - if (!old_enable) { + if (old_enable == 0) { /* Clear any existing per-channel interrupts */ - u32 val = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET) & - BIT(index); - - if (val) - xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, val); + val = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET); + val &= mask; + xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, val); /* Update GPIO IRQ read data before enabling interrupt*/ - val = xgpio_readreg(chip->regs + XGPIO_DATA_OFFSET + - index * XGPIO_CHANNEL_OFFSET); - chip->gpio_last_irq_read[index] = val; + xgpio_read_ch(chip, XGPIO_DATA_OFFSET, bit, chip->last_irq_read); /* Enable per channel interrupt */ val = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET); - val |= BIT(index); + val |= mask; xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, val); } @@ -459,8 +465,7 @@ static int xgpio_set_irq_type(struct irq_data *irq_data, unsigned int type) { struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data); int irq_offset = irqd_to_hwirq(irq_data); - int index = xgpio_index(chip, irq_offset); - int offset = xgpio_offset(chip, irq_offset); + int bit = xgpio_to_bit(chip, irq_offset); /* * The Xilinx GPIO hardware provides a single interrupt status @@ -470,16 +475,16 @@ static int xgpio_set_irq_type(struct irq_data *irq_data, unsigned int type) */ switch (type & IRQ_TYPE_SENSE_MASK) { case IRQ_TYPE_EDGE_BOTH: - chip->irq_rising_edge[index] |= BIT(offset); - chip->irq_falling_edge[index] |= BIT(offset); + __set_bit(bit, chip->rising_edge); + __set_bit(bit, chip->falling_edge); break; case IRQ_TYPE_EDGE_RISING: - chip->irq_rising_edge[index] |= BIT(offset); - chip->irq_falling_edge[index] &= ~BIT(offset); + __set_bit(bit, chip->rising_edge); + __clear_bit(bit, chip->falling_edge); break; case IRQ_TYPE_EDGE_FALLING: - chip->irq_rising_edge[index] &= ~BIT(offset); - chip->irq_falling_edge[index] |= BIT(offset); + __clear_bit(bit, chip->rising_edge); + __set_bit(bit, chip->falling_edge); break; default: return -EINVAL; @@ -496,46 +501,44 @@ static int xgpio_set_irq_type(struct irq_data *irq_data, unsigned int type) static void xgpio_irqhandler(struct irq_desc *desc) { struct xgpio_instance *chip = irq_desc_get_handler_data(desc); + struct gpio_chip *gc = &chip->gc; struct irq_chip *irqchip = irq_desc_get_chip(desc); - u32 num_channels = chip->gpio_width[1] ? 2 : 1; - u32 offset = 0, index; - u32 status = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET); - + DECLARE_BITMAP(rising, 64); + DECLARE_BITMAP(falling, 64); + DECLARE_BITMAP(all, 64); + int irq_offset; + u32 status; + u32 bit; + + status = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET); xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, status); chained_irq_enter(irqchip, desc); - for (index = 0; index < num_channels; index++) { - if ((status & BIT(index))) { - unsigned long rising_events, falling_events, all_events; - unsigned long flags; - u32 data, bit; - unsigned int irq; - - spin_lock_irqsave(&chip->gpio_lock, flags); - data = xgpio_readreg(chip->regs + XGPIO_DATA_OFFSET + - index * XGPIO_CHANNEL_OFFSET); - rising_events = data & - ~chip->gpio_last_irq_read[index] & - chip->irq_enable[index] & - chip->irq_rising_edge[index]; - falling_events = ~data & - chip->gpio_last_irq_read[index] & - chip->irq_enable[index] & - chip->irq_falling_edge[index]; - dev_dbg(chip->gc.parent, - "IRQ chan %u rising 0x%lx falling 0x%lx\n", - index, rising_events, falling_events); - all_events = rising_events | falling_events; - chip->gpio_last_irq_read[index] = data; - spin_unlock_irqrestore(&chip->gpio_lock, flags); - - for_each_set_bit(bit, &all_events, 32) { - irq = irq_find_mapping(chip->gc.irq.domain, - offset + bit); - generic_handle_irq(irq); - } - } - offset += chip->gpio_width[index]; + + spin_lock(&chip->gpio_lock); + + xgpio_read_ch_all(chip, XGPIO_DATA_OFFSET, all); + + bitmap_complement(rising, chip->last_irq_read, 64); + bitmap_and(rising, rising, all, 64); + bitmap_and(rising, rising, chip->enable, 64); + bitmap_and(rising, rising, chip->rising_edge, 64); + + bitmap_complement(falling, all, 64); + bitmap_and(falling, falling, chip->last_irq_read, 64); + bitmap_and(falling, falling, chip->enable, 64); + bitmap_and(falling, falling, chip->falling_edge, 64); + + bitmap_copy(chip->last_irq_read, all, 64); + bitmap_or(all, rising, falling, 64); + + spin_unlock(&chip->gpio_lock); + + dev_dbg(gc->parent, "IRQ rising %*pb falling %*pb\n", 64, rising, 64, falling); + + for_each_set_bit(bit, all, 64) { + irq_offset = xgpio_from_bit(chip, bit); + generic_handle_irq(irq_find_mapping(gc->irq.domain, irq_offset)); } chained_irq_exit(irqchip, desc); @@ -556,6 +559,9 @@ static int xgpio_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; u32 is_dual = 0; u32 cells = 2; + u32 width[2]; + u32 state[2]; + u32 dir[2]; struct gpio_irq_chip *girq; u32 temp; @@ -565,13 +571,25 @@ static int xgpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, chip); + /* First, check if the device is dual-channel */ + of_property_read_u32(np, "xlnx,is-dual", &is_dual); + + /* Setup defaults */ + memset32(width, 0, ARRAY_SIZE(width)); + memset32(state, 0, ARRAY_SIZE(state)); + memset32(dir, 0xFFFFFFFF, ARRAY_SIZE(dir)); + /* Update GPIO state shadow register with default value */ - if (of_property_read_u32(np, "xlnx,dout-default", &chip->gpio_state[0])) - chip->gpio_state[0] = 0x0; + of_property_read_u32(np, "xlnx,dout-default", &state[0]); + of_property_read_u32(np, "xlnx,dout-default-2", &state[1]); + + bitmap_from_arr32(chip->state, state, 64); /* Update GPIO direction shadow register with default value */ - if (of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir[0])) - chip->gpio_dir[0] = 0xFFFFFFFF; + of_property_read_u32(np, "xlnx,tri-default", &dir[0]); + of_property_read_u32(np, "xlnx,tri-default-2", &dir[1]); + + bitmap_from_arr32(chip->dir, dir, 64); /* Update cells with gpio-cells value */ if (of_property_read_u32(np, "#gpio-cells", &cells)) @@ -586,42 +604,29 @@ static int xgpio_probe(struct platform_device *pdev) * Check device node and parent device node for device width * and assume default width of 32 */ - if (of_property_read_u32(np, "xlnx,gpio-width", &chip->gpio_width[0])) - chip->gpio_width[0] = 32; + if (of_property_read_u32(np, "xlnx,gpio-width", &width[0])) + width[0] = 32; - if (chip->gpio_width[0] > 32) + if (width[0] > 32) return -EINVAL; - spin_lock_init(&chip->gpio_lock); + if (is_dual && of_property_read_u32(np, "xlnx,gpio2-width", &width[1])) + width[1] = 32; - if (of_property_read_u32(np, "xlnx,is-dual", &is_dual)) - is_dual = 0; - - if (is_dual) { - /* Update GPIO state shadow register with default value */ - if (of_property_read_u32(np, "xlnx,dout-default-2", - &chip->gpio_state[1])) - chip->gpio_state[1] = 0x0; - - /* Update GPIO direction shadow register with default value */ - if (of_property_read_u32(np, "xlnx,tri-default-2", - &chip->gpio_dir[1])) - chip->gpio_dir[1] = 0xFFFFFFFF; - - /* - * Check device node and parent device node for device width - * and assume default width of 32 - */ - if (of_property_read_u32(np, "xlnx,gpio2-width", - &chip->gpio_width[1])) - chip->gpio_width[1] = 32; - - if (chip->gpio_width[1] > 32) - return -EINVAL; - } + if (width[1] > 32) + return -EINVAL; + + /* Setup software pin mapping */ + bitmap_set(chip->sw_map, 0, width[0] + width[1]); + + /* Setup hardware pin mapping */ + bitmap_set(chip->hw_map, 0, width[0]); + bitmap_set(chip->hw_map, 32, width[1]); + + spin_lock_init(&chip->gpio_lock); chip->gc.base = -1; - chip->gc.ngpio = chip->gpio_width[0] + chip->gpio_width[1]; + chip->gc.ngpio = bitmap_weight(chip->hw_map, 64); chip->gc.parent = &pdev->dev; chip->gc.direction_input = xgpio_dir_in; chip->gc.direction_output = xgpio_dir_out; diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 3521c1dc3ac0..f0cb8ccd03ed 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -736,6 +736,11 @@ static int __maybe_unused zynq_gpio_suspend(struct device *dev) struct zynq_gpio *gpio = dev_get_drvdata(dev); struct irq_data *data = irq_get_irq_data(gpio->irq); + if (!data) { + dev_err(dev, "irq_get_irq_data() failed\n"); + return -EINVAL; + } + if (!device_may_wakeup(dev)) disable_irq(gpio->irq); @@ -753,6 +758,11 @@ static int __maybe_unused zynq_gpio_resume(struct device *dev) struct irq_data *data = irq_get_irq_data(gpio->irq); int ret; + if (!data) { + dev_err(dev, "irq_get_irq_data() failed\n"); + return -EINVAL; + } + if (!device_may_wakeup(dev)) enable_irq(gpio->irq); @@ -1001,8 +1011,11 @@ err_pm_dis: static int zynq_gpio_remove(struct platform_device *pdev) { struct zynq_gpio *gpio = platform_get_drvdata(pdev); + int ret; - pm_runtime_get_sync(&pdev->dev); + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) + dev_warn(&pdev->dev, "pm_runtime_get_sync() Failed\n"); gpiochip_remove(&gpio->chip); clk_disable_unprepare(gpio->clk); device_set_wakeup_capable(&pdev->dev, 0); @@ -1020,22 +1033,7 @@ static struct platform_driver zynq_gpio_driver = { .remove = zynq_gpio_remove, }; -/** - * zynq_gpio_init - Initial driver registration call - * - * Return: value from platform_driver_register - */ -static int __init zynq_gpio_init(void) -{ - return platform_driver_register(&zynq_gpio_driver); -} -postcore_initcall(zynq_gpio_init); - -static void __exit zynq_gpio_exit(void) -{ - platform_driver_unregister(&zynq_gpio_driver); -} -module_exit(zynq_gpio_exit); +module_platform_driver(zynq_gpio_driver); MODULE_AUTHOR("Xilinx Inc."); MODULE_DESCRIPTION("Zynq GPIO driver"); diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index ae49bb23c6ed..4098bc7f88b7 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -66,9 +66,8 @@ static ssize_t direction_show(struct device *dev, mutex_lock(&data->mutex); gpiod_get_direction(desc); - status = sprintf(buf, "%s\n", - test_bit(FLAG_IS_OUT, &desc->flags) - ? "out" : "in"); + status = sysfs_emit(buf, "%s\n", + test_bit(FLAG_IS_OUT, &desc->flags) ? "out" : "in"); mutex_unlock(&data->mutex); @@ -109,13 +108,9 @@ static ssize_t value_show(struct device *dev, mutex_lock(&data->mutex); status = gpiod_get_value_cansleep(desc); - if (status < 0) - goto err; + if (status >= 0) + status = sysfs_emit(buf, "%zd\n", status); - buf[0] = '0' + status; - buf[1] = '\n'; - status = 2; -err: mutex_unlock(&data->mutex); return status; @@ -249,11 +244,11 @@ static ssize_t edge_show(struct device *dev, mutex_lock(&data->mutex); for (i = 0; i < ARRAY_SIZE(trigger_types); i++) { - if (data->irq_flags == trigger_types[i].flags) { - status = sprintf(buf, "%s\n", trigger_types[i].name); + if (data->irq_flags == trigger_types[i].flags) break; - } } + if (i < ARRAY_SIZE(trigger_types)) + status = sysfs_emit(buf, "%s\n", trigger_types[i].name); mutex_unlock(&data->mutex); @@ -312,10 +307,7 @@ static int gpio_sysfs_set_active_low(struct device *dev, int value) if (!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) == !!value) return 0; - if (value) - set_bit(FLAG_ACTIVE_LOW, &desc->flags); - else - clear_bit(FLAG_ACTIVE_LOW, &desc->flags); + assign_bit(FLAG_ACTIVE_LOW, &desc->flags, value); /* reconfigure poll(2) support if enabled on one edge only */ if (flags == GPIO_IRQF_TRIGGER_FALLING || @@ -336,8 +328,8 @@ static ssize_t active_low_show(struct device *dev, mutex_lock(&data->mutex); - status = sprintf(buf, "%d\n", - !!test_bit(FLAG_ACTIVE_LOW, &desc->flags)); + status = sysfs_emit(buf, "%d\n", + !!test_bit(FLAG_ACTIVE_LOW, &desc->flags)); mutex_unlock(&data->mutex); @@ -415,7 +407,7 @@ static ssize_t base_show(struct device *dev, { const struct gpio_chip *chip = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", chip->base); + return sysfs_emit(buf, "%d\n", chip->base); } static DEVICE_ATTR_RO(base); @@ -424,7 +416,7 @@ static ssize_t label_show(struct device *dev, { const struct gpio_chip *chip = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", chip->label ? : ""); + return sysfs_emit(buf, "%s\n", chip->label ?: ""); } static DEVICE_ATTR_RO(label); @@ -433,7 +425,7 @@ static ssize_t ngpio_show(struct device *dev, { const struct gpio_chip *chip = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", chip->ngpio); + return sysfs_emit(buf, "%u\n", chip->ngpio); } static DEVICE_ATTR_RO(ngpio); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 1427c1be749b..27c07108496d 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2004,9 +2004,6 @@ const char *gpiochip_is_requested(struct gpio_chip *gc, unsigned int offset) { struct gpio_desc *desc; - if (offset >= gc->ngpio) - return NULL; - desc = gpiochip_get_desc(gc, offset); if (IS_ERR(desc)) return NULL; @@ -2543,21 +2540,28 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, while (i < array_size) { struct gpio_chip *gc = desc_array[i]->gdev->chip; - unsigned long fastpath[2 * BITS_TO_LONGS(FASTPATH_NGPIO)]; + DECLARE_BITMAP(fastpath_mask, FASTPATH_NGPIO); + DECLARE_BITMAP(fastpath_bits, FASTPATH_NGPIO); unsigned long *mask, *bits; int first, j; if (likely(gc->ngpio <= FASTPATH_NGPIO)) { - mask = fastpath; + mask = fastpath_mask; + bits = fastpath_bits; } else { - mask = kmalloc_array(2 * BITS_TO_LONGS(gc->ngpio), - sizeof(*mask), - can_sleep ? GFP_KERNEL : GFP_ATOMIC); + gfp_t flags = can_sleep ? GFP_KERNEL : GFP_ATOMIC; + + mask = bitmap_alloc(gc->ngpio, flags); if (!mask) return -ENOMEM; + + bits = bitmap_alloc(gc->ngpio, flags); + if (!bits) { + bitmap_free(mask); + return -ENOMEM; + } } - bits = mask + BITS_TO_LONGS(gc->ngpio); bitmap_zero(mask, gc->ngpio); if (!can_sleep) @@ -2580,8 +2584,10 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, ret = gpio_chip_get_multiple(gc, mask, bits); if (ret) { - if (mask != fastpath) - kfree(mask); + if (mask != fastpath_mask) + bitmap_free(mask); + if (bits != fastpath_bits) + bitmap_free(bits); return ret; } @@ -2601,8 +2607,10 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, j); } - if (mask != fastpath) - kfree(mask); + if (mask != fastpath_mask) + bitmap_free(mask); + if (bits != fastpath_bits) + bitmap_free(bits); } return 0; } @@ -2826,21 +2834,28 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, while (i < array_size) { struct gpio_chip *gc = desc_array[i]->gdev->chip; - unsigned long fastpath[2 * BITS_TO_LONGS(FASTPATH_NGPIO)]; + DECLARE_BITMAP(fastpath_mask, FASTPATH_NGPIO); + DECLARE_BITMAP(fastpath_bits, FASTPATH_NGPIO); unsigned long *mask, *bits; int count = 0; if (likely(gc->ngpio <= FASTPATH_NGPIO)) { - mask = fastpath; + mask = fastpath_mask; + bits = fastpath_bits; } else { - mask = kmalloc_array(2 * BITS_TO_LONGS(gc->ngpio), - sizeof(*mask), - can_sleep ? GFP_KERNEL : GFP_ATOMIC); + gfp_t flags = can_sleep ? GFP_KERNEL : GFP_ATOMIC; + + mask = bitmap_alloc(gc->ngpio, flags); if (!mask) return -ENOMEM; + + bits = bitmap_alloc(gc->ngpio, flags); + if (!bits) { + bitmap_free(mask); + return -ENOMEM; + } } - bits = mask + BITS_TO_LONGS(gc->ngpio); bitmap_zero(mask, gc->ngpio); if (!can_sleep) @@ -2885,8 +2900,10 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, if (count != 0) gpio_chip_set_multiple(gc, mask, bits); - if (mask != fastpath) - kfree(mask); + if (mask != fastpath_mask) + bitmap_free(mask); + if (bits != fastpath_bits) + bitmap_free(bits); } return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 130a9adf09ef..d303e88e3c23 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1369,6 +1369,38 @@ def_value: adev->pm.smu_prv_buffer_size = 0; } +static int amdgpu_device_init_apu_flags(struct amdgpu_device *adev) +{ + if (!(adev->flags & AMD_IS_APU) || + adev->asic_type < CHIP_RAVEN) + return 0; + + switch (adev->asic_type) { + case CHIP_RAVEN: + if (adev->pdev->device == 0x15dd) + adev->apu_flags |= AMD_APU_IS_RAVEN; + if (adev->pdev->device == 0x15d8) + adev->apu_flags |= AMD_APU_IS_PICASSO; + break; + case CHIP_RENOIR: + if ((adev->pdev->device == 0x1636) || + (adev->pdev->device == 0x164c)) + adev->apu_flags |= AMD_APU_IS_RENOIR; + else + adev->apu_flags |= AMD_APU_IS_GREEN_SARDINE; + break; + case CHIP_VANGOGH: + adev->apu_flags |= AMD_APU_IS_VANGOGH; + break; + case CHIP_YELLOW_CARP: + break; + default: + return -EINVAL; + } + + return 0; +} + /** * amdgpu_device_check_arguments - validate module params * @@ -3386,6 +3418,10 @@ int amdgpu_device_init(struct amdgpu_device *adev, mutex_init(&adev->psp.mutex); mutex_init(&adev->notifier_lock); + r = amdgpu_device_init_apu_flags(adev); + if (r) + return r; + r = amdgpu_device_check_arguments(adev); if (r) return r; @@ -4304,6 +4340,7 @@ bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev) case CHIP_SIENNA_CICHLID: case CHIP_NAVY_FLOUNDER: case CHIP_DIMGREY_CAVEFISH: + case CHIP_BEIGE_GOBY: case CHIP_VANGOGH: case CHIP_ALDEBARAN: break; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 6f30c525caac..71beb0db0125 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -160,6 +160,7 @@ int amdgpu_smu_pptable_id = -1; * highest. That helps saving some idle power. * DISABLE_FRACTIONAL_PWM (bit 2) disabled by default * PSR (bit 3) disabled by default + * EDP NO POWER SEQUENCING (bit 4) disabled by default */ uint amdgpu_dc_feature_mask = 2; uint amdgpu_dc_debug_mask; @@ -1198,6 +1199,7 @@ static const struct pci_device_id pciidlist[] = { {0x1002, 0x73E0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH}, {0x1002, 0x73E1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH}, {0x1002, 0x73E2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH}, + {0x1002, 0x73E3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH}, {0x1002, 0x73FF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH}, /* Aldebaran */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 0174f7817ce2..d0b8d415b63b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -562,6 +562,7 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev) case CHIP_NAVI14: case CHIP_NAVI12: case CHIP_VANGOGH: + case CHIP_YELLOW_CARP: /* Don't enable it by default yet. */ if (amdgpu_tmz < 1) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c index d6c54c7f7679..4b153daf283d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c @@ -160,7 +160,7 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier, struct mm_struct *mm, struct page **pages, uint64_t start, uint64_t npages, struct hmm_range **phmm_range, bool readonly, - bool mmap_locked) + bool mmap_locked, void *owner) { struct hmm_range *hmm_range; unsigned long timeout; @@ -185,6 +185,7 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier, hmm_range->hmm_pfns = pfns; hmm_range->start = start; hmm_range->end = start + npages * PAGE_SIZE; + hmm_range->dev_private_owner = owner; /* Assuming 512MB takes maxmium 1 second to fault page address */ timeout = max(npages >> 17, 1ULL) * HMM_RANGE_DEFAULT_TIMEOUT; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h index 7f7d37a457c3..14a3c1864085 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h @@ -34,7 +34,7 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier, struct mm_struct *mm, struct page **pages, uint64_t start, uint64_t npages, struct hmm_range **phmm_range, bool readonly, - bool mmap_locked); + bool mmap_locked, void *owner); int amdgpu_hmm_range_get_pages_done(struct hmm_range *hmm_range); #if defined(CONFIG_HMM_MIRROR) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h index 25ee53545837..45295dce5c3e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h @@ -93,6 +93,8 @@ struct amdgpu_nbio_funcs { void (*enable_aspm)(struct amdgpu_device *adev, bool enable); void (*program_aspm)(struct amdgpu_device *adev); + void (*apply_lc_spc_mode_wa)(struct amdgpu_device *adev); + void (*apply_l1_link_width_reconfig_wa)(struct amdgpu_device *adev); }; struct amdgpu_nbio { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h index 0527772fe1b8..d855cb53c7e0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h @@ -176,10 +176,10 @@ TRACE_EVENT(amdgpu_cs_ioctl, TP_fast_assign( __entry->sched_job_id = job->base.id; - __assign_str(timeline, AMDGPU_JOB_GET_TIMELINE_NAME(job)) + __assign_str(timeline, AMDGPU_JOB_GET_TIMELINE_NAME(job)); __entry->context = job->base.s_fence->finished.context; __entry->seqno = job->base.s_fence->finished.seqno; - __assign_str(ring, to_amdgpu_ring(job->base.sched)->name) + __assign_str(ring, to_amdgpu_ring(job->base.sched)->name); __entry->num_ibs = job->num_ibs; ), TP_printk("sched_job=%llu, timeline=%s, context=%u, seqno=%u, ring_name=%s, num_ibs=%u", @@ -201,10 +201,10 @@ TRACE_EVENT(amdgpu_sched_run_job, TP_fast_assign( __entry->sched_job_id = job->base.id; - __assign_str(timeline, AMDGPU_JOB_GET_TIMELINE_NAME(job)) + __assign_str(timeline, AMDGPU_JOB_GET_TIMELINE_NAME(job)); __entry->context = job->base.s_fence->finished.context; __entry->seqno = job->base.s_fence->finished.seqno; - __assign_str(ring, to_amdgpu_ring(job->base.sched)->name) + __assign_str(ring, to_amdgpu_ring(job->base.sched)->name); __entry->num_ibs = job->num_ibs; ), TP_printk("sched_job=%llu, timeline=%s, context=%u, seqno=%u, ring_name=%s, num_ibs=%u", @@ -229,7 +229,7 @@ TRACE_EVENT(amdgpu_vm_grab_id, TP_fast_assign( __entry->pasid = vm->pasid; - __assign_str(ring, ring->name) + __assign_str(ring, ring->name); __entry->vmid = job->vmid; __entry->vm_hub = ring->funcs->vmhub, __entry->pd_addr = job->vm_pd_addr; @@ -424,7 +424,7 @@ TRACE_EVENT(amdgpu_vm_flush, ), TP_fast_assign( - __assign_str(ring, ring->name) + __assign_str(ring, ring->name); __entry->vmid = vmid; __entry->vm_hub = ring->funcs->vmhub; __entry->pd_addr = pd_addr; @@ -525,7 +525,7 @@ TRACE_EVENT(amdgpu_ib_pipe_sync, ), TP_fast_assign( - __assign_str(ring, sched_job->base.sched->name) + __assign_str(ring, sched_job->base.sched->name); __entry->id = sched_job->base.id; __entry->fence = fence; __entry->ctx = fence->context; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index cdfc20b0b2eb..3a55f08e00e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -590,10 +590,6 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_device *bdev, mem->bus.offset += adev->gmc.aper_base; mem->bus.is_iomem = true; - if (adev->gmc.xgmi.connected_to_cpu) - mem->bus.caching = ttm_cached; - else - mem->bus.caching = ttm_write_combined; break; default: return -EINVAL; @@ -695,7 +691,7 @@ int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo, struct page **pages) readonly = amdgpu_ttm_tt_is_readonly(ttm); r = amdgpu_hmm_range_get_pages(&bo->notifier, mm, pages, start, ttm->num_pages, >t->range, readonly, - true); + true, NULL); out_unlock: mmap_read_unlock(mm); mmput(mm); @@ -923,7 +919,8 @@ static int amdgpu_ttm_backend_bind(struct ttm_device *bdev, bo_mem->mem_type == AMDGPU_PL_OA) return -EINVAL; - if (!amdgpu_gtt_mgr_has_gart_addr(bo_mem)) { + if (bo_mem->mem_type != TTM_PL_TT || + !amdgpu_gtt_mgr_has_gart_addr(bo_mem)) { gtt->offset = AMDGPU_BO_INVALID_OFFSET; return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 436ec246a7da..2fd77c36a1ff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -463,6 +463,11 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, if (i == 1) node->base.placement |= TTM_PL_FLAG_CONTIGUOUS; + if (adev->gmc.xgmi.connected_to_cpu) + node->base.bus.caching = ttm_cached; + else + node->base.bus.caching = ttm_write_combined; + atomic64_add(vis_usage, &mgr->vis_usage); *res = &node->base; return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/athub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/athub_v2_0.c index 5b90efd6f6d0..3ac505d954c4 100644 --- a/drivers/gpu/drm/amd/amdgpu/athub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/athub_v2_0.c @@ -36,9 +36,12 @@ athub_v2_0_update_medium_grain_clock_gating(struct amdgpu_device *adev, { uint32_t def, data; + if (!(adev->cg_flags & AMD_CG_SUPPORT_MC_MGCG)) + return; + def = data = RREG32_SOC15(ATHUB, 0, mmATHUB_MISC_CNTL); - if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_MGCG)) + if (enable) data |= ATHUB_MISC_CNTL__CG_ENABLE_MASK; else data &= ~ATHUB_MISC_CNTL__CG_ENABLE_MASK; @@ -53,10 +56,13 @@ athub_v2_0_update_medium_grain_light_sleep(struct amdgpu_device *adev, { uint32_t def, data; + if (!((adev->cg_flags & AMD_CG_SUPPORT_MC_LS) && + (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS))) + return; + def = data = RREG32_SOC15(ATHUB, 0, mmATHUB_MISC_CNTL); - if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_LS) && - (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS)) + if (enable) data |= ATHUB_MISC_CNTL__CG_MEM_LS_ENABLE_MASK; else data &= ~ATHUB_MISC_CNTL__CG_MEM_LS_ENABLE_MASK; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 2d56b60bc058..f5e9c022960b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -5086,47 +5086,44 @@ static void gfx_v10_0_tcp_harvest(struct amdgpu_device *adev) 4 + /* RMI */ 1); /* SQG */ - if (adev->asic_type == CHIP_NAVI10 || - adev->asic_type == CHIP_NAVI14 || - adev->asic_type == CHIP_NAVI12) { - mutex_lock(&adev->grbm_idx_mutex); - for (i = 0; i < adev->gfx.config.max_shader_engines; i++) { - for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) { - gfx_v10_0_select_se_sh(adev, i, j, 0xffffffff); - wgp_active_bitmap = gfx_v10_0_get_wgp_active_bitmap_per_sh(adev); - /* - * Set corresponding TCP bits for the inactive WGPs in - * GCRD_SA_TARGETS_DISABLE - */ - gcrd_targets_disable_tcp = 0; - /* Set TCP & SQC bits in UTCL1_UTCL0_INVREQ_DISABLE */ - utcl_invreq_disable = 0; - - for (k = 0; k < max_wgp_per_sh; k++) { - if (!(wgp_active_bitmap & (1 << k))) { - gcrd_targets_disable_tcp |= 3 << (2 * k); - utcl_invreq_disable |= (3 << (2 * k)) | - (3 << (2 * (max_wgp_per_sh + k))); - } + mutex_lock(&adev->grbm_idx_mutex); + for (i = 0; i < adev->gfx.config.max_shader_engines; i++) { + for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) { + gfx_v10_0_select_se_sh(adev, i, j, 0xffffffff); + wgp_active_bitmap = gfx_v10_0_get_wgp_active_bitmap_per_sh(adev); + /* + * Set corresponding TCP bits for the inactive WGPs in + * GCRD_SA_TARGETS_DISABLE + */ + gcrd_targets_disable_tcp = 0; + /* Set TCP & SQC bits in UTCL1_UTCL0_INVREQ_DISABLE */ + utcl_invreq_disable = 0; + + for (k = 0; k < max_wgp_per_sh; k++) { + if (!(wgp_active_bitmap & (1 << k))) { + gcrd_targets_disable_tcp |= 3 << (2 * k); + gcrd_targets_disable_tcp |= 1 << (k + (max_wgp_per_sh * 2)); + utcl_invreq_disable |= (3 << (2 * k)) | + (3 << (2 * (max_wgp_per_sh + k))); } - - tmp = RREG32_SOC15(GC, 0, mmUTCL1_UTCL0_INVREQ_DISABLE); - /* only override TCP & SQC bits */ - tmp &= 0xffffffff << (4 * max_wgp_per_sh); - tmp |= (utcl_invreq_disable & utcl_invreq_disable_mask); - WREG32_SOC15(GC, 0, mmUTCL1_UTCL0_INVREQ_DISABLE, tmp); - - tmp = RREG32_SOC15(GC, 0, mmGCRD_SA_TARGETS_DISABLE); - /* only override TCP bits */ - tmp &= 0xffffffff << (2 * max_wgp_per_sh); - tmp |= (gcrd_targets_disable_tcp & gcrd_targets_disable_mask); - WREG32_SOC15(GC, 0, mmGCRD_SA_TARGETS_DISABLE, tmp); } - } - gfx_v10_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); - mutex_unlock(&adev->grbm_idx_mutex); + tmp = RREG32_SOC15(GC, 0, mmUTCL1_UTCL0_INVREQ_DISABLE); + /* only override TCP & SQC bits */ + tmp &= (0xffffffffU << (4 * max_wgp_per_sh)); + tmp |= (utcl_invreq_disable & utcl_invreq_disable_mask); + WREG32_SOC15(GC, 0, mmUTCL1_UTCL0_INVREQ_DISABLE, tmp); + + tmp = RREG32_SOC15(GC, 0, mmGCRD_SA_TARGETS_DISABLE); + /* only override TCP & SQC bits */ + tmp &= (0xffffffffU << (3 * max_wgp_per_sh)); + tmp |= (gcrd_targets_disable_tcp & gcrd_targets_disable_mask); + WREG32_SOC15(GC, 0, mmGCRD_SA_TARGETS_DISABLE, tmp); + } } + + gfx_v10_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + mutex_unlock(&adev->grbm_idx_mutex); } static void gfx_v10_0_get_tcc_info(struct amdgpu_device *adev) @@ -7404,7 +7401,10 @@ static int gfx_v10_0_hw_init(void *handle) * init golden registers and rlc resume may override some registers, * reconfig them here */ - gfx_v10_0_tcp_harvest(adev); + if (adev->asic_type == CHIP_NAVI10 || + adev->asic_type == CHIP_NAVI14 || + adev->asic_type == CHIP_NAVI12) + gfx_v10_0_tcp_harvest(adev); r = gfx_v10_0_cp_resume(adev); if (r) @@ -7777,6 +7777,9 @@ static void gfx_v10_0_update_medium_grain_clock_gating(struct amdgpu_device *ade { uint32_t data, def; + if (!(adev->cg_flags & (AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS))) + return; + /* It is disabled by HW by default */ if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) { /* 0 - Disable some blocks' MGCG */ @@ -7791,6 +7794,7 @@ static void gfx_v10_0_update_medium_grain_clock_gating(struct amdgpu_device *ade RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK | RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK | RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK | + RLC_CGTT_MGCG_OVERRIDE__GFXIP_FGCG_OVERRIDE_MASK | RLC_CGTT_MGCG_OVERRIDE__ENABLE_CGTS_LEGACY_MASK); if (def != data) @@ -7813,13 +7817,15 @@ static void gfx_v10_0_update_medium_grain_clock_gating(struct amdgpu_device *ade WREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL, data); } } - } else { + } else if (!enable || !(adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) { /* 1 - MGCG_OVERRIDE */ def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE); data |= (RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK | RLC_CGTT_MGCG_OVERRIDE__GRBM_CGTT_SCLK_OVERRIDE_MASK | RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK | - RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK); + RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK | + RLC_CGTT_MGCG_OVERRIDE__GFXIP_FGCG_OVERRIDE_MASK | + RLC_CGTT_MGCG_OVERRIDE__ENABLE_CGTS_LEGACY_MASK); if (def != data) WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data); @@ -7845,22 +7851,34 @@ static void gfx_v10_0_update_3d_clock_gating(struct amdgpu_device *adev, { uint32_t data, def; + if (!(adev->cg_flags & (AMD_CG_SUPPORT_GFX_3D_CGCG | AMD_CG_SUPPORT_GFX_3D_CGLS))) + return; + /* Enable 3D CGCG/CGLS */ - if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGCG)) { + if (enable) { /* write cmd to clear cgcg/cgls ov */ def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE); + /* unset CGCG override */ - data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_GFX3D_CG_OVERRIDE_MASK; + if (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGCG) + data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_GFX3D_CG_OVERRIDE_MASK; + /* update CGCG and CGLS override bits */ if (def != data) WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data); + /* enable 3Dcgcg FSM(0x0000363f) */ def = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D); - data = (0x36 << RLC_CGCG_CGLS_CTRL_3D__CGCG_GFX_IDLE_THRESHOLD__SHIFT) | - RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK; + data = 0; + + if (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGCG) + data = (0x36 << RLC_CGCG_CGLS_CTRL_3D__CGCG_GFX_IDLE_THRESHOLD__SHIFT) | + RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK; + if (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGLS) data |= (0x000F << RLC_CGCG_CGLS_CTRL_3D__CGLS_REP_COMPANSAT_DELAY__SHIFT) | RLC_CGCG_CGLS_CTRL_3D__CGLS_EN_MASK; + if (def != data) WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D, data); @@ -7873,9 +7891,14 @@ static void gfx_v10_0_update_3d_clock_gating(struct amdgpu_device *adev, } else { /* Disable CGCG/CGLS */ def = data = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D); + /* disable cgcg, cgls should be disabled */ - data &= ~(RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK | - RLC_CGCG_CGLS_CTRL_3D__CGLS_EN_MASK); + if (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGCG) + data &= ~RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK; + + if (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGLS) + data &= ~RLC_CGCG_CGLS_CTRL_3D__CGLS_EN_MASK; + /* disable cgcg and cgls in FSM */ if (def != data) WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D, data); @@ -7887,25 +7910,35 @@ static void gfx_v10_0_update_coarse_grain_clock_gating(struct amdgpu_device *ade { uint32_t def, data; - if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG)) { + if (!(adev->cg_flags & (AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS))) + return; + + if (enable) { def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE); + /* unset CGCG override */ - data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGCG_OVERRIDE_MASK; + if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG) + data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGCG_OVERRIDE_MASK; + if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS) data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGLS_OVERRIDE_MASK; - else - data |= RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGLS_OVERRIDE_MASK; + /* update CGCG and CGLS override bits */ if (def != data) WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data); /* enable cgcg FSM(0x0000363F) */ def = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL); - data = (0x36 << RLC_CGCG_CGLS_CTRL__CGCG_GFX_IDLE_THRESHOLD__SHIFT) | - RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK; + data = 0; + + if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG) + data = (0x36 << RLC_CGCG_CGLS_CTRL__CGCG_GFX_IDLE_THRESHOLD__SHIFT) | + RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK; + if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS) data |= (0x000F << RLC_CGCG_CGLS_CTRL__CGLS_REP_COMPANSAT_DELAY__SHIFT) | RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK; + if (def != data) WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL, data); @@ -7917,8 +7950,14 @@ static void gfx_v10_0_update_coarse_grain_clock_gating(struct amdgpu_device *ade WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_CNTL, data); } else { def = data = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL); + /* reset CGCG/CGLS bits */ - data &= ~(RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK | RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK); + if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG) + data &= ~RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK; + + if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS) + data &= ~RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK; + /* disable cgcg and cgls in FSM */ if (def != data) WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL, data); @@ -7930,7 +7969,10 @@ static void gfx_v10_0_update_fine_grain_clock_gating(struct amdgpu_device *adev, { uint32_t def, data; - if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_FGCG)) { + if (!(adev->cg_flags & AMD_CG_SUPPORT_GFX_FGCG)) + return; + + if (enable) { def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE); /* unset FGCG override */ data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_FGCG_OVERRIDE_MASK; @@ -7961,6 +8003,97 @@ static void gfx_v10_0_update_fine_grain_clock_gating(struct amdgpu_device *adev, } } +static void gfx_v10_0_apply_medium_grain_clock_gating_workaround(struct amdgpu_device *adev) +{ + uint32_t reg_data = 0; + uint32_t reg_idx = 0; + uint32_t i; + + const uint32_t tcp_ctrl_regs[] = { + mmCGTS_SA0_WGP00_CU0_TCP_CTRL_REG, + mmCGTS_SA0_WGP00_CU1_TCP_CTRL_REG, + mmCGTS_SA0_WGP01_CU0_TCP_CTRL_REG, + mmCGTS_SA0_WGP01_CU1_TCP_CTRL_REG, + mmCGTS_SA0_WGP02_CU0_TCP_CTRL_REG, + mmCGTS_SA0_WGP02_CU1_TCP_CTRL_REG, + mmCGTS_SA0_WGP10_CU0_TCP_CTRL_REG, + mmCGTS_SA0_WGP10_CU1_TCP_CTRL_REG, + mmCGTS_SA0_WGP11_CU0_TCP_CTRL_REG, + mmCGTS_SA0_WGP11_CU1_TCP_CTRL_REG, + mmCGTS_SA0_WGP12_CU0_TCP_CTRL_REG, + mmCGTS_SA0_WGP12_CU1_TCP_CTRL_REG, + mmCGTS_SA1_WGP00_CU0_TCP_CTRL_REG, + mmCGTS_SA1_WGP00_CU1_TCP_CTRL_REG, + mmCGTS_SA1_WGP01_CU0_TCP_CTRL_REG, + mmCGTS_SA1_WGP01_CU1_TCP_CTRL_REG, + mmCGTS_SA1_WGP02_CU0_TCP_CTRL_REG, + mmCGTS_SA1_WGP02_CU1_TCP_CTRL_REG, + mmCGTS_SA1_WGP10_CU0_TCP_CTRL_REG, + mmCGTS_SA1_WGP10_CU1_TCP_CTRL_REG, + mmCGTS_SA1_WGP11_CU0_TCP_CTRL_REG, + mmCGTS_SA1_WGP11_CU1_TCP_CTRL_REG, + mmCGTS_SA1_WGP12_CU0_TCP_CTRL_REG, + mmCGTS_SA1_WGP12_CU1_TCP_CTRL_REG + }; + + const uint32_t tcp_ctrl_regs_nv12[] = { + mmCGTS_SA0_WGP00_CU0_TCP_CTRL_REG, + mmCGTS_SA0_WGP00_CU1_TCP_CTRL_REG, + mmCGTS_SA0_WGP01_CU0_TCP_CTRL_REG, + mmCGTS_SA0_WGP01_CU1_TCP_CTRL_REG, + mmCGTS_SA0_WGP02_CU0_TCP_CTRL_REG, + mmCGTS_SA0_WGP02_CU1_TCP_CTRL_REG, + mmCGTS_SA0_WGP10_CU0_TCP_CTRL_REG, + mmCGTS_SA0_WGP10_CU1_TCP_CTRL_REG, + mmCGTS_SA0_WGP11_CU0_TCP_CTRL_REG, + mmCGTS_SA0_WGP11_CU1_TCP_CTRL_REG, + mmCGTS_SA1_WGP00_CU0_TCP_CTRL_REG, + mmCGTS_SA1_WGP00_CU1_TCP_CTRL_REG, + mmCGTS_SA1_WGP01_CU0_TCP_CTRL_REG, + mmCGTS_SA1_WGP01_CU1_TCP_CTRL_REG, + mmCGTS_SA1_WGP02_CU0_TCP_CTRL_REG, + mmCGTS_SA1_WGP02_CU1_TCP_CTRL_REG, + mmCGTS_SA1_WGP10_CU0_TCP_CTRL_REG, + mmCGTS_SA1_WGP10_CU1_TCP_CTRL_REG, + mmCGTS_SA1_WGP11_CU0_TCP_CTRL_REG, + mmCGTS_SA1_WGP11_CU1_TCP_CTRL_REG, + }; + + const uint32_t sm_ctlr_regs[] = { + mmCGTS_SA0_QUAD0_SM_CTRL_REG, + mmCGTS_SA0_QUAD1_SM_CTRL_REG, + mmCGTS_SA1_QUAD0_SM_CTRL_REG, + mmCGTS_SA1_QUAD1_SM_CTRL_REG + }; + + if (adev->asic_type == CHIP_NAVI12) { + for (i = 0; i < ARRAY_SIZE(tcp_ctrl_regs_nv12); i++) { + reg_idx = adev->reg_offset[GC_HWIP][0][mmCGTS_SA0_WGP00_CU0_TCP_CTRL_REG_BASE_IDX] + + tcp_ctrl_regs_nv12[i]; + reg_data = RREG32(reg_idx); + reg_data |= CGTS_SA0_WGP00_CU0_TCP_CTRL_REG__TCPI_LS_OVERRIDE_MASK; + WREG32(reg_idx, reg_data); + } + } else { + for (i = 0; i < ARRAY_SIZE(tcp_ctrl_regs); i++) { + reg_idx = adev->reg_offset[GC_HWIP][0][mmCGTS_SA0_WGP00_CU0_TCP_CTRL_REG_BASE_IDX] + + tcp_ctrl_regs[i]; + reg_data = RREG32(reg_idx); + reg_data |= CGTS_SA0_WGP00_CU0_TCP_CTRL_REG__TCPI_LS_OVERRIDE_MASK; + WREG32(reg_idx, reg_data); + } + } + + for (i = 0; i < ARRAY_SIZE(sm_ctlr_regs); i++) { + reg_idx = adev->reg_offset[GC_HWIP][0][mmCGTS_SA0_QUAD0_SM_CTRL_REG_BASE_IDX] + + sm_ctlr_regs[i]; + reg_data = RREG32(reg_idx); + reg_data &= ~CGTS_SA0_QUAD0_SM_CTRL_REG__SM_MODE_MASK; + reg_data |= 2 << CGTS_SA0_QUAD0_SM_CTRL_REG__SM_MODE__SHIFT; + WREG32(reg_idx, reg_data); + } +} + static int gfx_v10_0_update_gfx_clock_gating(struct amdgpu_device *adev, bool enable) { @@ -7977,6 +8110,10 @@ static int gfx_v10_0_update_gfx_clock_gating(struct amdgpu_device *adev, gfx_v10_0_update_3d_clock_gating(adev, enable); /* === CGCG + CGLS === */ gfx_v10_0_update_coarse_grain_clock_gating(adev, enable); + + if ((adev->asic_type >= CHIP_NAVI10) && + (adev->asic_type <= CHIP_NAVI12)) + gfx_v10_0_apply_medium_grain_clock_gating_workaround(adev); } else { /* CGCG/CGLS should be disabled before MGCG/MGLS * === CGCG + CGLS === @@ -9324,17 +9461,22 @@ static void gfx_v10_0_set_user_wgp_inactive_bitmap_per_sh(struct amdgpu_device * static u32 gfx_v10_0_get_wgp_active_bitmap_per_sh(struct amdgpu_device *adev) { - u32 data, wgp_bitmask; - data = RREG32_SOC15(GC, 0, mmCC_GC_SHADER_ARRAY_CONFIG); - data |= RREG32_SOC15(GC, 0, mmGC_USER_SHADER_ARRAY_CONFIG); + u32 disabled_mask = + ~amdgpu_gfx_create_bitmask(adev->gfx.config.max_cu_per_sh >> 1); + u32 efuse_setting = 0; + u32 vbios_setting = 0; + + efuse_setting = RREG32_SOC15(GC, 0, mmCC_GC_SHADER_ARRAY_CONFIG); + efuse_setting &= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_WGPS_MASK; + efuse_setting >>= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_WGPS__SHIFT; - data &= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_WGPS_MASK; - data >>= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_WGPS__SHIFT; + vbios_setting = RREG32_SOC15(GC, 0, mmGC_USER_SHADER_ARRAY_CONFIG); + vbios_setting &= GC_USER_SHADER_ARRAY_CONFIG__INACTIVE_WGPS_MASK; + vbios_setting >>= GC_USER_SHADER_ARRAY_CONFIG__INACTIVE_WGPS__SHIFT; - wgp_bitmask = - amdgpu_gfx_create_bitmask(adev->gfx.config.max_cu_per_sh >> 1); + disabled_mask |= efuse_setting | vbios_setting; - return (~data) & wgp_bitmask; + return (~disabled_mask); } static u32 gfx_v10_0_get_cu_active_bitmap_per_sh(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c b/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c index 7a15e669b68d..5793977953cc 100644 --- a/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c @@ -90,45 +90,56 @@ static void hdp_v5_0_update_mem_power_gating(struct amdgpu_device *adev, RC_MEM_POWER_SD_EN, 0); WREG32_SOC15(HDP, 0, mmHDP_MEM_POWER_CTRL, hdp_mem_pwr_cntl); - /* only one clock gating mode (LS/DS/SD) can be enabled */ - if (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS) { - hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, - HDP_MEM_POWER_CTRL, - IPH_MEM_POWER_LS_EN, enable); - hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, - HDP_MEM_POWER_CTRL, - RC_MEM_POWER_LS_EN, enable); - } else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_DS) { - hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, - HDP_MEM_POWER_CTRL, - IPH_MEM_POWER_DS_EN, enable); - hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, - HDP_MEM_POWER_CTRL, - RC_MEM_POWER_DS_EN, enable); - } else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_SD) { - hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, - HDP_MEM_POWER_CTRL, - IPH_MEM_POWER_SD_EN, enable); - /* RC should not use shut down mode, fallback to ds */ - hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, - HDP_MEM_POWER_CTRL, - RC_MEM_POWER_DS_EN, enable); - } - - /* confirmed that IPH_MEM_POWER_CTRL_EN and RC_MEM_POWER_CTRL_EN have to - * be set for SRAM LS/DS/SD */ - if (adev->cg_flags & (AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_HDP_DS | - AMD_CG_SUPPORT_HDP_SD)) { - hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL, - IPH_MEM_POWER_CTRL_EN, 1); - hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL, - RC_MEM_POWER_CTRL_EN, 1); + /* Already disabled above. The actions below are for "enabled" only */ + if (enable) { + /* only one clock gating mode (LS/DS/SD) can be enabled */ + if (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS) { + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, + HDP_MEM_POWER_CTRL, + IPH_MEM_POWER_LS_EN, 1); + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, + HDP_MEM_POWER_CTRL, + RC_MEM_POWER_LS_EN, 1); + } else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_DS) { + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, + HDP_MEM_POWER_CTRL, + IPH_MEM_POWER_DS_EN, 1); + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, + HDP_MEM_POWER_CTRL, + RC_MEM_POWER_DS_EN, 1); + } else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_SD) { + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, + HDP_MEM_POWER_CTRL, + IPH_MEM_POWER_SD_EN, 1); + /* RC should not use shut down mode, fallback to ds or ls if allowed */ + if (adev->cg_flags & AMD_CG_SUPPORT_HDP_DS) + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, + HDP_MEM_POWER_CTRL, + RC_MEM_POWER_DS_EN, 1); + else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS) + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, + HDP_MEM_POWER_CTRL, + RC_MEM_POWER_LS_EN, 1); + } + + /* confirmed that IPH_MEM_POWER_CTRL_EN and RC_MEM_POWER_CTRL_EN have to + * be set for SRAM LS/DS/SD */ + if (adev->cg_flags & (AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_HDP_DS | + AMD_CG_SUPPORT_HDP_SD)) { + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL, + IPH_MEM_POWER_CTRL_EN, 1); + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL, + RC_MEM_POWER_CTRL_EN, 1); + WREG32_SOC15(HDP, 0, mmHDP_MEM_POWER_CTRL, hdp_mem_pwr_cntl); + } } - WREG32_SOC15(HDP, 0, mmHDP_MEM_POWER_CTRL, hdp_mem_pwr_cntl); - - /* restore IPH & RC clock override after clock/power mode changing */ - WREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL, hdp_clk_cntl1); + /* disable IPH & RC clock override after clock/power mode changing */ + hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL, + IPH_MEM_CLK_SOFT_OVERRIDE, 0); + hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL, + RC_MEM_CLK_SOFT_OVERRIDE, 0); + WREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL, hdp_clk_cntl); } static void hdp_v5_0_update_medium_grain_clock_gating(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c index f7e93bbc4e15..7ded6b2f058e 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c @@ -568,6 +568,9 @@ static void mmhub_v2_0_update_medium_grain_clock_gating(struct amdgpu_device *ad { uint32_t def, data, def1, data1; + if (!(adev->cg_flags & AMD_CG_SUPPORT_MC_MGCG)) + return; + switch (adev->asic_type) { case CHIP_SIENNA_CICHLID: case CHIP_NAVY_FLOUNDER: @@ -582,7 +585,7 @@ static void mmhub_v2_0_update_medium_grain_clock_gating(struct amdgpu_device *ad break; } - if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_MGCG)) { + if (enable) { data |= MM_ATC_L2_MISC_CG__ENABLE_MASK; data1 &= ~(DAGB0_CNTL_MISC2__DISABLE_WRREQ_CG_MASK | @@ -627,6 +630,9 @@ static void mmhub_v2_0_update_medium_grain_light_sleep(struct amdgpu_device *ade { uint32_t def, data; + if (!(adev->cg_flags & AMD_CG_SUPPORT_MC_LS)) + return; + switch (adev->asic_type) { case CHIP_SIENNA_CICHLID: case CHIP_NAVY_FLOUNDER: @@ -639,7 +645,7 @@ static void mmhub_v2_0_update_medium_grain_light_sleep(struct amdgpu_device *ade break; } - if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_LS)) + if (enable) data |= MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK; else data &= ~MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK; diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c b/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c index 05ddec7ba7e2..7b79eeaa88aa 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c @@ -51,6 +51,8 @@ #define mmBIF_MMSCH1_DOORBELL_RANGE 0x01d8 #define mmBIF_MMSCH1_DOORBELL_RANGE_BASE_IDX 2 +#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 + static void nbio_v2_3_remap_hdp_registers(struct amdgpu_device *adev) { WREG32_SOC15(NBIO, 0, mmREMAP_HDP_MEM_FLUSH_CNTL, @@ -218,8 +220,11 @@ static void nbio_v2_3_update_medium_grain_clock_gating(struct amdgpu_device *ade { uint32_t def, data; + if (!(adev->cg_flags & AMD_CG_SUPPORT_BIF_MGCG)) + return; + def = data = RREG32_PCIE(smnCPM_CONTROL); - if (enable && (adev->cg_flags & AMD_CG_SUPPORT_BIF_MGCG)) { + if (enable) { data |= (CPM_CONTROL__LCLK_DYN_GATE_ENABLE_MASK | CPM_CONTROL__TXCLK_DYN_GATE_ENABLE_MASK | CPM_CONTROL__TXCLK_LCNT_GATE_ENABLE_MASK | @@ -244,8 +249,11 @@ static void nbio_v2_3_update_medium_grain_light_sleep(struct amdgpu_device *adev { uint32_t def, data; + if (!(adev->cg_flags & AMD_CG_SUPPORT_BIF_LS)) + return; + def = data = RREG32_PCIE(smnPCIE_CNTL2); - if (enable && (adev->cg_flags & AMD_CG_SUPPORT_BIF_LS)) { + if (enable) { data |= (PCIE_CNTL2__SLV_MEM_LS_EN_MASK | PCIE_CNTL2__MST_MEM_LS_EN_MASK | PCIE_CNTL2__REPLAY_MEM_LS_EN_MASK); @@ -463,6 +471,43 @@ static void nbio_v2_3_program_aspm(struct amdgpu_device *adev) WREG32_PCIE(smnPCIE_LC_CNTL3, data); } +static void nbio_v2_3_apply_lc_spc_mode_wa(struct amdgpu_device *adev) +{ + uint32_t reg_data = 0; + uint32_t link_width = 0; + + if (!((adev->asic_type >= CHIP_NAVI10) && + (adev->asic_type <= CHIP_NAVI12))) + return; + + reg_data = RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL); + link_width = (reg_data & PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) + >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; + + /* + * Program PCIE_LC_CNTL6.LC_SPC_MODE_8GT to 0x2 (4 symbols per clock data) + * if link_width is 0x3 (x4) + */ + if (0x3 == link_width) { + reg_data = RREG32_PCIE(smnPCIE_LC_CNTL6); + reg_data &= ~PCIE_LC_CNTL6__LC_SPC_MODE_8GT_MASK; + reg_data |= (0x2 << PCIE_LC_CNTL6__LC_SPC_MODE_8GT__SHIFT); + WREG32_PCIE(smnPCIE_LC_CNTL6, reg_data); + } +} + +static void nbio_v2_3_apply_l1_link_width_reconfig_wa(struct amdgpu_device *adev) +{ + uint32_t reg_data = 0; + + if (adev->asic_type != CHIP_NAVI10) + return; + + reg_data = RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL); + reg_data |= PCIE_LC_LINK_WIDTH_CNTL__LC_L1_RECONFIG_EN_MASK; + WREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL, reg_data); +} + const struct amdgpu_nbio_funcs nbio_v2_3_funcs = { .get_hdp_flush_req_offset = nbio_v2_3_get_hdp_flush_req_offset, .get_hdp_flush_done_offset = nbio_v2_3_get_hdp_flush_done_offset, @@ -484,4 +529,6 @@ const struct amdgpu_nbio_funcs nbio_v2_3_funcs = { .remap_hdp_registers = nbio_v2_3_remap_hdp_registers, .enable_aspm = nbio_v2_3_enable_aspm, .program_aspm = nbio_v2_3_program_aspm, + .apply_lc_spc_mode_wa = nbio_v2_3_apply_lc_spc_mode_wa, + .apply_l1_link_width_reconfig_wa = nbio_v2_3_apply_l1_link_width_reconfig_wa, }; diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index 455d0425787c..94a2c0742ee5 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -64,6 +64,13 @@ #include "smuio_v11_0.h" #include "smuio_v11_0_6.h" +#define codec_info_build(type, width, height, level) \ + .codec_type = type,\ + .max_width = width,\ + .max_height = height,\ + .max_pixels_per_frame = height * width,\ + .max_level = level, + static const struct amd_ip_funcs nv_common_ip_funcs; /* Navi */ @@ -309,6 +316,23 @@ static struct amdgpu_video_codecs sriov_sc_video_codecs_decode = .codec_array = sriov_sc_video_codecs_decode_array, }; +/* Beige Goby*/ +static const struct amdgpu_video_codec_info bg_video_codecs_decode_array[] = { + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, +}; + +static const struct amdgpu_video_codecs bg_video_codecs_decode = { + .codec_count = ARRAY_SIZE(bg_video_codecs_decode_array), + .codec_array = bg_video_codecs_decode_array, +}; + +static const struct amdgpu_video_codecs bg_video_codecs_encode = { + .codec_count = 0, + .codec_array = NULL, +}; + static int nv_query_video_codecs(struct amdgpu_device *adev, bool encode, const struct amdgpu_video_codecs **codecs) { @@ -335,6 +359,12 @@ static int nv_query_video_codecs(struct amdgpu_device *adev, bool encode, else *codecs = &sc_video_codecs_decode; return 0; + case CHIP_BEIGE_GOBY: + if (encode) + *codecs = &bg_video_codecs_encode; + else + *codecs = &bg_video_codecs_decode; + return 0; case CHIP_NAVI10: case CHIP_NAVI14: case CHIP_NAVI12: @@ -1275,7 +1305,6 @@ static int nv_common_early_init(void *handle) break; case CHIP_VANGOGH: - adev->apu_flags |= AMD_APU_IS_VANGOGH; adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS | AMD_CG_SUPPORT_GFX_CP_LS | @@ -1411,6 +1440,12 @@ static int nv_common_hw_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + if (adev->nbio.funcs->apply_lc_spc_mode_wa) + adev->nbio.funcs->apply_lc_spc_mode_wa(adev); + + if (adev->nbio.funcs->apply_l1_link_width_reconfig_wa) + adev->nbio.funcs->apply_l1_link_width_reconfig_wa(adev); + /* enable pcie gen2/3 link */ nv_pcie_gen3_enable(adev); /* enable aspm */ diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index ae5464e2535a..8931000dcd41 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -144,7 +144,7 @@ static const struct soc15_reg_golden golden_settings_sdma_4_1[] = { SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_IB_CNTL, 0x800f0111, 0x00000100), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), - SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0), + SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003e0), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000) }; @@ -288,7 +288,7 @@ static const struct soc15_reg_golden golden_settings_sdma_4_3[] = { SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_POWER_CNTL, 0x003fff07, 0x40000051), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), - SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0), + SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003e0), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x03fbe1fe) }; @@ -1896,8 +1896,11 @@ static int sdma_v4_0_late_init(void *handle) sdma_v4_0_setup_ulv(adev); - if (adev->sdma.funcs && adev->sdma.funcs->reset_ras_error_count) - adev->sdma.funcs->reset_ras_error_count(adev); + if (!amdgpu_persistent_edc_harvesting_supported(adev)) { + if (adev->sdma.funcs && + adev->sdma.funcs->reset_ras_error_count) + adev->sdma.funcs->reset_ras_error_count(adev); + } if (adev->sdma.funcs && adev->sdma.funcs->ras_late_init) return adev->sdma.funcs->ras_late_init(adev, &ih_info); diff --git a/drivers/gpu/drm/amd/amdgpu/smuio_v11_0.c b/drivers/gpu/drm/amd/amdgpu/smuio_v11_0.c index e9c474c217ec..b6f1322f908c 100644 --- a/drivers/gpu/drm/amd/amdgpu/smuio_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/smuio_v11_0.c @@ -43,9 +43,12 @@ static void smuio_v11_0_update_rom_clock_gating(struct amdgpu_device *adev, bool if (adev->flags & AMD_IS_APU) return; + if (!(adev->cg_flags & AMD_CG_SUPPORT_ROM_MGCG)) + return; + def = data = RREG32_SOC15(SMUIO, 0, mmCGTT_ROM_CLK_CTRL0); - if (enable && (adev->cg_flags & AMD_CG_SUPPORT_ROM_MGCG)) + if (enable) data &= ~(CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE0_MASK | CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE1_MASK); else diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index de85577c9cfd..b02436401d46 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -1360,10 +1360,7 @@ static int soc15_common_early_init(void *handle) break; case CHIP_RAVEN: adev->asic_funcs = &soc15_asic_funcs; - if (adev->pdev->device == 0x15dd) - adev->apu_flags |= AMD_APU_IS_RAVEN; - if (adev->pdev->device == 0x15d8) - adev->apu_flags |= AMD_APU_IS_PICASSO; + if (adev->rev_id >= 0x8) adev->apu_flags |= AMD_APU_IS_RAVEN2; @@ -1455,11 +1452,6 @@ static int soc15_common_early_init(void *handle) break; case CHIP_RENOIR: adev->asic_funcs = &soc15_asic_funcs; - if ((adev->pdev->device == 0x1636) || - (adev->pdev->device == 0x164c)) - adev->apu_flags |= AMD_APU_IS_RENOIR; - else - adev->apu_flags |= AMD_APU_IS_GREEN_SARDINE; if (adev->apu_flags & AMD_APU_IS_RENOIR) adev->external_rev_id = adev->rev_id + 0x91; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c index 2660f03e63a7..dab290a4d19d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c @@ -218,7 +218,8 @@ svm_migrate_get_vram_page(struct svm_range *prange, unsigned long pfn) struct page *page; page = pfn_to_page(pfn); - page->zone_device_data = prange; + svm_range_bo_ref(prange->svm_bo); + page->zone_device_data = prange->svm_bo; get_page(page); lock_page(page); } @@ -293,15 +294,13 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange, for (i = j = 0; i < npages; i++) { struct page *spage; - dst[i] = cursor.start + (j << PAGE_SHIFT); - migrate->dst[i] = svm_migrate_addr_to_pfn(adev, dst[i]); - svm_migrate_get_vram_page(prange, migrate->dst[i]); - - migrate->dst[i] = migrate_pfn(migrate->dst[i]); - migrate->dst[i] |= MIGRATE_PFN_LOCKED; - - if (migrate->src[i] & MIGRATE_PFN_VALID) { - spage = migrate_pfn_to_page(migrate->src[i]); + spage = migrate_pfn_to_page(migrate->src[i]); + if (spage && !is_zone_device_page(spage)) { + dst[i] = cursor.start + (j << PAGE_SHIFT); + migrate->dst[i] = svm_migrate_addr_to_pfn(adev, dst[i]); + svm_migrate_get_vram_page(prange, migrate->dst[i]); + migrate->dst[i] = migrate_pfn(migrate->dst[i]); + migrate->dst[i] |= MIGRATE_PFN_LOCKED; src[i] = dma_map_page(dev, spage, 0, PAGE_SIZE, DMA_TO_DEVICE); r = dma_mapping_error(dev, src[i]); @@ -355,6 +354,20 @@ out_free_vram_pages: } } +#ifdef DEBUG_FORCE_MIXED_DOMAINS + for (i = 0, j = 0; i < npages; i += 4, j++) { + if (j & 1) + continue; + svm_migrate_put_vram_page(adev, dst[i]); + migrate->dst[i] = 0; + svm_migrate_put_vram_page(adev, dst[i + 1]); + migrate->dst[i + 1] = 0; + svm_migrate_put_vram_page(adev, dst[i + 2]); + migrate->dst[i + 2] = 0; + svm_migrate_put_vram_page(adev, dst[i + 3]); + migrate->dst[i + 3] = 0; + } +#endif out: return r; } @@ -365,20 +378,20 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange, uint64_t end) { uint64_t npages = (end - start) >> PAGE_SHIFT; + struct kfd_process_device *pdd; struct dma_fence *mfence = NULL; struct migrate_vma migrate; dma_addr_t *scratch; size_t size; void *buf; int r = -ENOMEM; - int retry = 0; memset(&migrate, 0, sizeof(migrate)); migrate.vma = vma; migrate.start = start; migrate.end = end; migrate.flags = MIGRATE_VMA_SELECT_SYSTEM; - migrate.pgmap_owner = adev; + migrate.pgmap_owner = SVM_ADEV_PGMAP_OWNER(adev); size = 2 * sizeof(*migrate.src) + sizeof(uint64_t) + sizeof(dma_addr_t); size *= npages; @@ -390,7 +403,6 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange, migrate.dst = migrate.src + npages; scratch = (dma_addr_t *)(migrate.dst + npages); -retry: r = migrate_vma_setup(&migrate); if (r) { pr_debug("failed %d prepare migrate svms 0x%p [0x%lx 0x%lx]\n", @@ -398,17 +410,9 @@ retry: goto out_free; } if (migrate.cpages != npages) { - pr_debug("collect 0x%lx/0x%llx pages, retry\n", migrate.cpages, + pr_debug("Partial migration. 0x%lx/0x%llx pages can be migrated\n", + migrate.cpages, npages); - migrate_vma_finalize(&migrate); - if (retry++ >= 3) { - r = -ENOMEM; - pr_debug("failed %d migrate svms 0x%p [0x%lx 0x%lx]\n", - r, prange->svms, prange->start, prange->last); - goto out_free; - } - - goto retry; } if (migrate.cpages) { @@ -425,6 +429,12 @@ retry: out_free: kvfree(buf); out: + if (!r) { + pdd = svm_range_get_pdd_by_adev(prange, adev); + if (pdd) + WRITE_ONCE(pdd->page_in, pdd->page_in + migrate.cpages); + } + return r; } @@ -464,7 +474,7 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc, prange->start, prange->last, best_loc); /* FIXME: workaround for page locking bug with invalid pages */ - svm_range_prefault(prange, mm); + svm_range_prefault(prange, mm, SVM_ADEV_PGMAP_OWNER(adev)); start = prange->start << PAGE_SHIFT; end = (prange->last + 1) << PAGE_SHIFT; @@ -493,15 +503,19 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc, static void svm_migrate_page_free(struct page *page) { - /* Keep this function to avoid warning */ + struct svm_range_bo *svm_bo = page->zone_device_data; + + if (svm_bo) { + pr_debug("svm_bo ref left: %d\n", kref_read(&svm_bo->kref)); + svm_range_bo_unref(svm_bo); + } } static int svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange, struct migrate_vma *migrate, struct dma_fence **mfence, - dma_addr_t *scratch) + dma_addr_t *scratch, uint64_t npages) { - uint64_t npages = migrate->cpages; struct device *dev = adev->dev; uint64_t *src; dma_addr_t *dst; @@ -518,15 +532,23 @@ svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange, src = (uint64_t *)(scratch + npages); dst = scratch; - for (i = 0, j = 0; i < npages; i++, j++, addr += PAGE_SIZE) { + for (i = 0, j = 0; i < npages; i++, addr += PAGE_SIZE) { struct page *spage; spage = migrate_pfn_to_page(migrate->src[i]); - if (!spage) { - pr_debug("failed get spage svms 0x%p [0x%lx 0x%lx]\n", + if (!spage || !is_zone_device_page(spage)) { + pr_debug("invalid page. Could be in CPU already svms 0x%p [0x%lx 0x%lx]\n", prange->svms, prange->start, prange->last); - r = -ENOMEM; - goto out_oom; + if (j) { + r = svm_migrate_copy_memory_gart(adev, dst + i - j, + src + i - j, j, + FROM_VRAM_TO_RAM, + mfence); + if (r) + goto out_oom; + j = 0; + } + continue; } src[i] = svm_migrate_addr(adev, spage); if (i > 0 && src[i] != src[i - 1] + PAGE_SIZE) { @@ -559,6 +581,7 @@ svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange, migrate->dst[i] = migrate_pfn(page_to_pfn(dpage)); migrate->dst[i] |= MIGRATE_PFN_LOCKED; + j++; } r = svm_migrate_copy_memory_gart(adev, dst + i - j, src + i - j, j, @@ -581,6 +604,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange, struct vm_area_struct *vma, uint64_t start, uint64_t end) { uint64_t npages = (end - start) >> PAGE_SHIFT; + struct kfd_process_device *pdd; struct dma_fence *mfence = NULL; struct migrate_vma migrate; dma_addr_t *scratch; @@ -593,7 +617,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange, migrate.start = start; migrate.end = end; migrate.flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE; - migrate.pgmap_owner = adev; + migrate.pgmap_owner = SVM_ADEV_PGMAP_OWNER(adev); size = 2 * sizeof(*migrate.src) + sizeof(uint64_t) + sizeof(dma_addr_t); size *= npages; @@ -616,7 +640,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange, if (migrate.cpages) { r = svm_migrate_copy_to_ram(adev, prange, &migrate, &mfence, - scratch); + scratch, npages); migrate_vma_pages(&migrate); svm_migrate_copy_done(adev, mfence); migrate_vma_finalize(&migrate); @@ -630,6 +654,12 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange, out_free: kvfree(buf); out: + if (!r) { + pdd = svm_range_get_pdd_by_adev(prange, adev); + if (pdd) + WRITE_ONCE(pdd->page_out, + pdd->page_out + migrate.cpages); + } return r; } @@ -859,7 +889,7 @@ int svm_migrate_init(struct amdgpu_device *adev) pgmap->range.start = res->start; pgmap->range.end = res->end; pgmap->ops = &svm_migrate_pgmap_ops; - pgmap->owner = adev; + pgmap->owner = SVM_ADEV_PGMAP_OWNER(adev); pgmap->flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE; r = devm_memremap_pages(adev->dev, pgmap); if (IS_ERR(r)) { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 6dc22fa1e555..3426743ed228 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -730,6 +730,15 @@ struct kfd_process_device { * number of CU's a device has along with number of other competing processes */ struct attribute attr_cu_occupancy; + + /* sysfs counters for GPU retry fault and page migration tracking */ + struct kobject *kobj_counters; + struct attribute attr_faults; + struct attribute attr_page_in; + struct attribute attr_page_out; + uint64_t faults; + uint64_t page_in; + uint64_t page_out; }; #define qpd_to_pdd(x) container_of(x, struct kfd_process_device, qpd) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 09b98a83f670..21ec8a18cad2 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -416,6 +416,29 @@ static ssize_t kfd_procfs_stats_show(struct kobject *kobj, return 0; } +static ssize_t kfd_sysfs_counters_show(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + struct kfd_process_device *pdd; + + if (!strcmp(attr->name, "faults")) { + pdd = container_of(attr, struct kfd_process_device, + attr_faults); + return sysfs_emit(buf, "%llu\n", READ_ONCE(pdd->faults)); + } + if (!strcmp(attr->name, "page_in")) { + pdd = container_of(attr, struct kfd_process_device, + attr_page_in); + return sysfs_emit(buf, "%llu\n", READ_ONCE(pdd->page_in)); + } + if (!strcmp(attr->name, "page_out")) { + pdd = container_of(attr, struct kfd_process_device, + attr_page_out); + return sysfs_emit(buf, "%llu\n", READ_ONCE(pdd->page_out)); + } + return 0; +} + static struct attribute attr_queue_size = { .name = "size", .mode = KFD_SYSFS_FILE_MODE @@ -451,13 +474,18 @@ static const struct sysfs_ops procfs_stats_ops = { .show = kfd_procfs_stats_show, }; -static struct attribute *procfs_stats_attrs[] = { - NULL -}; - static struct kobj_type procfs_stats_type = { .sysfs_ops = &procfs_stats_ops, - .default_attrs = procfs_stats_attrs, + .release = kfd_procfs_kobj_release, +}; + +static const struct sysfs_ops sysfs_counters_ops = { + .show = kfd_sysfs_counters_show, +}; + +static struct kobj_type sysfs_counters_type = { + .sysfs_ops = &sysfs_counters_ops, + .release = kfd_procfs_kobj_release, }; int kfd_procfs_add_queue(struct queue *q) @@ -484,34 +512,31 @@ int kfd_procfs_add_queue(struct queue *q) return 0; } -static int kfd_sysfs_create_file(struct kfd_process *p, struct attribute *attr, +static void kfd_sysfs_create_file(struct kobject *kobj, struct attribute *attr, char *name) { - int ret = 0; + int ret; - if (!p || !attr || !name) - return -EINVAL; + if (!kobj || !attr || !name) + return; attr->name = name; attr->mode = KFD_SYSFS_FILE_MODE; sysfs_attr_init(attr); - ret = sysfs_create_file(p->kobj, attr); - - return ret; + ret = sysfs_create_file(kobj, attr); + if (ret) + pr_warn("Create sysfs %s/%s failed %d", kobj->name, name, ret); } -static int kfd_procfs_add_sysfs_stats(struct kfd_process *p) +static void kfd_procfs_add_sysfs_stats(struct kfd_process *p) { - int ret = 0; + int ret; int i; char stats_dir_filename[MAX_SYSFS_FILENAME_LEN]; - if (!p) - return -EINVAL; - - if (!p->kobj) - return -EFAULT; + if (!p || !p->kobj) + return; /* * Create sysfs files for each GPU: @@ -521,63 +546,87 @@ static int kfd_procfs_add_sysfs_stats(struct kfd_process *p) */ for (i = 0; i < p->n_pdds; i++) { struct kfd_process_device *pdd = p->pdds[i]; - struct kobject *kobj_stats; snprintf(stats_dir_filename, MAX_SYSFS_FILENAME_LEN, "stats_%u", pdd->dev->id); - kobj_stats = kfd_alloc_struct(kobj_stats); - if (!kobj_stats) - return -ENOMEM; + pdd->kobj_stats = kfd_alloc_struct(pdd->kobj_stats); + if (!pdd->kobj_stats) + return; - ret = kobject_init_and_add(kobj_stats, - &procfs_stats_type, - p->kobj, - stats_dir_filename); + ret = kobject_init_and_add(pdd->kobj_stats, + &procfs_stats_type, + p->kobj, + stats_dir_filename); if (ret) { pr_warn("Creating KFD proc/stats_%s folder failed", - stats_dir_filename); - kobject_put(kobj_stats); - goto err; + stats_dir_filename); + kobject_put(pdd->kobj_stats); + pdd->kobj_stats = NULL; + return; } - pdd->kobj_stats = kobj_stats; - pdd->attr_evict.name = "evicted_ms"; - pdd->attr_evict.mode = KFD_SYSFS_FILE_MODE; - sysfs_attr_init(&pdd->attr_evict); - ret = sysfs_create_file(kobj_stats, &pdd->attr_evict); - if (ret) - pr_warn("Creating eviction stats for gpuid %d failed", - (int)pdd->dev->id); - + kfd_sysfs_create_file(pdd->kobj_stats, &pdd->attr_evict, + "evicted_ms"); /* Add sysfs file to report compute unit occupancy */ - if (pdd->dev->kfd2kgd->get_cu_occupancy != NULL) { - pdd->attr_cu_occupancy.name = "cu_occupancy"; - pdd->attr_cu_occupancy.mode = KFD_SYSFS_FILE_MODE; - sysfs_attr_init(&pdd->attr_cu_occupancy); - ret = sysfs_create_file(kobj_stats, - &pdd->attr_cu_occupancy); - if (ret) - pr_warn("Creating %s failed for gpuid: %d", - pdd->attr_cu_occupancy.name, - (int)pdd->dev->id); - } + if (pdd->dev->kfd2kgd->get_cu_occupancy) + kfd_sysfs_create_file(pdd->kobj_stats, + &pdd->attr_cu_occupancy, + "cu_occupancy"); } -err: - return ret; } - -static int kfd_procfs_add_sysfs_files(struct kfd_process *p) +static void kfd_procfs_add_sysfs_counters(struct kfd_process *p) { int ret = 0; int i; + char counters_dir_filename[MAX_SYSFS_FILENAME_LEN]; - if (!p) - return -EINVAL; + if (!p || !p->kobj) + return; - if (!p->kobj) - return -EFAULT; + /* + * Create sysfs files for each GPU which supports SVM + * - proc/<pid>/counters_<gpuid>/ + * - proc/<pid>/counters_<gpuid>/faults + * - proc/<pid>/counters_<gpuid>/page_in + * - proc/<pid>/counters_<gpuid>/page_out + */ + for_each_set_bit(i, p->svms.bitmap_supported, p->n_pdds) { + struct kfd_process_device *pdd = p->pdds[i]; + struct kobject *kobj_counters; + + snprintf(counters_dir_filename, MAX_SYSFS_FILENAME_LEN, + "counters_%u", pdd->dev->id); + kobj_counters = kfd_alloc_struct(kobj_counters); + if (!kobj_counters) + return; + + ret = kobject_init_and_add(kobj_counters, &sysfs_counters_type, + p->kobj, counters_dir_filename); + if (ret) { + pr_warn("Creating KFD proc/%s folder failed", + counters_dir_filename); + kobject_put(kobj_counters); + return; + } + + pdd->kobj_counters = kobj_counters; + kfd_sysfs_create_file(kobj_counters, &pdd->attr_faults, + "faults"); + kfd_sysfs_create_file(kobj_counters, &pdd->attr_page_in, + "page_in"); + kfd_sysfs_create_file(kobj_counters, &pdd->attr_page_out, + "page_out"); + } +} + +static void kfd_procfs_add_sysfs_files(struct kfd_process *p) +{ + int i; + + if (!p || !p->kobj) + return; /* * Create sysfs files for each GPU: @@ -589,20 +638,14 @@ static int kfd_procfs_add_sysfs_files(struct kfd_process *p) snprintf(pdd->vram_filename, MAX_SYSFS_FILENAME_LEN, "vram_%u", pdd->dev->id); - ret = kfd_sysfs_create_file(p, &pdd->attr_vram, pdd->vram_filename); - if (ret) - pr_warn("Creating vram usage for gpu id %d failed", - (int)pdd->dev->id); + kfd_sysfs_create_file(p->kobj, &pdd->attr_vram, + pdd->vram_filename); snprintf(pdd->sdma_filename, MAX_SYSFS_FILENAME_LEN, "sdma_%u", pdd->dev->id); - ret = kfd_sysfs_create_file(p, &pdd->attr_sdma, pdd->sdma_filename); - if (ret) - pr_warn("Creating sdma usage for gpu id %d failed", - (int)pdd->dev->id); + kfd_sysfs_create_file(p->kobj, &pdd->attr_sdma, + pdd->sdma_filename); } - - return ret; } void kfd_procfs_del_queue(struct queue *q) @@ -800,28 +843,17 @@ struct kfd_process *kfd_create_process(struct file *filep) goto out; } - process->attr_pasid.name = "pasid"; - process->attr_pasid.mode = KFD_SYSFS_FILE_MODE; - sysfs_attr_init(&process->attr_pasid); - ret = sysfs_create_file(process->kobj, &process->attr_pasid); - if (ret) - pr_warn("Creating pasid for pid %d failed", - (int)process->lead_thread->pid); + kfd_sysfs_create_file(process->kobj, &process->attr_pasid, + "pasid"); process->kobj_queues = kobject_create_and_add("queues", process->kobj); if (!process->kobj_queues) pr_warn("Creating KFD proc/queues folder failed"); - ret = kfd_procfs_add_sysfs_stats(process); - if (ret) - pr_warn("Creating sysfs stats dir for pid %d failed", - (int)process->lead_thread->pid); - - ret = kfd_procfs_add_sysfs_files(process); - if (ret) - pr_warn("Creating sysfs usage file for pid %d failed", - (int)process->lead_thread->pid); + kfd_procfs_add_sysfs_stats(process); + kfd_procfs_add_sysfs_files(process); + kfd_procfs_add_sysfs_counters(process); } out: if (!IS_ERR(process)) @@ -964,6 +996,50 @@ static void kfd_process_destroy_pdds(struct kfd_process *p) p->n_pdds = 0; } +static void kfd_process_remove_sysfs(struct kfd_process *p) +{ + struct kfd_process_device *pdd; + int i; + + if (!p->kobj) + return; + + sysfs_remove_file(p->kobj, &p->attr_pasid); + kobject_del(p->kobj_queues); + kobject_put(p->kobj_queues); + p->kobj_queues = NULL; + + for (i = 0; i < p->n_pdds; i++) { + pdd = p->pdds[i]; + + sysfs_remove_file(p->kobj, &pdd->attr_vram); + sysfs_remove_file(p->kobj, &pdd->attr_sdma); + + sysfs_remove_file(pdd->kobj_stats, &pdd->attr_evict); + if (pdd->dev->kfd2kgd->get_cu_occupancy) + sysfs_remove_file(pdd->kobj_stats, + &pdd->attr_cu_occupancy); + kobject_del(pdd->kobj_stats); + kobject_put(pdd->kobj_stats); + pdd->kobj_stats = NULL; + } + + for_each_set_bit(i, p->svms.bitmap_supported, p->n_pdds) { + pdd = p->pdds[i]; + + sysfs_remove_file(pdd->kobj_counters, &pdd->attr_faults); + sysfs_remove_file(pdd->kobj_counters, &pdd->attr_page_in); + sysfs_remove_file(pdd->kobj_counters, &pdd->attr_page_out); + kobject_del(pdd->kobj_counters); + kobject_put(pdd->kobj_counters); + pdd->kobj_counters = NULL; + } + + kobject_del(p->kobj); + kobject_put(p->kobj); + p->kobj = NULL; +} + /* No process locking is needed in this function, because the process * is not findable any more. We must assume that no other thread is * using it any more, otherwise we couldn't safely free the process @@ -973,33 +1049,7 @@ static void kfd_process_wq_release(struct work_struct *work) { struct kfd_process *p = container_of(work, struct kfd_process, release_work); - int i; - - /* Remove the procfs files */ - if (p->kobj) { - sysfs_remove_file(p->kobj, &p->attr_pasid); - kobject_del(p->kobj_queues); - kobject_put(p->kobj_queues); - p->kobj_queues = NULL; - - for (i = 0; i < p->n_pdds; i++) { - struct kfd_process_device *pdd = p->pdds[i]; - - sysfs_remove_file(p->kobj, &pdd->attr_vram); - sysfs_remove_file(p->kobj, &pdd->attr_sdma); - sysfs_remove_file(p->kobj, &pdd->attr_evict); - if (pdd->dev->kfd2kgd->get_cu_occupancy != NULL) - sysfs_remove_file(p->kobj, &pdd->attr_cu_occupancy); - kobject_del(pdd->kobj_stats); - kobject_put(pdd->kobj_stats); - pdd->kobj_stats = NULL; - } - - kobject_del(p->kobj); - kobject_put(p->kobj); - p->kobj = NULL; - } - + kfd_process_remove_sysfs(p); kfd_iommu_unbind_process(p); kfd_process_free_outstanding_kfd_bos(p); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index 95a6c36cea4c..243dd1efcdbf 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -153,6 +153,7 @@ void pqm_uninit(struct process_queue_manager *pqm) if (pqn->q && pqn->q->gws) amdgpu_amdkfd_remove_gws_from_process(pqm->process->kgd_process_info, pqn->q->gws); + kfd_procfs_del_queue(pqn->q); uninit_queue(pqn->q); list_del(&pqn->process_queue_list); kfree(pqn); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index dff1011dd7ee..9a71d8919bd6 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -119,28 +119,40 @@ static void svm_range_remove_notifier(struct svm_range *prange) } static int -svm_range_dma_map_dev(struct device *dev, dma_addr_t **dma_addr, - unsigned long *hmm_pfns, uint64_t npages) +svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange, + unsigned long *hmm_pfns, uint32_t gpuidx) { enum dma_data_direction dir = DMA_BIDIRECTIONAL; - dma_addr_t *addr = *dma_addr; + dma_addr_t *addr = prange->dma_addr[gpuidx]; + struct device *dev = adev->dev; struct page *page; int i, r; if (!addr) { - addr = kvmalloc_array(npages, sizeof(*addr), + addr = kvmalloc_array(prange->npages, sizeof(*addr), GFP_KERNEL | __GFP_ZERO); if (!addr) return -ENOMEM; - *dma_addr = addr; + prange->dma_addr[gpuidx] = addr; } - for (i = 0; i < npages; i++) { + for (i = 0; i < prange->npages; i++) { if (WARN_ONCE(addr[i] && !dma_mapping_error(dev, addr[i]), "leaking dma mapping\n")) dma_unmap_page(dev, addr[i], PAGE_SIZE, dir); page = hmm_pfn_to_page(hmm_pfns[i]); + if (is_zone_device_page(page)) { + struct amdgpu_device *bo_adev = + amdgpu_ttm_adev(prange->svm_bo->bo->tbo.bdev); + + addr[i] = (hmm_pfns[i] << PAGE_SHIFT) + + bo_adev->vm_manager.vram_base_offset - + bo_adev->kfd.dev->pgmap.range.start; + addr[i] |= SVM_RANGE_VRAM_DOMAIN; + pr_debug("vram address detected: 0x%llx\n", addr[i]); + continue; + } addr[i] = dma_map_page(dev, page, 0, PAGE_SIZE, dir); r = dma_mapping_error(dev, addr[i]); if (r) { @@ -175,8 +187,7 @@ svm_range_dma_map(struct svm_range *prange, unsigned long *bitmap, } adev = (struct amdgpu_device *)pdd->dev->kgd; - r = svm_range_dma_map_dev(adev->dev, &prange->dma_addr[gpuidx], - hmm_pfns, prange->npages); + r = svm_range_dma_map_dev(adev, prange, hmm_pfns, gpuidx); if (r) break; } @@ -301,14 +312,6 @@ static bool svm_bo_ref_unless_zero(struct svm_range_bo *svm_bo) return true; } -static struct svm_range_bo *svm_range_bo_ref(struct svm_range_bo *svm_bo) -{ - if (svm_bo) - kref_get(&svm_bo->kref); - - return svm_bo; -} - static void svm_range_bo_release(struct kref *kref) { struct svm_range_bo *svm_bo; @@ -347,7 +350,7 @@ static void svm_range_bo_release(struct kref *kref) kfree(svm_bo); } -static void svm_range_bo_unref(struct svm_range_bo *svm_bo) +void svm_range_bo_unref(struct svm_range_bo *svm_bo) { if (!svm_bo) return; @@ -564,6 +567,24 @@ svm_range_get_adev_by_id(struct svm_range *prange, uint32_t gpu_id) return (struct amdgpu_device *)pdd->dev->kgd; } +struct kfd_process_device * +svm_range_get_pdd_by_adev(struct svm_range *prange, struct amdgpu_device *adev) +{ + struct kfd_process *p; + int32_t gpu_idx, gpuid; + int r; + + p = container_of(prange->svms, struct kfd_process, svms); + + r = kfd_process_gpuid_from_kgd(p, adev, &gpuid, &gpu_idx); + if (r) { + pr_debug("failed to get device id by adev %p\n", adev); + return NULL; + } + + return kfd_process_device_from_gpuidx(p, gpu_idx); +} + static int svm_range_bo_validate(void *param, struct amdgpu_bo *bo) { struct ttm_operation_ctx ctx = { false, false }; @@ -1002,21 +1023,22 @@ svm_range_split_by_granularity(struct kfd_process *p, struct mm_struct *mm, } static uint64_t -svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange) +svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange, + int domain) { struct amdgpu_device *bo_adev; uint32_t flags = prange->flags; uint32_t mapping_flags = 0; uint64_t pte_flags; - bool snoop = !prange->ttm_res; + bool snoop = (domain != SVM_RANGE_VRAM_DOMAIN); bool coherent = flags & KFD_IOCTL_SVM_FLAG_COHERENT; - if (prange->svm_bo && prange->ttm_res) + if (domain == SVM_RANGE_VRAM_DOMAIN) bo_adev = amdgpu_ttm_adev(prange->svm_bo->bo->tbo.bdev); switch (adev->asic_type) { case CHIP_ARCTURUS: - if (prange->svm_bo && prange->ttm_res) { + if (domain == SVM_RANGE_VRAM_DOMAIN) { if (bo_adev == adev) { mapping_flags |= coherent ? AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_RW; @@ -1032,7 +1054,7 @@ svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange) } break; case CHIP_ALDEBARAN: - if (prange->svm_bo && prange->ttm_res) { + if (domain == SVM_RANGE_VRAM_DOMAIN) { if (bo_adev == adev) { mapping_flags |= coherent ? AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_RW; @@ -1062,14 +1084,14 @@ svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange) mapping_flags |= AMDGPU_VM_PAGE_EXECUTABLE; pte_flags = AMDGPU_PTE_VALID; - pte_flags |= prange->ttm_res ? 0 : AMDGPU_PTE_SYSTEM; + pte_flags |= (domain == SVM_RANGE_VRAM_DOMAIN) ? 0 : AMDGPU_PTE_SYSTEM; pte_flags |= snoop ? AMDGPU_PTE_SNOOPED : 0; pte_flags |= amdgpu_gem_va_map_flags(adev, mapping_flags); pr_debug("svms 0x%p [0x%lx 0x%lx] vram %d PTE 0x%llx mapping 0x%x\n", prange->svms, prange->start, prange->last, - prange->ttm_res ? 1:0, pte_flags, mapping_flags); + (domain == SVM_RANGE_VRAM_DOMAIN) ? 1:0, pte_flags, mapping_flags); return pte_flags; } @@ -1140,31 +1162,41 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm, struct amdgpu_bo_va bo_va; bool table_freed = false; uint64_t pte_flags; + unsigned long last_start; + int last_domain; int r = 0; + int64_t i; pr_debug("svms 0x%p [0x%lx 0x%lx]\n", prange->svms, prange->start, prange->last); - if (prange->svm_bo && prange->ttm_res) { + if (prange->svm_bo && prange->ttm_res) bo_va.is_xgmi = amdgpu_xgmi_same_hive(adev, bo_adev); - prange->mapping.bo_va = &bo_va; - } - prange->mapping.start = prange->start; - prange->mapping.last = prange->last; - prange->mapping.offset = prange->ttm_res ? prange->offset : 0; - pte_flags = svm_range_get_pte_flags(adev, prange); + last_start = prange->start; + for (i = 0; i < prange->npages; i++) { + last_domain = dma_addr[i] & SVM_RANGE_VRAM_DOMAIN; + dma_addr[i] &= ~SVM_RANGE_VRAM_DOMAIN; + if ((prange->start + i) < prange->last && + last_domain == (dma_addr[i + 1] & SVM_RANGE_VRAM_DOMAIN)) + continue; - r = amdgpu_vm_bo_update_mapping(adev, bo_adev, vm, false, false, NULL, - prange->mapping.start, - prange->mapping.last, pte_flags, - prange->mapping.offset, - prange->ttm_res, - dma_addr, &vm->last_update, - &table_freed); - if (r) { - pr_debug("failed %d to map to gpu 0x%lx\n", r, prange->start); - goto out; + pr_debug("Mapping range [0x%lx 0x%llx] on domain: %s\n", + last_start, prange->start + i, last_domain ? "GPU" : "CPU"); + pte_flags = svm_range_get_pte_flags(adev, prange, last_domain); + r = amdgpu_vm_bo_update_mapping(adev, bo_adev, vm, false, false, NULL, + last_start, + prange->start + i, pte_flags, + last_start - prange->start, + NULL, + dma_addr, + &vm->last_update, + &table_freed); + if (r) { + pr_debug("failed %d to map to gpu 0x%lx\n", r, prange->start); + goto out; + } + last_start = prange->start + i + 1; } r = amdgpu_vm_update_pdes(adev, vm, false); @@ -1185,7 +1217,6 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm, p->pasid, TLB_FLUSH_LEGACY); } out: - prange->mapping.bo_va = NULL; return r; } @@ -1319,6 +1350,17 @@ static void svm_range_unreserve_bos(struct svm_validate_context *ctx) ttm_eu_backoff_reservation(&ctx->ticket, &ctx->validate_list); } +static void *kfd_svm_page_owner(struct kfd_process *p, int32_t gpuidx) +{ + struct kfd_process_device *pdd; + struct amdgpu_device *adev; + + pdd = kfd_process_device_from_gpuidx(p, gpuidx); + adev = (struct amdgpu_device *)pdd->dev->kgd; + + return SVM_ADEV_PGMAP_OWNER(adev); +} + /* * Validation+GPU mapping with concurrent invalidation (MMU notifiers) * @@ -1349,6 +1391,9 @@ static int svm_range_validate_and_map(struct mm_struct *mm, { struct svm_validate_context ctx; struct hmm_range *hmm_range; + struct kfd_process *p; + void *owner; + int32_t idx; int r = 0; ctx.process = container_of(prange->svms, struct kfd_process, svms); @@ -1394,33 +1439,38 @@ static int svm_range_validate_and_map(struct mm_struct *mm, svm_range_reserve_bos(&ctx); - if (!prange->actual_loc) { - r = amdgpu_hmm_range_get_pages(&prange->notifier, mm, NULL, - prange->start << PAGE_SHIFT, - prange->npages, &hmm_range, - false, true); - if (r) { - pr_debug("failed %d to get svm range pages\n", r); - goto unreserve_out; - } - - r = svm_range_dma_map(prange, ctx.bitmap, - hmm_range->hmm_pfns); - if (r) { - pr_debug("failed %d to dma map range\n", r); - goto unreserve_out; + p = container_of(prange->svms, struct kfd_process, svms); + owner = kfd_svm_page_owner(p, find_first_bit(ctx.bitmap, + MAX_GPU_INSTANCE)); + for_each_set_bit(idx, ctx.bitmap, MAX_GPU_INSTANCE) { + if (kfd_svm_page_owner(p, idx) != owner) { + owner = NULL; + break; } + } + r = amdgpu_hmm_range_get_pages(&prange->notifier, mm, NULL, + prange->start << PAGE_SHIFT, + prange->npages, &hmm_range, + false, true, owner); + if (r) { + pr_debug("failed %d to get svm range pages\n", r); + goto unreserve_out; + } - prange->validated_once = true; + r = svm_range_dma_map(prange, ctx.bitmap, + hmm_range->hmm_pfns); + if (r) { + pr_debug("failed %d to dma map range\n", r); + goto unreserve_out; } + prange->validated_once = true; + svm_range_lock(prange); - if (!prange->actual_loc) { - if (amdgpu_hmm_range_get_pages_done(hmm_range)) { - pr_debug("hmm update the range, need validate again\n"); - r = -EAGAIN; - goto unlock_out; - } + if (amdgpu_hmm_range_get_pages_done(hmm_range)) { + pr_debug("hmm update the range, need validate again\n"); + r = -EAGAIN; + goto unlock_out; } if (!list_empty(&prange->child_list)) { pr_debug("range split by unmap in parallel, validate again\n"); @@ -1572,6 +1622,7 @@ svm_range_evict(struct svm_range *prange, struct mm_struct *mm, unsigned long start, unsigned long last) { struct svm_range_list *svms = prange->svms; + struct svm_range *pchild; struct kfd_process *p; int r = 0; @@ -1583,7 +1634,19 @@ svm_range_evict(struct svm_range *prange, struct mm_struct *mm, if (!p->xnack_enabled) { int evicted_ranges; - atomic_inc(&prange->invalid); + list_for_each_entry(pchild, &prange->child_list, child_list) { + mutex_lock_nested(&pchild->lock, 1); + if (pchild->start <= last && pchild->last >= start) { + pr_debug("increment pchild invalid [0x%lx 0x%lx]\n", + pchild->start, pchild->last); + atomic_inc(&pchild->invalid); + } + mutex_unlock(&pchild->lock); + } + + if (prange->start <= last && prange->last >= start) + atomic_inc(&prange->invalid); + evicted_ranges = atomic_inc_return(&svms->evicted_ranges); if (evicted_ranges != 1) return r; @@ -1600,7 +1663,6 @@ svm_range_evict(struct svm_range *prange, struct mm_struct *mm, schedule_delayed_work(&svms->restore_work, msecs_to_jiffies(AMDGPU_SVM_RANGE_RESTORE_DELAY_MS)); } else { - struct svm_range *pchild; unsigned long s, l; pr_debug("invalidate unmap svms 0x%p [0x%lx 0x%lx] from GPUs\n", @@ -2311,6 +2373,27 @@ static bool svm_range_skip_recover(struct svm_range *prange) return false; } +static void +svm_range_count_fault(struct amdgpu_device *adev, struct kfd_process *p, + struct svm_range *prange, int32_t gpuidx) +{ + struct kfd_process_device *pdd; + + if (gpuidx == MAX_GPU_INSTANCE) + /* fault is on different page of same range + * or fault is skipped to recover later + */ + pdd = svm_range_get_pdd_by_adev(prange, adev); + else + /* fault recovered + * or fault cannot recover because GPU no access on the range + */ + pdd = kfd_process_device_from_gpuidx(p, gpuidx); + + if (pdd) + WRITE_ONCE(pdd->faults, pdd->faults + 1); +} + int svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid, uint64_t addr) @@ -2320,7 +2403,8 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid, struct svm_range *prange; struct kfd_process *p; uint64_t timestamp; - int32_t best_loc, gpuidx; + int32_t best_loc; + int32_t gpuidx = MAX_GPU_INSTANCE; bool write_locked = false; int r = 0; @@ -2440,6 +2524,9 @@ out_unlock_range: out_unlock_svms: mutex_unlock(&svms->lock); mmap_read_unlock(mm); + + svm_range_count_fault(adev, p, prange, gpuidx); + mmput(mm); out: kfd_unref_process(p); @@ -2662,7 +2749,8 @@ out: /* FIXME: This is a workaround for page locking bug when some pages are * invalid during migration to VRAM */ -void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm) +void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm, + void *owner) { struct hmm_range *hmm_range; int r; @@ -2673,7 +2761,7 @@ void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm) r = amdgpu_hmm_range_get_pages(&prange->notifier, mm, NULL, prange->start << PAGE_SHIFT, prange->npages, &hmm_range, - false, true); + false, true, owner); if (!r) { amdgpu_hmm_range_get_pages_done(hmm_range); prange->validated_once = true; @@ -2718,16 +2806,6 @@ svm_range_trigger_migration(struct mm_struct *mm, struct svm_range *prange, best_loc == prange->actual_loc) return 0; - /* - * Prefetch to GPU without host access flag, set actual_loc to gpu, then - * validate on gpu and map to gpus will be handled afterwards. - */ - if (best_loc && !prange->actual_loc && - !(prange->flags & KFD_IOCTL_SVM_FLAG_HOST_ACCESS)) { - prange->actual_loc = best_loc; - return 0; - } - if (!best_loc) { r = svm_migrate_vram_to_ram(prange, mm); *migrated = !r; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h index 0c0fc399395e..3fc1fd8b4fbc 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h @@ -35,6 +35,10 @@ #include "amdgpu.h" #include "kfd_priv.h" +#define SVM_RANGE_VRAM_DOMAIN (1UL << 0) +#define SVM_ADEV_PGMAP_OWNER(adev)\ + ((adev)->hive ? (void *)(adev)->hive : (void *)(adev)) + struct svm_range_bo { struct amdgpu_bo *bo; struct kref kref; @@ -110,7 +114,6 @@ struct svm_range { struct list_head update_list; struct list_head remove_list; struct list_head insert_list; - struct amdgpu_bo_va_mapping mapping; uint64_t npages; dma_addr_t *dma_addr[MAX_GPU_INSTANCE]; struct ttm_resource *ttm_res; @@ -147,6 +150,14 @@ static inline void svm_range_unlock(struct svm_range *prange) mutex_unlock(&prange->lock); } +static inline struct svm_range_bo *svm_range_bo_ref(struct svm_range_bo *svm_bo) +{ + if (svm_bo) + kref_get(&svm_bo->kref); + + return svm_bo; +} + int svm_range_list_init(struct kfd_process *p); void svm_range_list_fini(struct kfd_process *p); int svm_ioctl(struct kfd_process *p, enum kfd_ioctl_svm_op op, uint64_t start, @@ -173,13 +184,17 @@ void schedule_deferred_list_work(struct svm_range_list *svms); void svm_range_dma_unmap(struct device *dev, dma_addr_t *dma_addr, unsigned long offset, unsigned long npages); void svm_range_free_dma_mappings(struct svm_range *prange); -void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm); +void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm, + void *owner); +struct kfd_process_device * +svm_range_get_pdd_by_adev(struct svm_range *prange, struct amdgpu_device *adev); /* SVM API and HMM page migration work together, device memory type * is initialized to not 0 when page migration register device memory. */ #define KFD_IS_SVM_API_SUPPORTED(dev) ((dev)->pgmap.type != 0) +void svm_range_bo_unref(struct svm_range_bo *svm_bo); #else struct kfd_process; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index b5b5ccf0ed71..01e1062dc235 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1160,6 +1160,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) if (amdgpu_dc_feature_mask & DC_DISABLE_FRACTIONAL_PWM_MASK) init_data.flags.disable_fractional_pwm = true; + if (amdgpu_dc_feature_mask & DC_EDP_NO_POWER_SEQUENCING) + init_data.flags.edp_no_power_sequencing = true; + init_data.flags.power_down_display_on_boot = true; INIT_LIST_HEAD(&adev->dm.da_list); @@ -10118,7 +10121,7 @@ static int validate_overlay(struct drm_atomic_state *state) int i; struct drm_plane *plane; struct drm_plane_state *new_plane_state; - struct drm_plane_state *primary_state, *cursor_state, *overlay_state = NULL; + struct drm_plane_state *primary_state, *overlay_state = NULL; /* Check if primary plane is contained inside overlay */ for_each_new_plane_in_state_reverse(state, plane, new_plane_state, i) { @@ -10148,14 +10151,6 @@ static int validate_overlay(struct drm_atomic_state *state) if (!primary_state->crtc) return 0; - /* check if cursor plane is enabled */ - cursor_state = drm_atomic_get_plane_state(state, overlay_state->crtc->cursor); - if (IS_ERR(cursor_state)) - return PTR_ERR(cursor_state); - - if (drm_atomic_plane_disabling(plane->state, cursor_state)) - return 0; - /* Perform the bounds check to ensure the overlay plane covers the primary */ if (primary_state->crtc_x < overlay_state->crtc_x || primary_state->crtc_y < overlay_state->crtc_y || diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 5101a4f8f69f..45640f1c26c4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -297,6 +297,7 @@ struct dc_config { bool allow_seamless_boot_optimization; bool power_down_display_on_boot; bool edp_not_connected; + bool edp_no_power_sequencing; bool force_enum_edp; bool forced_clocks; bool allow_lttpr_non_transparent_mode; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 2938caaa2299..62d595ded866 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1022,8 +1022,20 @@ void dce110_edp_backlight_control( /* dc_service_sleep_in_milliseconds(50); */ /*edp 1.2*/ panel_instance = link->panel_cntl->inst; - if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) - edp_receiver_ready_T7(link); + + if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) { + if (!link->dc->config.edp_no_power_sequencing) + /* + * Sometimes, DP receiver chip power-controlled externally by an + * Embedded Controller could be treated and used as eDP, + * if it drives mobile display. In this case, + * we shouldn't be doing power-sequencing, hence we can skip + * waiting for T7-ready. + */ + edp_receiver_ready_T7(link); + else + DC_LOG_DC("edp_receiver_ready_T7 skipped\n"); + } if (ctx->dc->ctx->dmub_srv && ctx->dc->debug.dmub_command_table) { @@ -1048,8 +1060,19 @@ void dce110_edp_backlight_control( dc_link_backlight_enable_aux(link, enable); /*edp 1.2*/ - if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF) - edp_add_delay_for_T9(link); + if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF) { + if (!link->dc->config.edp_no_power_sequencing) + /* + * Sometimes, DP receiver chip power-controlled externally by an + * Embedded Controller could be treated and used as eDP, + * if it drives mobile display. In this case, + * we shouldn't be doing power-sequencing, hence we can skip + * waiting for T9-ready. + */ + edp_add_delay_for_T9(link); + else + DC_LOG_DC("edp_receiver_ready_T9 skipped\n"); + } if (!enable && link->dpcd_sink_ext_caps.bits.oled) msleep(OLED_PRE_T11_DELAY); diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile index 5dcdc5a858fe..4bab97acb155 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile @@ -28,6 +28,7 @@ endif CFLAGS_$(AMDDALPATH)/dc/dcn31/dcn31_resource.o += -mhard-float endif +ifdef CONFIG_X86 ifdef IS_OLD_GCC # Stack alignment mismatch, proceed with caution. # GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3 @@ -36,6 +37,7 @@ CFLAGS_$(AMDDALPATH)/dc/dcn31/dcn31_resource.o += -mpreferred-stack-boundary=4 else CFLAGS_$(AMDDALPATH)/dc/dcn31/dcn31_resource.o += -msse2 endif +endif AMD_DAL_DCN31 = $(addprefix $(AMDDALPATH)/dc/dcn31/,$(DCN31)) diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index d34024fd798a..45862167e6ce 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -50,6 +50,10 @@ dml_ccflags += -msse2 endif endif +ifneq ($(CONFIG_FRAME_WARN),0) +frame_warn_flag := -Wframe-larger-than=2048 +endif + CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags) ifdef CONFIG_DRM_AMD_DC_DCN @@ -60,9 +64,9 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20v2.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn21/display_mode_vba_21.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn21/display_rq_dlg_calc_21.o := $(dml_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_mode_vba_30.o := $(dml_ccflags) -Wframe-larger-than=2048 +CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_mode_vba_30.o := $(dml_ccflags) $(frame_warn_flag) CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_ccflags) -Wframe-larger-than=2048 +CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_ccflags) $(frame_warn_flag) CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_rcflags) diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c index 5f245bde54ff..a2a4fbeb83f8 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c @@ -119,7 +119,7 @@ bool dal_irq_service_set( dal_irq_service_ack(irq_service, source); - if (info->funcs->set) + if (info->funcs && info->funcs->set) return info->funcs->set(irq_service, info, enable); dal_irq_service_set_generic(irq_service, info, enable); @@ -153,7 +153,7 @@ bool dal_irq_service_ack( return false; } - if (info->funcs->ack) + if (info->funcs && info->funcs->ack) return info->funcs->ack(irq_service, info); dal_irq_service_ack_generic(irq_service, info); diff --git a/drivers/gpu/drm/amd/display/dc/irq_types.h b/drivers/gpu/drm/amd/display/dc/irq_types.h index 5f9346622301..1139b9eb9f6f 100644 --- a/drivers/gpu/drm/amd/display/dc/irq_types.h +++ b/drivers/gpu/drm/amd/display/dc/irq_types.h @@ -165,7 +165,7 @@ enum irq_type }; #define DAL_VALID_IRQ_SRC_NUM(src) \ - ((src) <= DAL_IRQ_SOURCES_NUMBER && (src) > DC_IRQ_SOURCE_INVALID) + ((src) < DAL_IRQ_SOURCES_NUMBER && (src) > DC_IRQ_SOURCE_INVALID) /* Number of Page Flip IRQ Sources. */ #define DAL_PFLIP_IRQ_SRC_NUM \ diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c index 8c886ece71f6..973de346410d 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c @@ -352,3 +352,63 @@ uint32_t dmub_dcn31_get_current_time(struct dmub_srv *dmub) { return REG_READ(DMCUB_TIMER_CURRENT); } + +void dmub_dcn31_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data) +{ + uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset; + uint32_t is_traceport_enabled, is_cw0_enabled, is_cw6_enabled; + + if (!dmub || !diag_data) + return; + + memset(diag_data, 0, sizeof(*diag_data)); + + diag_data->dmcub_version = dmub->fw_version; + + diag_data->scratch[0] = REG_READ(DMCUB_SCRATCH0); + diag_data->scratch[1] = REG_READ(DMCUB_SCRATCH1); + diag_data->scratch[2] = REG_READ(DMCUB_SCRATCH2); + diag_data->scratch[3] = REG_READ(DMCUB_SCRATCH3); + diag_data->scratch[4] = REG_READ(DMCUB_SCRATCH4); + diag_data->scratch[5] = REG_READ(DMCUB_SCRATCH5); + diag_data->scratch[6] = REG_READ(DMCUB_SCRATCH6); + diag_data->scratch[7] = REG_READ(DMCUB_SCRATCH7); + diag_data->scratch[8] = REG_READ(DMCUB_SCRATCH8); + diag_data->scratch[9] = REG_READ(DMCUB_SCRATCH9); + diag_data->scratch[10] = REG_READ(DMCUB_SCRATCH10); + diag_data->scratch[11] = REG_READ(DMCUB_SCRATCH11); + diag_data->scratch[12] = REG_READ(DMCUB_SCRATCH12); + diag_data->scratch[13] = REG_READ(DMCUB_SCRATCH13); + diag_data->scratch[14] = REG_READ(DMCUB_SCRATCH14); + diag_data->scratch[15] = REG_READ(DMCUB_SCRATCH15); + + diag_data->undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR); + diag_data->inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR); + diag_data->data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR); + + diag_data->inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR); + diag_data->inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR); + diag_data->inbox1_size = REG_READ(DMCUB_INBOX1_SIZE); + + diag_data->inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR); + diag_data->inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR); + diag_data->inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); + + REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled); + diag_data->is_dmcub_enabled = is_dmub_enabled; + + REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset); + diag_data->is_dmcub_soft_reset = is_soft_reset; + + REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset); + diag_data->is_dmcub_secure_reset = is_sec_reset; + + REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled); + diag_data->is_traceport_en = is_traceport_enabled; + + REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled); + diag_data->is_cw0_enabled = is_cw0_enabled; + + REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); + diag_data->is_cw6_enabled = is_cw6_enabled; +} diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h index 2829c3e9a310..9456a6a2d518 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h @@ -36,6 +36,9 @@ struct dmub_srv; DMUB_SR(DMCUB_CNTL) \ DMUB_SR(DMCUB_CNTL2) \ DMUB_SR(DMCUB_SEC_CNTL) \ + DMUB_SR(DMCUB_INBOX0_SIZE) \ + DMUB_SR(DMCUB_INBOX0_RPTR) \ + DMUB_SR(DMCUB_INBOX0_WPTR) \ DMUB_SR(DMCUB_INBOX1_BASE_ADDRESS) \ DMUB_SR(DMCUB_INBOX1_SIZE) \ DMUB_SR(DMCUB_INBOX1_RPTR) \ @@ -103,11 +106,15 @@ struct dmub_srv; DMUB_SR(DMCUB_SCRATCH14) \ DMUB_SR(DMCUB_SCRATCH15) \ DMUB_SR(DMCUB_GPINT_DATAIN1) \ + DMUB_SR(DMCUB_GPINT_DATAOUT) \ DMUB_SR(CC_DC_PIPE_DIS) \ DMUB_SR(MMHUBBUB_SOFT_RESET) \ DMUB_SR(DCN_VM_FB_LOCATION_BASE) \ DMUB_SR(DCN_VM_FB_OFFSET) \ - DMUB_SR(DMCUB_TIMER_CURRENT) + DMUB_SR(DMCUB_TIMER_CURRENT) \ + DMUB_SR(DMCUB_INST_FETCH_FAULT_ADDR) \ + DMUB_SR(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR) \ + DMUB_SR(DMCUB_DATA_WRITE_FAULT_ADDR) #define DMUB_DCN31_FIELDS() \ DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \ @@ -115,6 +122,7 @@ struct dmub_srv; DMUB_SF(DMCUB_CNTL2, DMCUB_SOFT_RESET) \ DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET) \ DMUB_SF(DMCUB_SEC_CNTL, DMCUB_MEM_UNIT_ID) \ + DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS) \ DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_TOP_ADDRESS) \ DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE) \ DMUB_SF(DMCUB_REGION3_CW1_TOP_ADDRESS, DMCUB_REGION3_CW1_TOP_ADDRESS) \ @@ -138,11 +146,13 @@ struct dmub_srv; DMUB_SF(CC_DC_PIPE_DIS, DC_DMCUB_ENABLE) \ DMUB_SF(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET) \ DMUB_SF(DCN_VM_FB_LOCATION_BASE, FB_BASE) \ - DMUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET) + DMUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET) \ + DMUB_SF(DMCUB_INBOX0_WPTR, DMCUB_INBOX0_WPTR) struct dmub_srv_dcn31_reg_offset { #define DMUB_SR(reg) uint32_t reg; DMUB_DCN31_REGS() + DMCUB_INTERNAL_REGS() #undef DMUB_SR }; @@ -227,4 +237,6 @@ void dmub_dcn31_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset); uint32_t dmub_dcn31_get_current_time(struct dmub_srv *dmub); +void dmub_dcn31_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data); + #endif /* _DMUB_DCN31_H_ */ diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c index fd7e996ab1d7..2bdbd7406f56 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -208,6 +208,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) break; case DMUB_ASIC_DCN31: + dmub->regs_dcn31 = &dmub_srv_dcn31_regs; funcs->reset = dmub_dcn31_reset; funcs->reset_release = dmub_dcn31_reset_release; funcs->backdoor_load = dmub_dcn31_backdoor_load; @@ -231,9 +232,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) funcs->get_outbox0_wptr = dmub_dcn31_get_outbox0_wptr; funcs->set_outbox0_rptr = dmub_dcn31_set_outbox0_rptr; - if (asic == DMUB_ASIC_DCN31) { - dmub->regs_dcn31 = &dmub_srv_dcn31_regs; - } + funcs->get_diagnostic_data = dmub_dcn31_get_diagnostic_data; funcs->get_current_time = dmub_dcn31_get_current_time; diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index 332b0df53e52..ff1d3d4a6488 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -223,10 +223,12 @@ enum amd_harvest_ip_mask { }; enum DC_FEATURE_MASK { - DC_FBC_MASK = 0x1, - DC_MULTI_MON_PP_MCLK_SWITCH_MASK = 0x2, - DC_DISABLE_FRACTIONAL_PWM_MASK = 0x4, - DC_PSR_MASK = 0x8, + //Default value can be found at "uint amdgpu_dc_feature_mask" + DC_FBC_MASK = (1 << 0), //0x1, disabled by default + DC_MULTI_MON_PP_MCLK_SWITCH_MASK = (1 << 1), //0x2, enabled by default + DC_DISABLE_FRACTIONAL_PWM_MASK = (1 << 2), //0x4, disabled by default + DC_PSR_MASK = (1 << 3), //0x8, disabled by default + DC_EDP_NO_POWER_SEQUENCING = (1 << 4), //0x10, disabled by default }; enum DC_DEBUG_MASK { diff --git a/drivers/gpu/drm/amd/include/navi10_enum.h b/drivers/gpu/drm/amd/include/navi10_enum.h index d5ead9680c6e..84bcb96f76ea 100644 --- a/drivers/gpu/drm/amd/include/navi10_enum.h +++ b/drivers/gpu/drm/amd/include/navi10_enum.h @@ -430,7 +430,7 @@ ARRAY_2D_DEPTH = 0x00000001, */ typedef enum ENUM_NUM_SIMD_PER_CU { -NUM_SIMD_PER_CU = 0x00000004, +NUM_SIMD_PER_CU = 0x00000002, } ENUM_NUM_SIMD_PER_CU; /* diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index a276ebad47e6..769f58d5ae1a 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -2902,14 +2902,15 @@ static ssize_t amdgpu_hwmon_show_power_cap_min(struct device *dev, return sprintf(buf, "%i\n", 0); } -static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, - struct device_attribute *attr, - char *buf) + +static ssize_t amdgpu_hwmon_show_power_cap_generic(struct device *dev, + struct device_attribute *attr, + char *buf, + enum pp_power_limit_level pp_limit_level) { struct amdgpu_device *adev = dev_get_drvdata(dev); const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; enum pp_power_type power_type = to_sensor_dev_attr(attr)->index; - enum pp_power_limit_level pp_limit_level = PP_PWR_LIMIT_MAX; uint32_t limit; ssize_t size; int r; @@ -2919,17 +2920,17 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, if (adev->in_suspend && !adev->in_runpm) return -EPERM; + if ( !(pp_funcs && pp_funcs->get_power_limit)) + return -ENODATA; + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } - if (pp_funcs && pp_funcs->get_power_limit) - r = pp_funcs->get_power_limit(adev->powerplay.pp_handle, &limit, - pp_limit_level, power_type); - else - r = -ENODATA; + r = pp_funcs->get_power_limit(adev->powerplay.pp_handle, &limit, + pp_limit_level, power_type); if (!r) size = sysfs_emit(buf, "%u\n", limit * 1000000); @@ -2942,85 +2943,31 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, return size; } -static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, + +static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, struct device_attribute *attr, char *buf) { - struct amdgpu_device *adev = dev_get_drvdata(dev); - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - enum pp_power_type power_type = to_sensor_dev_attr(attr)->index; - enum pp_power_limit_level pp_limit_level = PP_PWR_LIMIT_CURRENT; - uint32_t limit; - ssize_t size; - int r; - - if (amdgpu_in_reset(adev)) - return -EPERM; - if (adev->in_suspend && !adev->in_runpm) - return -EPERM; - - r = pm_runtime_get_sync(adev_to_drm(adev)->dev); - if (r < 0) { - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - return r; - } - - if (pp_funcs && pp_funcs->get_power_limit) - r = pp_funcs->get_power_limit(adev->powerplay.pp_handle, &limit, - pp_limit_level, power_type); - else - r = -ENODATA; + return amdgpu_hwmon_show_power_cap_generic(dev, attr, buf, PP_PWR_LIMIT_MAX); - if (!r) - size = sysfs_emit(buf, "%u\n", limit * 1000000); - else - size = sysfs_emit(buf, "\n"); +} - pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); +static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return amdgpu_hwmon_show_power_cap_generic(dev, attr, buf, PP_PWR_LIMIT_CURRENT); - return size; } static ssize_t amdgpu_hwmon_show_power_cap_default(struct device *dev, struct device_attribute *attr, char *buf) { - struct amdgpu_device *adev = dev_get_drvdata(dev); - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - enum pp_power_type power_type = to_sensor_dev_attr(attr)->index; - enum pp_power_limit_level pp_limit_level = PP_PWR_LIMIT_DEFAULT; - uint32_t limit; - ssize_t size; - int r; + return amdgpu_hwmon_show_power_cap_generic(dev, attr, buf, PP_PWR_LIMIT_DEFAULT); - if (amdgpu_in_reset(adev)) - return -EPERM; - if (adev->in_suspend && !adev->in_runpm) - return -EPERM; - - r = pm_runtime_get_sync(adev_to_drm(adev)->dev); - if (r < 0) { - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - return r; - } - - if (pp_funcs && pp_funcs->get_power_limit) - r = pp_funcs->get_power_limit(adev->powerplay.pp_handle, &limit, - pp_limit_level, power_type); - else - r = -ENODATA; - - if (!r) - size = sysfs_emit(buf, "%u\n", limit * 1000000); - else - size = sysfs_emit(buf, "\n"); - - pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - - return size; } + static ssize_t amdgpu_hwmon_show_power_label(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index cb375f1beebd..ebe672142808 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1453,10 +1453,14 @@ static int smu_hw_fini(void *handle) if (smu->is_apu) { smu_powergate_sdma(&adev->smu, true); - smu_dpm_set_vcn_enable(smu, false); - smu_dpm_set_jpeg_enable(smu, false); } + smu_dpm_set_vcn_enable(smu, false); + smu_dpm_set_jpeg_enable(smu, false); + + adev->vcn.cur_state = AMD_PG_STATE_GATE; + adev->jpeg.cur_state = AMD_PG_STATE_GATE; + if (!smu->pm_enabled) return 0; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c index 7664334d8144..18a1ffdca227 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c @@ -189,10 +189,11 @@ err0_out: static int yellow_carp_system_features_control(struct smu_context *smu, bool en) { struct smu_feature *feature = &smu->smu_feature; + struct amdgpu_device *adev = smu->adev; uint32_t feature_mask[2]; int ret = 0; - if (!en) + if (!en && !adev->in_s0ix) ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL); bitmap_zero(feature->enabled, feature->feature_num); diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index ebe9dccf2d83..0b8648396fb2 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -352,6 +352,7 @@ static struct drm_framebuffer *psb_user_framebuffer_create const struct drm_mode_fb_cmd2 *cmd) { struct drm_gem_object *obj; + struct drm_framebuffer *fb; /* * Find the GEM object and thus the gtt range object that is @@ -362,7 +363,11 @@ static struct drm_framebuffer *psb_user_framebuffer_create return ERR_PTR(-ENOENT); /* Let the core code do all the work */ - return psb_framebuffer_create(dev, cmd, obj); + fb = psb_framebuffer_create(dev, cmd, obj); + if (IS_ERR(fb)) + drm_gem_object_put(obj); + + return fb; } static int psbfb_probe(struct drm_fb_helper *fb_helper, diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index b63d374dff23..f960f5d7664e 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -125,7 +125,7 @@ config DRM_I915_GVT_KVMGT tristate "Enable KVM/VFIO support for Intel GVT-g" depends on DRM_I915_GVT depends on KVM - depends on VFIO_MDEV && VFIO_MDEV_DEVICE + depends on VFIO_MDEV default n help Choose this option if you want to enable KVMGT support for diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 390869bd6b63..be716b56e8e0 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1791,10 +1791,23 @@ static struct intel_shared_dpll *dg1_ddi_get_pll(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); enum phy phy = intel_port_to_phy(i915, encoder->port); + enum intel_dpll_id id; + u32 val; - return _cnl_ddi_get_pll(i915, DG1_DPCLKA_CFGCR0(phy), - DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy), - DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)); + val = intel_de_read(i915, DG1_DPCLKA_CFGCR0(phy)); + val &= DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy); + val >>= DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy); + id = val; + + /* + * _DG1_DPCLKA0_CFGCR0 maps between DPLL 0 and 1 with one bit for phy A + * and B while _DG1_DPCLKA1_CFGCR0 maps between DPLL 2 and 3 with one + * bit for phy C and D. + */ + if (phy >= PHY_C) + id += DPLL_ID_DG1_DPLL2; + + return intel_get_shared_dpll_by_id(i915, id); } static void icl_ddi_combo_enable_clock(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 5c9222283044..6cc03b9e4321 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2868,7 +2868,7 @@ static int intel_dp_vsc_sdp_unpack(struct drm_dp_vsc_sdp *vsc, if (size < sizeof(struct dp_sdp)) return -EINVAL; - memset(vsc, 0, size); + memset(vsc, 0, sizeof(*vsc)); if (sdp->sdp_header.HB0 != 0) return -EINVAL; diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 9ceddfbb1687..7f03df236613 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -1279,7 +1279,7 @@ bool intel_engine_is_idle(struct intel_engine_cs *engine) return true; /* Waiting to drain ELSP? */ - synchronize_hardirq(to_pci_dev(engine->i915->drm.dev)->irq); + intel_synchronize_hardirq(engine->i915); intel_engine_flush_submission(engine); /* ELSP is empty, but there are ready requests? E.g. after reset */ diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 0c423f096e2b..37d74d4ed59b 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -184,8 +184,11 @@ static int xcs_resume(struct intel_engine_cs *engine) ENGINE_TRACE(engine, "ring:{HEAD:%04x, TAIL:%04x}\n", ring->head, ring->tail); - /* Double check the ring is empty & disabled before we resume */ - synchronize_hardirq(engine->i915->drm.irq); + /* + * Double check the ring is empty & disabled before we resume. Called + * from atomic context during PCI probe, so _hardirq(). + */ + intel_synchronize_hardirq(engine->i915); if (!stop_ring(engine)) goto err; diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index 48b4d4cf805d..1ac98f8aba31 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -88,6 +88,7 @@ struct kvmgt_pgfn { struct hlist_node hnode; }; +#define KVMGT_DEBUGFS_FILENAME "kvmgt_nr_cache_entries" struct kvmgt_guest_info { struct kvm *kvm; struct intel_vgpu *vgpu; @@ -95,7 +96,6 @@ struct kvmgt_guest_info { #define NR_BKT (1 << 18) struct hlist_head ptable[NR_BKT]; #undef NR_BKT - struct dentry *debugfs_cache_entries; }; struct gvt_dma { @@ -1947,16 +1947,15 @@ static int kvmgt_guest_init(struct mdev_device *mdev) info->track_node.track_flush_slot = kvmgt_page_track_flush_slot; kvm_page_track_register_notifier(kvm, &info->track_node); - info->debugfs_cache_entries = debugfs_create_ulong( - "kvmgt_nr_cache_entries", - 0444, vgpu->debugfs, - &vdev->nr_cache_entries); + debugfs_create_ulong(KVMGT_DEBUGFS_FILENAME, 0444, vgpu->debugfs, + &vdev->nr_cache_entries); return 0; } static bool kvmgt_guest_exit(struct kvmgt_guest_info *info) { - debugfs_remove(info->debugfs_cache_entries); + debugfs_remove(debugfs_lookup(KVMGT_DEBUGFS_FILENAME, + info->vgpu->debugfs)); kvm_page_track_unregister_notifier(info->kvm, &info->track_node); kvm_put_kvm(info->kvm); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 850b499c71c8..73de45472f60 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -42,7 +42,6 @@ #include <drm/drm_aperture.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_ioctl.h> -#include <drm/drm_irq.h> #include <drm/drm_managed.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index a11bdb667241..c03943198089 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -33,7 +33,6 @@ #include <linux/sysrq.h> #include <drm/drm_drv.h> -#include <drm/drm_irq.h> #include "display/intel_de.h" #include "display/intel_display_types.h" @@ -4564,10 +4563,6 @@ void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv) bool intel_irqs_enabled(struct drm_i915_private *dev_priv) { - /* - * We only use drm_irq_uninstall() at unload and VT switch, so - * this is the only thing we need to check. - */ return dev_priv->runtime_pm.irqs_enabled; } @@ -4575,3 +4570,8 @@ void intel_synchronize_irq(struct drm_i915_private *i915) { synchronize_irq(to_pci_dev(i915->drm.dev)->irq); } + +void intel_synchronize_hardirq(struct drm_i915_private *i915) +{ + synchronize_hardirq(to_pci_dev(i915->drm.dev)->irq); +} diff --git a/drivers/gpu/drm/i915/i915_irq.h b/drivers/gpu/drm/i915/i915_irq.h index db34d5dbe402..e43b6734f21b 100644 --- a/drivers/gpu/drm/i915/i915_irq.h +++ b/drivers/gpu/drm/i915/i915_irq.h @@ -94,6 +94,7 @@ void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv); void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv); bool intel_irqs_enabled(struct drm_i915_private *dev_priv); void intel_synchronize_irq(struct drm_i915_private *i915); +void intel_synchronize_hardirq(struct drm_i915_private *i915); int intel_get_crtc_scanline(struct intel_crtc *crtc); void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e915ec034c98..94fde5ca26ae 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -10513,7 +10513,6 @@ enum skl_power_gate { #define _DG1_DPCLKA1_CFGCR0 0x16C280 #define _DG1_DPCLKA_PHY_IDX(phy) ((phy) % 2) #define _DG1_DPCLKA_PLL_IDX(pll) ((pll) % 2) -#define _DG1_PHY_DPLL_MAP(phy) ((phy) >= PHY_C ? DPLL_ID_DG1_DPLL2 : DPLL_ID_DG1_DPLL0) #define DG1_DPCLKA_CFGCR0(phy) _MMIO_PHY((phy) / 2, \ _DG1_DPCLKA_CFGCR0, \ _DG1_DPCLKA1_CFGCR0) @@ -10521,8 +10520,6 @@ enum skl_power_gate { #define DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy) (_DG1_DPCLKA_PHY_IDX(phy) * 2) #define DG1_DPCLKA_CFGCR0_DDI_CLK_SEL(pll, phy) (_DG1_DPCLKA_PLL_IDX(pll) << DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) #define DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy) (0x3 << DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) -#define DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_DPLL_MAP(clk_sel, phy) \ - (((clk_sel) >> DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) + _DG1_PHY_DPLL_MAP(phy)) /* ADLS Clocks */ #define _ADLS_DPCLKA_CFGCR0 0x164280 diff --git a/drivers/gpu/drm/lima/lima_trace.h b/drivers/gpu/drm/lima/lima_trace.h index 3a430e93d384..494b9790b1da 100644 --- a/drivers/gpu/drm/lima/lima_trace.h +++ b/drivers/gpu/drm/lima/lima_trace.h @@ -24,7 +24,7 @@ DECLARE_EVENT_CLASS(lima_task, __entry->task_id = task->base.id; __entry->context = task->base.s_fence->finished.context; __entry->seqno = task->base.s_fence->finished.seqno; - __assign_str(pipe, task->base.sched->name) + __assign_str(pipe, task->base.sched->name); ), TP_printk("task=%llu, context=%u seqno=%u pipe=%s", diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 406681317419..573154268d43 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1325,6 +1325,7 @@ radeon_user_framebuffer_create(struct drm_device *dev, /* Handle is imported dma-buf, so cannot be migrated to VRAM for scanout */ if (obj->import_attach) { DRM_DEBUG_KMS("Cannot create framebuffer from imported dma_buf\n"); + drm_gem_object_put(obj); return ERR_PTR(-EINVAL); } diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 8cd135fa6dcd..5c23b77cb81a 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -374,13 +374,13 @@ radeon_pci_shutdown(struct pci_dev *pdev) if (radeon_device_is_virtual()) radeon_pci_remove(pdev); -#ifdef CONFIG_PPC64 +#if defined(CONFIG_PPC64) || defined(CONFIG_MACH_LOONGSON64) /* * Some adapters need to be suspended before a * shutdown occurs in order to prevent an error - * during kexec. - * Make this power specific becauase it breaks - * some non-power boards. + * during kexec, shutdown or reboot. + * Make this power and Loongson specific because + * it breaks some other boards. */ radeon_suspend_kms(pci_get_drvdata(pdev), true, true, false); #endif diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index bfaaa3c969a3..56ede9d63b12 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -49,23 +49,23 @@ static void radeon_bo_clear_surface_reg(struct radeon_bo *bo); * function are calling it. */ -static void radeon_update_memory_usage(struct radeon_bo *bo, - unsigned mem_type, int sign) +static void radeon_update_memory_usage(struct ttm_buffer_object *bo, + unsigned int mem_type, int sign) { - struct radeon_device *rdev = bo->rdev; + struct radeon_device *rdev = radeon_get_rdev(bo->bdev); switch (mem_type) { case TTM_PL_TT: if (sign > 0) - atomic64_add(bo->tbo.base.size, &rdev->gtt_usage); + atomic64_add(bo->base.size, &rdev->gtt_usage); else - atomic64_sub(bo->tbo.base.size, &rdev->gtt_usage); + atomic64_sub(bo->base.size, &rdev->gtt_usage); break; case TTM_PL_VRAM: if (sign > 0) - atomic64_add(bo->tbo.base.size, &rdev->vram_usage); + atomic64_add(bo->base.size, &rdev->vram_usage); else - atomic64_sub(bo->tbo.base.size, &rdev->vram_usage); + atomic64_sub(bo->base.size, &rdev->vram_usage); break; } } @@ -76,8 +76,6 @@ static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo) bo = container_of(tbo, struct radeon_bo, tbo); - radeon_update_memory_usage(bo, bo->tbo.resource->mem_type, -1); - mutex_lock(&bo->rdev->gem.mutex); list_del_init(&bo->list); mutex_unlock(&bo->rdev->gem.mutex); @@ -727,24 +725,21 @@ int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, } void radeon_bo_move_notify(struct ttm_buffer_object *bo, - bool evict, + unsigned int old_type, struct ttm_resource *new_mem) { struct radeon_bo *rbo; + radeon_update_memory_usage(bo, old_type, -1); + if (new_mem) + radeon_update_memory_usage(bo, new_mem->mem_type, 1); + if (!radeon_ttm_bo_is_radeon_bo(bo)) return; rbo = container_of(bo, struct radeon_bo, tbo); radeon_bo_check_tiling(rbo, 0, 1); radeon_vm_bo_invalidate(rbo->rdev, rbo); - - /* update statistics */ - if (!new_mem) - return; - - radeon_update_memory_usage(rbo, bo->resource->mem_type, -1); - radeon_update_memory_usage(rbo, new_mem->mem_type, 1); } vm_fault_t radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo) diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index 1739c6a142cd..1afc7992ef91 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h @@ -161,7 +161,7 @@ extern void radeon_bo_get_tiling_flags(struct radeon_bo *bo, extern int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, bool force_drop); extern void radeon_bo_move_notify(struct ttm_buffer_object *bo, - bool evict, + unsigned int old_type, struct ttm_resource *new_mem); extern vm_fault_t radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo); extern int radeon_bo_get_surface_reg(struct radeon_bo *bo); diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index ad2a5a791bba..a06d4cc2fb1c 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -199,7 +199,7 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, bool evict, struct ttm_resource *old_mem = bo->resource; struct radeon_device *rdev; struct radeon_bo *rbo; - int r; + int r, old_type; if (new_mem->mem_type == TTM_PL_TT) { r = radeon_ttm_tt_bind(bo->bdev, bo->ttm, new_mem); @@ -216,6 +216,9 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, bool evict, if (WARN_ON_ONCE(rbo->tbo.pin_count > 0)) return -EINVAL; + /* Save old type for statistics update */ + old_type = old_mem->mem_type; + rdev = radeon_get_rdev(bo->bdev); if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { ttm_bo_move_null(bo, new_mem); @@ -261,7 +264,7 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, bool evict, out: /* update statistics */ atomic64_add(bo->base.size, &rdev->num_bytes_moved); - radeon_bo_move_notify(bo, evict, new_mem); + radeon_bo_move_notify(bo, old_type, new_mem); return 0; } @@ -682,7 +685,11 @@ bool radeon_ttm_tt_is_readonly(struct radeon_device *rdev, static void radeon_bo_delete_mem_notify(struct ttm_buffer_object *bo) { - radeon_bo_move_notify(bo, false, NULL); + unsigned int old_type = TTM_PL_SYSTEM; + + if (bo->resource) + old_type = bo->resource->mem_type; + radeon_bo_move_notify(bo, old_type, NULL); } static struct ttm_device_funcs radeon_bo_driver = { diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c index 967532afb1c0..0d68a78be980 100644 --- a/drivers/hwmon/occ/common.c +++ b/drivers/hwmon/occ/common.c @@ -1151,6 +1151,8 @@ int occ_setup(struct occ *occ, const char *name) { int rc; + /* start with 1 to avoid false match with zero-initialized SRAM buffer */ + occ->seq_no = 1; mutex_init(&occ->lock); occ->groups[0] = &occ->group; @@ -1160,8 +1162,9 @@ int occ_setup(struct occ *occ, const char *name) dev_info(occ->bus_dev, "host is not ready\n"); return rc; } else if (rc < 0) { - dev_err(occ->bus_dev, "failed to get OCC poll response: %d\n", - rc); + dev_err(occ->bus_dev, + "failed to get OCC poll response=%02x: %d\n", + occ->resp.return_status, rc); return rc; } diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig index 53e13476e831..3874d15b0e9b 100644 --- a/drivers/hwspinlock/Kconfig +++ b/drivers/hwspinlock/Kconfig @@ -44,6 +44,15 @@ config HWSPINLOCK_STM32 If unsure, say N. +config HWSPINLOCK_SUN6I + tristate "SUN6I Hardware Spinlock device" + depends on ARCH_SUNXI || COMPILE_TEST + help + Say y here to support the SUN6I Hardware Spinlock device which can be + found in most of the sun6i compatible Allwinner SoCs. + + If unsure, say N. + config HSEM_U8500 tristate "STE Hardware Semaphore functionality" depends on ARCH_U8500 || COMPILE_TEST diff --git a/drivers/hwspinlock/Makefile b/drivers/hwspinlock/Makefile index 1f8dd6f5814f..a0f16c9aaa82 100644 --- a/drivers/hwspinlock/Makefile +++ b/drivers/hwspinlock/Makefile @@ -8,4 +8,5 @@ obj-$(CONFIG_HWSPINLOCK_OMAP) += omap_hwspinlock.o obj-$(CONFIG_HWSPINLOCK_QCOM) += qcom_hwspinlock.o obj-$(CONFIG_HWSPINLOCK_SPRD) += sprd_hwspinlock.o obj-$(CONFIG_HWSPINLOCK_STM32) += stm32_hwspinlock.o +obj-$(CONFIG_HWSPINLOCK_SUN6I) += sun6i_hwspinlock.o obj-$(CONFIG_HSEM_U8500) += u8500_hsem.o diff --git a/drivers/hwspinlock/sun6i_hwspinlock.c b/drivers/hwspinlock/sun6i_hwspinlock.c new file mode 100644 index 000000000000..c2d314588046 --- /dev/null +++ b/drivers/hwspinlock/sun6i_hwspinlock.c @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * sun6i_hwspinlock.c - hardware spinlock driver for sun6i compatible Allwinner SoCs + * Copyright (C) 2020 Wilken Gottwalt <wilken.gottwalt@posteo.net> + */ + +#include <linux/clk.h> +#include <linux/debugfs.h> +#include <linux/errno.h> +#include <linux/hwspinlock.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/reset.h> +#include <linux/slab.h> +#include <linux/spinlock.h> +#include <linux/types.h> + +#include "hwspinlock_internal.h" + +#define DRIVER_NAME "sun6i_hwspinlock" + +#define SPINLOCK_BASE_ID 0 /* there is only one hwspinlock device per SoC */ +#define SPINLOCK_SYSSTATUS_REG 0x0000 +#define SPINLOCK_LOCK_REGN 0x0100 +#define SPINLOCK_NOTTAKEN 0 + +struct sun6i_hwspinlock_data { + struct hwspinlock_device *bank; + struct reset_control *reset; + struct clk *ahb_clk; + struct dentry *debugfs; + int nlocks; +}; + +#ifdef CONFIG_DEBUG_FS + +static int hwlocks_supported_show(struct seq_file *seqf, void *unused) +{ + struct sun6i_hwspinlock_data *priv = seqf->private; + + seq_printf(seqf, "%d\n", priv->nlocks); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(hwlocks_supported); + +static void sun6i_hwspinlock_debugfs_init(struct sun6i_hwspinlock_data *priv) +{ + priv->debugfs = debugfs_create_dir(DRIVER_NAME, NULL); + debugfs_create_file("supported", 0444, priv->debugfs, priv, &hwlocks_supported_fops); +} + +#else + +static void sun6i_hwspinlock_debugfs_init(struct sun6i_hwspinlock_data *priv) +{ +} + +#endif + +static int sun6i_hwspinlock_trylock(struct hwspinlock *lock) +{ + void __iomem *lock_addr = lock->priv; + + return (readl(lock_addr) == SPINLOCK_NOTTAKEN); +} + +static void sun6i_hwspinlock_unlock(struct hwspinlock *lock) +{ + void __iomem *lock_addr = lock->priv; + + writel(SPINLOCK_NOTTAKEN, lock_addr); +} + +static const struct hwspinlock_ops sun6i_hwspinlock_ops = { + .trylock = sun6i_hwspinlock_trylock, + .unlock = sun6i_hwspinlock_unlock, +}; + +static void sun6i_hwspinlock_disable(void *data) +{ + struct sun6i_hwspinlock_data *priv = data; + + debugfs_remove_recursive(priv->debugfs); + clk_disable_unprepare(priv->ahb_clk); + reset_control_assert(priv->reset); +} + +static int sun6i_hwspinlock_probe(struct platform_device *pdev) +{ + struct sun6i_hwspinlock_data *priv; + struct hwspinlock *hwlock; + void __iomem *io_base; + u32 num_banks; + int err, i; + + io_base = devm_platform_ioremap_resource(pdev, SPINLOCK_BASE_ID); + if (IS_ERR(io_base)) + return PTR_ERR(io_base); + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->ahb_clk = devm_clk_get(&pdev->dev, "ahb"); + if (IS_ERR(priv->ahb_clk)) { + err = PTR_ERR(priv->ahb_clk); + dev_err(&pdev->dev, "unable to get AHB clock (%d)\n", err); + return err; + } + + priv->reset = devm_reset_control_get(&pdev->dev, "ahb"); + if (IS_ERR(priv->reset)) + return dev_err_probe(&pdev->dev, PTR_ERR(priv->reset), + "unable to get reset control\n"); + + err = reset_control_deassert(priv->reset); + if (err) { + dev_err(&pdev->dev, "deassert reset control failure (%d)\n", err); + return err; + } + + err = clk_prepare_enable(priv->ahb_clk); + if (err) { + dev_err(&pdev->dev, "unable to prepare AHB clk (%d)\n", err); + goto clk_fail; + } + + /* + * bit 28 and 29 represents the hwspinlock setup + * + * every datasheet (A64, A80, A83T, H3, H5, H6 ...) says the default value is 0x1 and 0x1 + * to 0x4 represent 32, 64, 128 and 256 locks + * but later datasheets (H5, H6) say 00, 01, 10, 11 represent 32, 64, 128 and 256 locks, + * but that would mean H5 and H6 have 64 locks, while their datasheets talk about 32 locks + * all the time, not a single mentioning of 64 locks + * the 0x4 value is also not representable by 2 bits alone, so some datasheets are not + * correct + * one thing have all in common, default value of the sysstatus register is 0x10000000, + * which results in bit 28 being set + * this is the reason 0x1 is considered being 32 locks and bit 30 is taken into account + * verified on H2+ (datasheet 0x1 = 32 locks) and H5 (datasheet 01 = 64 locks) + */ + num_banks = readl(io_base + SPINLOCK_SYSSTATUS_REG) >> 28; + switch (num_banks) { + case 1 ... 4: + priv->nlocks = 1 << (4 + num_banks); + break; + default: + err = -EINVAL; + dev_err(&pdev->dev, "unsupported hwspinlock setup (%d)\n", num_banks); + goto bank_fail; + } + + priv->bank = devm_kzalloc(&pdev->dev, struct_size(priv->bank, lock, priv->nlocks), + GFP_KERNEL); + if (!priv->bank) { + err = -ENOMEM; + goto bank_fail; + } + + for (i = 0; i < priv->nlocks; ++i) { + hwlock = &priv->bank->lock[i]; + hwlock->priv = io_base + SPINLOCK_LOCK_REGN + sizeof(u32) * i; + } + + /* failure of debugfs is considered non-fatal */ + sun6i_hwspinlock_debugfs_init(priv); + if (IS_ERR(priv->debugfs)) + priv->debugfs = NULL; + + err = devm_add_action_or_reset(&pdev->dev, sun6i_hwspinlock_disable, priv); + if (err) { + dev_err(&pdev->dev, "failed to add hwspinlock disable action\n"); + goto bank_fail; + } + + platform_set_drvdata(pdev, priv); + + return devm_hwspin_lock_register(&pdev->dev, priv->bank, &sun6i_hwspinlock_ops, + SPINLOCK_BASE_ID, priv->nlocks); + +bank_fail: + clk_disable_unprepare(priv->ahb_clk); +clk_fail: + reset_control_assert(priv->reset); + + return err; +} + +static const struct of_device_id sun6i_hwspinlock_ids[] = { + { .compatible = "allwinner,sun6i-a31-hwspinlock", }, + {}, +}; +MODULE_DEVICE_TABLE(of, sun6i_hwspinlock_ids); + +static struct platform_driver sun6i_hwspinlock_driver = { + .probe = sun6i_hwspinlock_probe, + .driver = { + .name = DRIVER_NAME, + .of_match_table = sun6i_hwspinlock_ids, + }, +}; +module_platform_driver(sun6i_hwspinlock_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SUN6I hardware spinlock driver"); +MODULE_AUTHOR("Wilken Gottwalt <wilken.gottwalt@posteo.net>"); diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 6c68d34d956e..1002605db8ba 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -608,7 +608,7 @@ static struct coresight_device * coresight_find_enabled_sink(struct coresight_device *csdev) { int i; - struct coresight_device *sink; + struct coresight_device *sink = NULL; if ((csdev->type == CORESIGHT_DEV_TYPE_SINK || csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) && @@ -886,7 +886,6 @@ void coresight_release_path(struct list_head *path) } kfree(path); - path = NULL; } /* return true if the device is a suitable type for a default sink */ @@ -1392,7 +1391,7 @@ static int coresight_fixup_device_conns(struct coresight_device *csdev) } } - return 0; + return ret; } static int coresight_remove_match(struct device *dev, void *data) @@ -1730,9 +1729,9 @@ char *coresight_alloc_device_name(struct coresight_dev_list *dict, if (idx < 0) { /* Make space for the new entry */ idx = dict->nr_idx; - list = krealloc(dict->fwnode_list, - (idx + 1) * sizeof(*dict->fwnode_list), - GFP_KERNEL); + list = krealloc_array(dict->fwnode_list, + idx + 1, sizeof(*dict->fwnode_list), + GFP_KERNEL); if (ZERO_OR_NULL_PTR(list)) { idx = -ENOMEM; goto done; diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c index db881993c211..da27cd4a3c38 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c @@ -568,11 +568,6 @@ static int etm4_parse_event_config(struct etmv4_drvdata *drvdata, struct etmv4_config *config = &drvdata->config; struct perf_event_attr *attr = &event->attr; - if (!attr) { - ret = -EINVAL; - goto out; - } - /* Clear configuration from previous run */ memset(config, 0, sizeof(struct etmv4_config)); diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 45b85edfc690..cd0fb7bfba68 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -530,7 +530,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, buf_ptr = buf->data_pages[cur] + offset; *buf_ptr = readl_relaxed(drvdata->base + TMC_RRD); - if (lost && *barrier) { + if (lost && i < CORESIGHT_BARRIER_PKT_SIZE) { *buf_ptr = *barrier; barrier++; } diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c index 24d0c974bfd5..66eed2dff818 100644 --- a/drivers/hwtracing/intel_th/core.c +++ b/drivers/hwtracing/intel_th/core.c @@ -100,16 +100,18 @@ static int intel_th_remove(struct device *dev) struct intel_th_driver *thdrv = to_intel_th_driver(dev->driver); struct intel_th_device *thdev = to_intel_th_device(dev); struct intel_th_device *hub = to_intel_th_hub(thdev); - int err; if (thdev->type == INTEL_TH_SWITCH) { struct intel_th *th = to_intel_th(hub); int i, lowest; - /* disconnect outputs */ - err = device_for_each_child(dev, thdev, intel_th_child_remove); - if (err) - return err; + /* + * disconnect outputs + * + * intel_th_child_remove returns 0 unconditionally, so there is + * no need to check the return value of device_for_each_child. + */ + device_for_each_child(dev, thdev, intel_th_child_remove); /* * Remove outputs, that is, hub's children: they are created @@ -215,6 +217,22 @@ static ssize_t port_show(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR_RO(port); +static void intel_th_trace_prepare(struct intel_th_device *thdev) +{ + struct intel_th_device *hub = to_intel_th_hub(thdev); + struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver); + + if (hub->type != INTEL_TH_SWITCH) + return; + + if (thdev->type != INTEL_TH_OUTPUT) + return; + + pm_runtime_get_sync(&thdev->dev); + hubdrv->prepare(hub, &thdev->output); + pm_runtime_put(&thdev->dev); +} + static int intel_th_output_activate(struct intel_th_device *thdev) { struct intel_th_driver *thdrv = @@ -235,6 +253,7 @@ static int intel_th_output_activate(struct intel_th_device *thdev) if (ret) goto fail_put; + intel_th_trace_prepare(thdev); if (thdrv->activate) ret = thdrv->activate(thdev); else diff --git a/drivers/hwtracing/intel_th/gth.c b/drivers/hwtracing/intel_th/gth.c index 28509b02a0b5..b3308934a687 100644 --- a/drivers/hwtracing/intel_th/gth.c +++ b/drivers/hwtracing/intel_th/gth.c @@ -564,6 +564,21 @@ static void gth_tscu_resync(struct gth_device *gth) iowrite32(reg, gth->base + REG_TSCU_TSUCTRL); } +static void intel_th_gth_prepare(struct intel_th_device *thdev, + struct intel_th_output *output) +{ + struct gth_device *gth = dev_get_drvdata(&thdev->dev); + int count; + + /* + * Wait until the output port is in reset before we start + * programming it. + */ + for (count = GTH_PLE_WAITLOOP_DEPTH; + count && !(gth_output_get(gth, output->port) & BIT(5)); count--) + cpu_relax(); +} + /** * intel_th_gth_enable() - enable tracing to an output device * @thdev: GTH device @@ -815,6 +830,7 @@ static struct intel_th_driver intel_th_gth_driver = { .assign = intel_th_gth_assign, .unassign = intel_th_gth_unassign, .set_output = intel_th_gth_set_output, + .prepare = intel_th_gth_prepare, .enable = intel_th_gth_enable, .trig_switch = intel_th_gth_switch, .disable = intel_th_gth_disable, diff --git a/drivers/hwtracing/intel_th/intel_th.h b/drivers/hwtracing/intel_th/intel_th.h index 89c67e0e1d34..0ffb42990175 100644 --- a/drivers/hwtracing/intel_th/intel_th.h +++ b/drivers/hwtracing/intel_th/intel_th.h @@ -143,6 +143,7 @@ intel_th_output_assigned(struct intel_th_device *thdev) * @remove: remove method * @assign: match a given output type device against available outputs * @unassign: deassociate an output type device from an output port + * @prepare: prepare output port for tracing * @enable: enable tracing for a given output device * @disable: disable tracing for a given output device * @irq: interrupt callback @@ -164,6 +165,8 @@ struct intel_th_driver { struct intel_th_device *othdev); void (*unassign)(struct intel_th_device *thdev, struct intel_th_device *othdev); + void (*prepare)(struct intel_th_device *thdev, + struct intel_th_output *output); void (*enable)(struct intel_th_device *thdev, struct intel_th_output *output); void (*trig_switch)(struct intel_th_device *thdev, diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c index 2edc4666633d..432ade0842f6 100644 --- a/drivers/hwtracing/intel_th/msu.c +++ b/drivers/hwtracing/intel_th/msu.c @@ -1024,33 +1024,49 @@ err_nomem: } #ifdef CONFIG_X86 -static void msc_buffer_set_uc(struct msc_window *win, unsigned int nr_segs) +static void msc_buffer_set_uc(struct msc *msc) { struct scatterlist *sg_ptr; + struct msc_window *win; int i; - for_each_sg(win->sgt->sgl, sg_ptr, nr_segs, i) { - /* Set the page as uncached */ - set_memory_uc((unsigned long)sg_virt(sg_ptr), - PFN_DOWN(sg_ptr->length)); + if (msc->mode == MSC_MODE_SINGLE) { + set_memory_uc((unsigned long)msc->base, msc->nr_pages); + return; + } + + list_for_each_entry(win, &msc->win_list, entry) { + for_each_sg(win->sgt->sgl, sg_ptr, win->nr_segs, i) { + /* Set the page as uncached */ + set_memory_uc((unsigned long)sg_virt(sg_ptr), + PFN_DOWN(sg_ptr->length)); + } } } -static void msc_buffer_set_wb(struct msc_window *win) +static void msc_buffer_set_wb(struct msc *msc) { struct scatterlist *sg_ptr; + struct msc_window *win; int i; - for_each_sg(win->sgt->sgl, sg_ptr, win->nr_segs, i) { - /* Reset the page to write-back */ - set_memory_wb((unsigned long)sg_virt(sg_ptr), - PFN_DOWN(sg_ptr->length)); + if (msc->mode == MSC_MODE_SINGLE) { + set_memory_wb((unsigned long)msc->base, msc->nr_pages); + return; + } + + list_for_each_entry(win, &msc->win_list, entry) { + for_each_sg(win->sgt->sgl, sg_ptr, win->nr_segs, i) { + /* Reset the page to write-back */ + set_memory_wb((unsigned long)sg_virt(sg_ptr), + PFN_DOWN(sg_ptr->length)); + } } } #else /* !X86 */ static inline void -msc_buffer_set_uc(struct msc_window *win, unsigned int nr_segs) {} -static inline void msc_buffer_set_wb(struct msc_window *win) {} +msc_buffer_set_uc(struct msc *msc) {} +static inline void msc_buffer_set_wb(struct msc *msc) {} #endif /* CONFIG_X86 */ /** @@ -1097,8 +1113,6 @@ static int msc_buffer_win_alloc(struct msc *msc, unsigned int nr_blocks) if (ret <= 0) goto err_nomem; - msc_buffer_set_uc(win, ret); - win->nr_segs = ret; win->nr_blocks = nr_blocks; @@ -1152,8 +1166,6 @@ static void msc_buffer_win_free(struct msc *msc, struct msc_window *win) msc->base_addr = 0; } - msc_buffer_set_wb(win); - if (msc->mbuf && msc->mbuf->free_window) msc->mbuf->free_window(msc->mbuf_priv, win->sgt); else @@ -1260,6 +1272,8 @@ static int msc_buffer_multi_alloc(struct msc *msc, unsigned long *nr_pages, */ static void msc_buffer_free(struct msc *msc) { + msc_buffer_set_wb(msc); + if (msc->mode == MSC_MODE_SINGLE) msc_buffer_contig_free(msc); else if (msc->mode == MSC_MODE_MULTI) @@ -1303,6 +1317,8 @@ static int msc_buffer_alloc(struct msc *msc, unsigned long *nr_pages, } if (!ret) { + msc_buffer_set_uc(msc); + /* allocation should be visible before the counter goes to 0 */ smp_mb__before_atomic(); diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index fb93152845f4..ee83c4581bce 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -508,6 +508,11 @@ static void ali1535_remove(struct pci_dev *dev) { i2c_del_adapter(&ali1535_adapter); release_region(ali1535_smba, ALI1535_SMB_IOSIZE); + + /* + * do not call pci_disable_device(dev) since it can cause hard hangs on + * some systems during power-off + */ } static struct pci_driver ali1535_driver = { diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c index 724bf30600d6..67e8b97c0c95 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -727,10 +727,14 @@ static void __aspeed_i2c_reg_slave(struct aspeed_i2c_bus *bus, u16 slave_addr) { u32 addr_reg_val, func_ctrl_reg_val; - /* Set slave addr. */ - addr_reg_val = readl(bus->base + ASPEED_I2C_DEV_ADDR_REG); - addr_reg_val &= ~ASPEED_I2CD_DEV_ADDR_MASK; - addr_reg_val |= slave_addr & ASPEED_I2CD_DEV_ADDR_MASK; + /* + * Set slave addr. Reserved bits can all safely be written with zeros + * on all of ast2[456]00, so zero everything else to ensure we only + * enable a single slave address (ast2500 has two, ast2600 has three, + * the enable bits for which are also in this register) so that we don't + * end up with additional phantom devices responding on the bus. + */ + addr_reg_val = slave_addr & ASPEED_I2CD_DEV_ADDR_MASK; writel(addr_reg_val, bus->base + ASPEED_I2C_DEV_ADDR_REG); /* Turn on slave mode. */ diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index 66aafa7d1123..20aa3398e642 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -578,6 +578,11 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id) { unsigned int ctrl_reg; unsigned int isr_status; + unsigned long flags; + bool hold_clear = false; + bool irq_save = false; + + u32 addr; id->p_recv_buf = id->p_msg->buf; id->recv_count = id->p_msg->len; @@ -618,14 +623,43 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id) cdns_i2c_writereg(id->recv_count, CDNS_I2C_XFER_SIZE_OFFSET); } - /* Set the slave address in address register - triggers operation */ - cdns_i2c_writereg(id->p_msg->addr & CDNS_I2C_ADDR_MASK, - CDNS_I2C_ADDR_OFFSET); - /* Clear the bus hold flag if bytes to receive is less than FIFO size */ + /* Determine hold_clear based on number of bytes to receive and hold flag */ if (!id->bus_hold_flag && - ((id->p_msg->flags & I2C_M_RECV_LEN) != I2C_M_RECV_LEN) && - (id->recv_count <= CDNS_I2C_FIFO_DEPTH)) - cdns_i2c_clear_bus_hold(id); + ((id->p_msg->flags & I2C_M_RECV_LEN) != I2C_M_RECV_LEN) && + (id->recv_count <= CDNS_I2C_FIFO_DEPTH)) { + if (cdns_i2c_readreg(CDNS_I2C_CR_OFFSET) & CDNS_I2C_CR_HOLD) { + hold_clear = true; + if (id->quirks & CDNS_I2C_BROKEN_HOLD_BIT) + irq_save = true; + } + } + + addr = id->p_msg->addr; + addr &= CDNS_I2C_ADDR_MASK; + + if (hold_clear) { + ctrl_reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET) & ~CDNS_I2C_CR_HOLD; + /* + * In case of Xilinx Zynq SOC, clear the HOLD bit before transfer size + * register reaches '0'. This is an IP bug which causes transfer size + * register overflow to 0xFF. To satisfy this timing requirement, + * disable the interrupts on current processor core between register + * writes to slave address register and control register. + */ + if (irq_save) + local_irq_save(flags); + + cdns_i2c_writereg(addr, CDNS_I2C_ADDR_OFFSET); + cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET); + /* Read it back to avoid bufferring and make sure write happens */ + cdns_i2c_readreg(CDNS_I2C_CR_OFFSET); + + if (irq_save) + local_irq_restore(flags); + } else { + cdns_i2c_writereg(addr, CDNS_I2C_ADDR_OFFSET); + } + cdns_i2c_writereg(CDNS_I2C_ENABLED_INTR_MASK, CDNS_I2C_IER_OFFSET); } @@ -1217,11 +1251,10 @@ static int cdns_i2c_probe(struct platform_device *pdev) "Cadence I2C at %08lx", (unsigned long)r_mem->start); id->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(id->clk)) { - if (PTR_ERR(id->clk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "input clock not found.\n"); - return PTR_ERR(id->clk); - } + if (IS_ERR(id->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(id->clk), + "input clock not found.\n"); + ret = clk_prepare_enable(id->clk); if (ret) dev_err(&pdev->dev, "Unable to enable clock.\n"); diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c index 08f491ea21ac..1cf68f85b2e1 100644 --- a/drivers/i2c/busses/i2c-cht-wc.c +++ b/drivers/i2c/busses/i2c-cht-wc.c @@ -354,8 +354,7 @@ static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev) return ret; /* Alloc and register client IRQ */ - adap->irq_domain = irq_domain_add_linear(pdev->dev.of_node, 1, - &irq_domain_simple_ops, NULL); + adap->irq_domain = irq_domain_add_linear(NULL, 1, &irq_domain_simple_ops, NULL); if (!adap->irq_domain) return -ENOMEM; diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 232a7679b69b..e9d07323c604 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -768,10 +768,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) if (irq <= 0) { if (!irq) irq = -ENXIO; - if (irq != -EPROBE_DEFER) - dev_err(&pdev->dev, - "can't get irq resource ret=%d\n", irq); - return irq; + return dev_err_probe(&pdev->dev, irq, "can't get irq resource\n"); } dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_i2c_dev), diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 04a1e38f2a6f..aa3f60e69230 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -88,6 +88,8 @@ * See the file Documentation/i2c/busses/i2c-i801.rst for details. */ +#define DRV_NAME "i801_smbus" + #include <linux/interrupt.h> #include <linux/module.h> #include <linux/pci.h> @@ -103,7 +105,7 @@ #include <linux/dmi.h> #include <linux/slab.h> #include <linux/string.h> -#include <linux/wait.h> +#include <linux/completion.h> #include <linux/err.h> #include <linux/platform_device.h> #include <linux/platform_data/itco_wdt.h> @@ -131,8 +133,6 @@ /* PCI Address Constants */ #define SMBBAR 4 -#define SMBPCICTL 0x004 -#define SMBPCISTS 0x006 #define SMBHSTCFG 0x040 #define TCOBASE 0x050 #define TCOCTL 0x054 @@ -141,12 +141,6 @@ #define SBREG_SMBCTRL 0xc6000c #define SBREG_SMBCTRL_DNV 0xcf000c -/* Host status bits for SMBPCISTS */ -#define SMBPCISTS_INTS BIT(3) - -/* Control bits for SMBPCICTL */ -#define SMBPCICTL_INTDIS BIT(10) - /* Host configuration bits for SMBHSTCFG */ #define SMBHSTCFG_HST_EN BIT(0) #define SMBHSTCFG_SMB_SMI_EN BIT(1) @@ -164,9 +158,6 @@ #define SMBAUXCTL_CRC BIT(0) #define SMBAUXCTL_E32B BIT(1) -/* Other settings */ -#define MAX_RETRIES 400 - /* I801 command constants */ #define I801_QUICK 0x00 #define I801_BYTE 0x04 @@ -270,7 +261,7 @@ struct i801_priv { unsigned int features; /* isr processing */ - wait_queue_head_t waitq; + struct completion done; u8 status; /* Command state used by isr for byte-by-byte block transactions */ @@ -453,67 +444,53 @@ static int i801_check_post(struct i801_priv *priv, int status) /* Wait for BUSY being cleared and either INTR or an error flag being set */ static int i801_wait_intr(struct i801_priv *priv) { - int timeout = 0; - int status; + unsigned long timeout = jiffies + priv->adapter.timeout; + int status, busy; - /* We will always wait for a fraction of a second! */ do { usleep_range(250, 500); status = inb_p(SMBHSTSTS(priv)); - } while (((status & SMBHSTSTS_HOST_BUSY) || - !(status & (STATUS_ERROR_FLAGS | SMBHSTSTS_INTR))) && - (timeout++ < MAX_RETRIES)); + busy = status & SMBHSTSTS_HOST_BUSY; + status &= STATUS_ERROR_FLAGS | SMBHSTSTS_INTR; + if (!busy && status) + return status; + } while (time_is_after_eq_jiffies(timeout)); - if (timeout > MAX_RETRIES) { - dev_dbg(&priv->pci_dev->dev, "INTR Timeout!\n"); - return -ETIMEDOUT; - } - return status & (STATUS_ERROR_FLAGS | SMBHSTSTS_INTR); + return -ETIMEDOUT; } /* Wait for either BYTE_DONE or an error flag being set */ static int i801_wait_byte_done(struct i801_priv *priv) { - int timeout = 0; + unsigned long timeout = jiffies + priv->adapter.timeout; int status; - /* We will always wait for a fraction of a second! */ do { usleep_range(250, 500); status = inb_p(SMBHSTSTS(priv)); - } while (!(status & (STATUS_ERROR_FLAGS | SMBHSTSTS_BYTE_DONE)) && - (timeout++ < MAX_RETRIES)); + if (status & (STATUS_ERROR_FLAGS | SMBHSTSTS_BYTE_DONE)) + return status & STATUS_ERROR_FLAGS; + } while (time_is_after_eq_jiffies(timeout)); - if (timeout > MAX_RETRIES) { - dev_dbg(&priv->pci_dev->dev, "BYTE_DONE Timeout!\n"); - return -ETIMEDOUT; - } - return status & STATUS_ERROR_FLAGS; + return -ETIMEDOUT; } static int i801_transaction(struct i801_priv *priv, int xact) { int status; - int result; + unsigned long result; const struct i2c_adapter *adap = &priv->adapter; - result = i801_check_pre(priv); - if (result < 0) - return result; + status = i801_check_pre(priv); + if (status < 0) + return status; if (priv->features & FEATURE_IRQ) { + reinit_completion(&priv->done); outb_p(xact | SMBHSTCNT_INTREN | SMBHSTCNT_START, SMBHSTCNT(priv)); - result = wait_event_timeout(priv->waitq, - (status = priv->status), - adap->timeout); - if (!result) { - status = -ETIMEDOUT; - dev_warn(&priv->pci_dev->dev, - "Timeout waiting for interrupt!\n"); - } - priv->status = 0; - return i801_check_post(priv, status); + result = wait_for_completion_timeout(&priv->done, adap->timeout); + return i801_check_post(priv, result ? priv->status : -ETIMEDOUT); } /* the current contents of SMBHSTCNT can be overwritten, since PEC, @@ -638,7 +615,7 @@ static irqreturn_t i801_host_notify_isr(struct i801_priv *priv) * DEV_ERR - Invalid command, NAK or communication timeout * BUS_ERR - SMI# transaction collision * FAILED - transaction was canceled due to a KILL request - * When any of these occur, update ->status and wake up the waitq. + * When any of these occur, update ->status and signal completion. * ->status must be cleared before kicking off the next transaction. * * 2) For byte-by-byte (I2C read/write) transactions, one BYTE_DONE interrupt @@ -653,8 +630,8 @@ static irqreturn_t i801_isr(int irq, void *dev_id) u8 status; /* Confirm this is our interrupt */ - pci_read_config_word(priv->pci_dev, SMBPCISTS, &pcists); - if (!(pcists & SMBPCISTS_INTS)) + pci_read_config_word(priv->pci_dev, PCI_STATUS, &pcists); + if (!(pcists & PCI_STATUS_INTERRUPT)) return IRQ_NONE; if (priv->features & FEATURE_HOST_NOTIFY) { @@ -675,7 +652,7 @@ static irqreturn_t i801_isr(int irq, void *dev_id) if (status) { outb_p(status, SMBHSTSTS(priv)); priv->status = status; - wake_up(&priv->waitq); + complete(&priv->done); } return IRQ_HANDLED; @@ -694,15 +671,15 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, int i, len; int smbcmd; int status; - int result; + unsigned long result; const struct i2c_adapter *adap = &priv->adapter; if (command == I2C_SMBUS_BLOCK_PROC_CALL) return -EOPNOTSUPP; - result = i801_check_pre(priv); - if (result < 0) - return result; + status = i801_check_pre(priv); + if (status < 0) + return status; len = data->block[0]; @@ -726,17 +703,10 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, priv->count = 0; priv->data = &data->block[1]; + reinit_completion(&priv->done); outb_p(priv->cmd | SMBHSTCNT_START, SMBHSTCNT(priv)); - result = wait_event_timeout(priv->waitq, - (status = priv->status), - adap->timeout); - if (!result) { - status = -ETIMEDOUT; - dev_warn(&priv->pci_dev->dev, - "Timeout waiting for interrupt!\n"); - } - priv->status = 0; - return i801_check_post(priv, status); + result = wait_for_completion_timeout(&priv->done, adap->timeout); + return i801_check_post(priv, result ? priv->status : -ETIMEDOUT); } for (i = 1; i <= len; i++) { @@ -1322,11 +1292,11 @@ static void i801_probe_optional_slaves(struct i801_priv *priv) return; if (apanel_addr) { - struct i2c_board_info info; + struct i2c_board_info info = { + .addr = apanel_addr, + .type = "fujitsu_apanel", + }; - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = apanel_addr; - strlcpy(info.type, "fujitsu_apanel", I2C_NAME_SIZE); i2c_new_client_device(&priv->adapter, &info); } @@ -1715,19 +1685,17 @@ static inline int i801_acpi_probe(struct i801_priv *priv) { return 0; } static inline void i801_acpi_remove(struct i801_priv *priv) { } #endif -static unsigned char i801_setup_hstcfg(struct i801_priv *priv) +static void i801_setup_hstcfg(struct i801_priv *priv) { unsigned char hstcfg = priv->original_hstcfg; hstcfg &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ hstcfg |= SMBHSTCFG_HST_EN; pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hstcfg); - return hstcfg; } static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) { - unsigned char temp; int err, i; struct i801_priv *priv; @@ -1838,8 +1806,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) if (i801_acpi_probe(priv)) return -ENODEV; - err = pcim_iomap_regions(dev, 1 << SMBBAR, - dev_driver_string(&dev->dev)); + err = pcim_iomap_regions(dev, 1 << SMBBAR, DRV_NAME); if (err) { dev_err(&dev->dev, "Failed to request SMBus region 0x%lx-0x%Lx\n", @@ -1850,16 +1817,16 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) } pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &priv->original_hstcfg); - temp = i801_setup_hstcfg(priv); + i801_setup_hstcfg(priv); if (!(priv->original_hstcfg & SMBHSTCFG_HST_EN)) dev_info(&dev->dev, "Enabling SMBus device\n"); - if (temp & SMBHSTCFG_SMB_SMI_EN) { + if (priv->original_hstcfg & SMBHSTCFG_SMB_SMI_EN) { dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n"); /* Disable SMBus interrupt feature if SMBus using SMI# */ priv->features &= ~FEATURE_IRQ; } - if (temp & SMBHSTCFG_SPD_WD) + if (priv->original_hstcfg & SMBHSTCFG_SPD_WD) dev_info(&dev->dev, "SPD Write Disable is set\n"); /* Clear special mode bits */ @@ -1881,24 +1848,23 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) u16 pcictl, pcists; /* Complain if an interrupt is already pending */ - pci_read_config_word(priv->pci_dev, SMBPCISTS, &pcists); - if (pcists & SMBPCISTS_INTS) + pci_read_config_word(priv->pci_dev, PCI_STATUS, &pcists); + if (pcists & PCI_STATUS_INTERRUPT) dev_warn(&dev->dev, "An interrupt is pending!\n"); /* Check if interrupts have been disabled */ - pci_read_config_word(priv->pci_dev, SMBPCICTL, &pcictl); - if (pcictl & SMBPCICTL_INTDIS) { + pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pcictl); + if (pcictl & PCI_COMMAND_INTX_DISABLE) { dev_info(&dev->dev, "Interrupts are disabled\n"); priv->features &= ~FEATURE_IRQ; } } if (priv->features & FEATURE_IRQ) { - init_waitqueue_head(&priv->waitq); + init_completion(&priv->done); err = devm_request_irq(&dev->dev, dev->irq, i801_isr, - IRQF_SHARED, - dev_driver_string(&dev->dev), priv); + IRQF_SHARED, DRV_NAME, priv); if (err) { dev_err(&dev->dev, "Failed to allocate irq %d: %d\n", dev->irq, err); @@ -1988,7 +1954,7 @@ static int i801_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(i801_pm_ops, i801_suspend, i801_resume); static struct pci_driver i801_driver = { - .name = "i801_smbus", + .name = DRV_NAME, .id_table = i801_ids, .probe = i801_probe, .remove = i801_remove, diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index dc5ca71906db..d5b5f084a27d 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -170,11 +170,11 @@ enum imx_i2c_type { struct imx_i2c_hwdata { enum imx_i2c_type devtype; - unsigned regshift; + unsigned int regshift; struct imx_i2c_clk_pair *clk_div; - unsigned ndivs; - unsigned i2sr_clr_opcode; - unsigned i2cr_ien_opcode; + unsigned int ndivs; + unsigned int i2sr_clr_opcode; + unsigned int i2cr_ien_opcode; }; struct imx_i2c_dma { @@ -452,8 +452,6 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool a unsigned long orig_jiffies = jiffies; unsigned int temp; - dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); - while (1) { temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR); @@ -599,8 +597,6 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx, bool atomic) unsigned int temp = 0; int result; - dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); - imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR); /* Enable I2C controller */ imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR); @@ -635,7 +631,6 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx, bool atomic) if (!i2c_imx->stopped) { /* Stop I2C transaction */ - dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); if (!(temp & I2CR_MSTA)) i2c_imx->stopped = 1; @@ -1167,8 +1162,6 @@ static int i2c_imx_xfer_common(struct i2c_adapter *adapter, bool is_lastmsg = false; struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter); - dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); - /* Start I2C transfer */ result = i2c_imx_start(i2c_imx, atomic); if (result) { @@ -1371,8 +1364,6 @@ static int i2c_imx_probe(struct platform_device *pdev) dma_addr_t phy_addr; const struct imx_i2c_hwdata *match; - dev_dbg(&pdev->dev, "<%s>\n", __func__); - irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; @@ -1395,7 +1386,7 @@ static int i2c_imx_probe(struct platform_device *pdev) platform_get_device_id(pdev)->driver_data; /* Setup i2c_imx driver structure */ - strlcpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name)); + strscpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name)); i2c_imx->adapter.owner = THIS_MODULE; i2c_imx->adapter.algo = &i2c_imx_algo; i2c_imx->adapter.dev.parent = &pdev->dev; diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index dcca9c2396db..6d5014ebaab5 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -635,6 +635,8 @@ static irqreturn_t mpc_i2c_isr(int irq, void *dev_id) status = readb(i2c->base + MPC_I2C_SR); if (status & CSR_MIF) { + /* Read again to allow register to stabilise */ + status = readb(i2c->base + MPC_I2C_SR); writeb(0, i2c->base + MPC_I2C_SR); mpc_i2c_do_intr(i2c, status); return IRQ_HANDLED; diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index 4e9fb6b44436..4ca716e09149 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -1225,6 +1225,13 @@ static int mtk_i2c_probe(struct platform_device *pdev) i2c->adap.quirks = i2c->dev_comp->quirks; i2c->adap.timeout = 2 * HZ; i2c->adap.retries = 1; + i2c->adap.bus_regulator = devm_regulator_get_optional(&pdev->dev, "vbus"); + if (IS_ERR(i2c->adap.bus_regulator)) { + if (PTR_ERR(i2c->adap.bus_regulator) == -ENODEV) + i2c->adap.bus_regulator = NULL; + else + return PTR_ERR(i2c->adap.bus_regulator); + } ret = mtk_i2c_parse_dt(pdev->dev.of_node, i2c); if (ret) @@ -1286,7 +1293,7 @@ static int mtk_i2c_probe(struct platform_device *pdev) ret = devm_request_irq(&pdev->dev, irq, mtk_i2c_irq, IRQF_NO_SUSPEND | IRQF_TRIGGER_NONE, - I2C_DRV_NAME, i2c); + dev_name(&pdev->dev), i2c); if (ret < 0) { dev_err(&pdev->dev, "Request I2C IRQ %d fail\n", irq); diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c index c63d5545fc2a..c1de8eb66169 100644 --- a/drivers/i2c/busses/i2c-qcom-cci.c +++ b/drivers/i2c/busses/i2c-qcom-cci.c @@ -769,6 +769,7 @@ static const struct of_device_id cci_dt_match[] = { { .compatible = "qcom,msm8916-cci", .data = &cci_v1_data}, { .compatible = "qcom,msm8996-cci", .data = &cci_v2_data}, { .compatible = "qcom,sdm845-cci", .data = &cci_v2_data}, + { .compatible = "qcom,sm8250-cci", .data = &cci_v2_data}, {} }; MODULE_DEVICE_TABLE(of, cci_dt_match); diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 327c092a4130..bff9913c37b8 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -1013,7 +1013,6 @@ static const struct of_device_id rcar_i2c_dt_ids[] = { { .compatible = "renesas,i2c-r8a7794", .data = (void *)I2C_RCAR_GEN2 }, { .compatible = "renesas,i2c-r8a7795", .data = (void *)I2C_RCAR_GEN3 }, { .compatible = "renesas,i2c-r8a7796", .data = (void *)I2C_RCAR_GEN3 }, - { .compatible = "renesas,i2c-rcar", .data = (void *)I2C_RCAR_GEN1 }, /* Deprecated */ { .compatible = "renesas,rcar-gen1-i2c", .data = (void *)I2C_RCAR_GEN1 }, { .compatible = "renesas,rcar-gen2-i2c", .data = (void *)I2C_RCAR_GEN2 }, { .compatible = "renesas,rcar-gen3-i2c", .data = (void *)I2C_RCAR_GEN3 }, diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c index 4eccc0f69861..78b84445ee6a 100644 --- a/drivers/i2c/busses/i2c-riic.c +++ b/drivers/i2c/busses/i2c-riic.c @@ -42,8 +42,10 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <linux/reset.h> #define RIIC_ICCR1 0x00 #define RIIC_ICCR2 0x04 @@ -86,6 +88,11 @@ #define RIIC_INIT_MSG -1 +enum riic_type { + RIIC_RZ_A, + RIIC_RZ_G2L, +}; + struct riic_dev { void __iomem *base; u8 *buf; @@ -395,7 +402,9 @@ static int riic_i2c_probe(struct platform_device *pdev) struct i2c_adapter *adap; struct resource *res; struct i2c_timings i2c_t; + struct reset_control *rstc; int i, ret; + enum riic_type type; riic = devm_kzalloc(&pdev->dev, sizeof(*riic), GFP_KERNEL); if (!riic) @@ -412,6 +421,17 @@ static int riic_i2c_probe(struct platform_device *pdev) return PTR_ERR(riic->clk); } + type = (enum riic_type)of_device_get_match_data(&pdev->dev); + if (type == RIIC_RZ_G2L) { + rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); + if (IS_ERR(rstc)) { + dev_err(&pdev->dev, "Error: missing reset ctrl\n"); + return PTR_ERR(rstc); + } + + reset_control_deassert(rstc); + } + for (i = 0; i < ARRAY_SIZE(riic_irqs); i++) { res = platform_get_resource(pdev, IORESOURCE_IRQ, riic_irqs[i].res_num); if (!res) @@ -472,7 +492,8 @@ static int riic_i2c_remove(struct platform_device *pdev) } static const struct of_device_id riic_i2c_dt_ids[] = { - { .compatible = "renesas,riic-rz" }, + { .compatible = "renesas,riic-r9a07g044", .data = (void *)RIIC_RZ_G2L }, + { .compatible = "renesas,riic-rz", .data = (void *)RIIC_RZ_A }, { /* Sentinel */ }, }; diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index 0138317ea600..b9b19a2a2ffa 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -51,6 +51,7 @@ /* STM32F7 I2C control 1 */ #define STM32F7_I2C_CR1_PECEN BIT(23) +#define STM32F7_I2C_CR1_ALERTEN BIT(22) #define STM32F7_I2C_CR1_SMBHEN BIT(20) #define STM32F7_I2C_CR1_WUPEN BIT(18) #define STM32F7_I2C_CR1_SBC BIT(16) @@ -125,6 +126,7 @@ (((n) & STM32F7_I2C_ISR_ADDCODE_MASK) >> 17) #define STM32F7_I2C_ISR_DIR BIT(16) #define STM32F7_I2C_ISR_BUSY BIT(15) +#define STM32F7_I2C_ISR_ALERT BIT(13) #define STM32F7_I2C_ISR_PECERR BIT(11) #define STM32F7_I2C_ISR_ARLO BIT(9) #define STM32F7_I2C_ISR_BERR BIT(8) @@ -138,6 +140,7 @@ #define STM32F7_I2C_ISR_TXE BIT(0) /* STM32F7 I2C Interrupt Clear */ +#define STM32F7_I2C_ICR_ALERTCF BIT(13) #define STM32F7_I2C_ICR_PECCF BIT(11) #define STM32F7_I2C_ICR_ARLOCF BIT(9) #define STM32F7_I2C_ICR_BERRCF BIT(8) @@ -279,6 +282,17 @@ struct stm32f7_i2c_msg { }; /** + * struct stm32f7_i2c_alert - SMBus alert specific data + * @setup: platform data for the smbus_alert i2c client + * @ara: I2C slave device used to respond to the SMBus Alert with Alert + * Response Address + */ +struct stm32f7_i2c_alert { + struct i2c_smbus_alert_setup setup; + struct i2c_client *ara; +}; + +/** * struct stm32f7_i2c_dev - private data of the controller * @adap: I2C adapter for this controller * @dev: device for this controller @@ -310,6 +324,7 @@ struct stm32f7_i2c_msg { * @analog_filter: boolean to indicate enabling of the analog filter * @dnf_dt: value of digital filter requested via dt * @dnf: value of digital filter to apply + * @alert: SMBus alert specific data */ struct stm32f7_i2c_dev { struct i2c_adapter adap; @@ -341,6 +356,7 @@ struct stm32f7_i2c_dev { bool analog_filter; u32 dnf_dt; u32 dnf; + struct stm32f7_i2c_alert *alert; }; /* @@ -1624,6 +1640,13 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data) f7_msg->result = -EINVAL; } + if (status & STM32F7_I2C_ISR_ALERT) { + dev_dbg(dev, "<%s>: SMBus alert received\n", __func__); + writel_relaxed(STM32F7_I2C_ICR_ALERTCF, base + STM32F7_I2C_ICR); + i2c_handle_smbus_alert(i2c_dev->alert->ara); + return IRQ_HANDLED; + } + if (!i2c_dev->slave_running) { u32 mask; /* Disable interrupts */ @@ -1990,6 +2013,42 @@ static void stm32f7_i2c_disable_smbus_host(struct stm32f7_i2c_dev *i2c_dev) } } +static int stm32f7_i2c_enable_smbus_alert(struct stm32f7_i2c_dev *i2c_dev) +{ + struct stm32f7_i2c_alert *alert; + struct i2c_adapter *adap = &i2c_dev->adap; + struct device *dev = i2c_dev->dev; + void __iomem *base = i2c_dev->base; + + alert = devm_kzalloc(dev, sizeof(*alert), GFP_KERNEL); + if (!alert) + return -ENOMEM; + + alert->ara = i2c_new_smbus_alert_device(adap, &alert->setup); + if (IS_ERR(alert->ara)) + return PTR_ERR(alert->ara); + + i2c_dev->alert = alert; + + /* Enable SMBus Alert */ + stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, STM32F7_I2C_CR1_ALERTEN); + + return 0; +} + +static void stm32f7_i2c_disable_smbus_alert(struct stm32f7_i2c_dev *i2c_dev) +{ + struct stm32f7_i2c_alert *alert = i2c_dev->alert; + void __iomem *base = i2c_dev->base; + + if (alert) { + /* Disable SMBus Alert */ + stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR1, + STM32F7_I2C_CR1_ALERTEN); + i2c_unregister_device(alert->ara); + } +} + static u32 stm32f7_i2c_func(struct i2c_adapter *adap) { struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(adap); @@ -2173,6 +2232,16 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) } } + if (of_property_read_bool(pdev->dev.of_node, "smbus-alert")) { + ret = stm32f7_i2c_enable_smbus_alert(i2c_dev); + if (ret) { + dev_err(i2c_dev->dev, + "failed to enable SMBus alert protocol (%d)\n", + ret); + goto i2c_disable_smbus_host; + } + } + dev_info(i2c_dev->dev, "STM32F7 I2C-%d bus adapter\n", adap->nr); pm_runtime_mark_last_busy(i2c_dev->dev); @@ -2180,6 +2249,9 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) return 0; +i2c_disable_smbus_host: + stm32f7_i2c_disable_smbus_host(i2c_dev); + i2c_adapter_remove: i2c_del_adapter(adap); @@ -2214,6 +2286,7 @@ static int stm32f7_i2c_remove(struct platform_device *pdev) { struct stm32f7_i2c_dev *i2c_dev = platform_get_drvdata(pdev); + stm32f7_i2c_disable_smbus_alert(i2c_dev); stm32f7_i2c_disable_smbus_host(i2c_dev); i2c_del_adapter(&i2c_dev->adap); diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 2a8568b97c14..bb93db98404e 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -798,11 +798,10 @@ static int xiic_i2c_probe(struct platform_device *pdev) init_waitqueue_head(&i2c->wait); i2c->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(i2c->clk)) { - if (PTR_ERR(i2c->clk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "input clock not found.\n"); - return PTR_ERR(i2c->clk); - } + if (IS_ERR(i2c->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(i2c->clk), + "input clock not found.\n"); + ret = clk_prepare_enable(i2c->clk); if (ret) { dev_err(&pdev->dev, "Unable to enable clock.\n"); diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 5a97e4a02fa2..84f12bf90644 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -24,6 +24,7 @@ #include <linux/i2c-smbus.h> #include <linux/idr.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/irqflags.h> #include <linux/jump_label.h> #include <linux/kernel.h> @@ -399,7 +400,8 @@ static int i2c_gpio_init_recovery(struct i2c_adapter *adap) static int i2c_init_recovery(struct i2c_adapter *adap) { struct i2c_bus_recovery_info *bri = adap->bus_recovery_info; - char *err_str, *err_level = KERN_ERR; + bool is_error_level = true; + char *err_str; if (!bri) return 0; @@ -409,7 +411,7 @@ static int i2c_init_recovery(struct i2c_adapter *adap) if (!bri->recover_bus) { err_str = "no suitable method provided"; - err_level = KERN_DEBUG; + is_error_level = false; goto err; } @@ -436,7 +438,10 @@ static int i2c_init_recovery(struct i2c_adapter *adap) return 0; err: - dev_printk(err_level, &adap->dev, "Not using recovery: %s\n", err_str); + if (is_error_level) + dev_err(&adap->dev, "Not using recovery: %s\n", err_str); + else + dev_dbg(&adap->dev, "Not using recovery: %s\n", err_str); adap->bus_recovery_info = NULL; return -EINVAL; @@ -461,12 +466,14 @@ static int i2c_smbus_host_notify_to_irq(const struct i2c_client *client) static int i2c_device_probe(struct device *dev) { struct i2c_client *client = i2c_verify_client(dev); + struct i2c_adapter *adap; struct i2c_driver *driver; int status; if (!client) return 0; + adap = client->adapter; client->irq = client->init_irq; if (!client->irq) { @@ -532,6 +539,14 @@ static int i2c_device_probe(struct device *dev) dev_dbg(dev, "probe\n"); + if (adap->bus_regulator) { + status = regulator_enable(adap->bus_regulator); + if (status < 0) { + dev_err(&adap->dev, "Failed to enable bus regulator\n"); + goto err_clear_wakeup_irq; + } + } + status = of_clk_set_defaults(dev->of_node, false); if (status < 0) goto err_clear_wakeup_irq; @@ -589,8 +604,10 @@ put_sync_adapter: static int i2c_device_remove(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); + struct i2c_adapter *adap; struct i2c_driver *driver; + adap = client->adapter; driver = to_i2c_driver(dev->driver); if (driver->remove) { int status; @@ -605,6 +622,8 @@ static int i2c_device_remove(struct device *dev) devres_release_group(&client->dev, client->devres_group_id); dev_pm_domain_detach(&client->dev, true); + if (!pm_runtime_status_suspended(&client->dev) && adap->bus_regulator) + regulator_disable(adap->bus_regulator); dev_pm_clear_wake_irq(&client->dev); device_init_wakeup(&client->dev, false); @@ -617,6 +636,86 @@ static int i2c_device_remove(struct device *dev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int i2c_resume_early(struct device *dev) +{ + struct i2c_client *client = i2c_verify_client(dev); + int err; + + if (!client) + return 0; + + if (pm_runtime_status_suspended(&client->dev) && + client->adapter->bus_regulator) { + err = regulator_enable(client->adapter->bus_regulator); + if (err) + return err; + } + + return pm_generic_resume_early(&client->dev); +} + +static int i2c_suspend_late(struct device *dev) +{ + struct i2c_client *client = i2c_verify_client(dev); + int err; + + if (!client) + return 0; + + err = pm_generic_suspend_late(&client->dev); + if (err) + return err; + + if (!pm_runtime_status_suspended(&client->dev) && + client->adapter->bus_regulator) + return regulator_disable(client->adapter->bus_regulator); + + return 0; +} +#endif + +#ifdef CONFIG_PM +static int i2c_runtime_resume(struct device *dev) +{ + struct i2c_client *client = i2c_verify_client(dev); + int err; + + if (!client) + return 0; + + if (client->adapter->bus_regulator) { + err = regulator_enable(client->adapter->bus_regulator); + if (err) + return err; + } + + return pm_generic_runtime_resume(&client->dev); +} + +static int i2c_runtime_suspend(struct device *dev) +{ + struct i2c_client *client = i2c_verify_client(dev); + int err; + + if (!client) + return 0; + + err = pm_generic_runtime_suspend(&client->dev); + if (err) + return err; + + if (client->adapter->bus_regulator) + return regulator_disable(client->adapter->bus_regulator); + return 0; +} +#endif + +static const struct dev_pm_ops i2c_device_pm = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(i2c_suspend_late, i2c_resume_early) + SET_RUNTIME_PM_OPS(i2c_runtime_suspend, i2c_runtime_resume, NULL) +}; + static void i2c_device_shutdown(struct device *dev) { struct i2c_client *client = i2c_verify_client(dev); @@ -627,6 +726,8 @@ static void i2c_device_shutdown(struct device *dev) driver = to_i2c_driver(dev->driver); if (driver->shutdown) driver->shutdown(client); + else if (client->irq > 0) + disable_irq(client->irq); } static void i2c_client_dev_release(struct device *dev) @@ -674,6 +775,7 @@ struct bus_type i2c_bus_type = { .probe = i2c_device_probe, .remove = i2c_device_remove, .shutdown = i2c_device_shutdown, + .pm = &i2c_device_pm, }; EXPORT_SYMBOL_GPL(i2c_bus_type); diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c index d2d32c0fd8c3..e5b2d1465e7e 100644 --- a/drivers/i2c/i2c-core-smbus.c +++ b/drivers/i2c/i2c-core-smbus.c @@ -37,8 +37,15 @@ static u8 crc8(u16 data) return (u8)(data >> 8); } -/* Incremental CRC8 over count bytes in the array pointed to by p */ -static u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count) +/** + * i2c_smbus_pec - Incremental CRC8 over the given input data array + * @crc: previous return crc8 value + * @p: pointer to data buffer. + * @count: number of bytes in data buffer. + * + * Incremental CRC8 over count bytes in the array pointed to by p + */ +u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count) { int i; @@ -46,6 +53,7 @@ static u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count) crc = crc8((crc ^ p[i]) << 8); return crc; } +EXPORT_SYMBOL(i2c_smbus_pec); /* Assume a 7-bit address, which is reasonable for SMBus */ static u8 i2c_smbus_msg_pec(u8 pec, struct i2c_msg *msg) diff --git a/drivers/i3c/master/i3c-master-cdns.c b/drivers/i3c/master/i3c-master-cdns.c index 3f2226928fe0..5b37ffe5ad5b 100644 --- a/drivers/i3c/master/i3c-master-cdns.c +++ b/drivers/i3c/master/i3c-master-cdns.c @@ -1379,6 +1379,8 @@ static void cnds_i3c_master_demux_ibis(struct cdns_i3c_master *master) case IBIR_TYPE_MR: WARN_ON(IBIR_XFER_BYTES(ibir) || (ibir & IBIR_ERROR)); + break; + default: break; } diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 8b1723635cce..0e56ace61103 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -89,13 +89,13 @@ config ADXL372_I2C module will be called adxl372_i2c. config BMA180 - tristate "Bosch BMA023/BMA1x0/BMA25x 3-Axis Accelerometer Driver" + tristate "Bosch BMA023/BMA1x0/BMA250 3-Axis Accelerometer Driver" depends on I2C && INPUT_BMA150=n select IIO_BUFFER select IIO_TRIGGERED_BUFFER help Say Y here if you want to build a driver for the Bosch BMA023, BMA150 - BMA180, SMB380, or BMA25x triaxial acceleration sensor. + BMA180, BMA250 or SMB380 triaxial acceleration sensor. To compile this driver as a module, choose M here: the module will be called bma180. @@ -143,9 +143,12 @@ config BMC150_ACCEL select BMC150_ACCEL_SPI if SPI help Say yes here to build support for the following Bosch accelerometers: - BMC150, BMI055, BMA250E, BMA222E, BMA255, BMA280. + BMA222, BMA222E, BMA250E, BMA253, BMA254, BMA255, BMA280, BMC150, BMI055. + + Note that some of these are combo modules: + - BMC150: accelerometer and magnetometer + - BMI055: accelerometer and gyroscope - This is a combo module with both accelerometer and magnetometer. This driver is only implementing accelerometer part, which has its own address and register map. @@ -226,6 +229,33 @@ config DMARD10 Choosing M will build the driver as a module. If so, the module will be called dmard10. +config FXLS8962AF + tristate + +config FXLS8962AF_I2C + tristate "NXP FXLS8962AF/FXLS8964AF Accelerometer I2C Driver" + depends on I2C + select FXLS8962AF + select REGMAP_I2C + help + Say yes here to build support for the NXP 3-axis automotive + accelerometer FXLS8962AF/FXLS8964AF with I2C support. + + To compile this driver as a module, choose M here: the module + will be called fxls8962af_i2c. + +config FXLS8962AF_SPI + tristate "NXP FXLS8962AF/FXLS8964AF Accelerometer SPI Driver" + depends on SPI + select FXLS8962AF + select REGMAP_SPI + help + Say yes here to build support for the NXP 3-axis automotive + accelerometer FXLS8962AF/FXLS8964AF with SPI support. + + To compile this driver as a module, choose M here: the module + will be called fxls8962af_spi. + config HID_SENSOR_ACCEL_3D depends on HID_SENSOR_HUB select IIO_BUFFER @@ -449,6 +479,19 @@ config SCA3000 To compile this driver as a module, say M here: the module will be called sca3000. +config SCA3300 + tristate "Murata SCA3300 3-Axis Accelerometer Driver" + depends on SPI + select CRC8 + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for Murata SCA3300 3-Axis + accelerometer. + + To compile this driver as a module, choose M here: the module will be + called sca3300. + config STK8312 tristate "Sensortek STK8312 3-Axis Accelerometer Driver" depends on I2C diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index 32cd1342a31a..89280e823bcd 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -27,6 +27,9 @@ obj-$(CONFIG_DA311) += da311.o obj-$(CONFIG_DMARD06) += dmard06.o obj-$(CONFIG_DMARD09) += dmard09.o obj-$(CONFIG_DMARD10) += dmard10.o +obj-$(CONFIG_FXLS8962AF) += fxls8962af-core.o +obj-$(CONFIG_FXLS8962AF_I2C) += fxls8962af-i2c.o +obj-$(CONFIG_FXLS8962AF_SPI) += fxls8962af-spi.o obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o obj-$(CONFIG_KXSD9) += kxsd9.o @@ -50,6 +53,7 @@ obj-$(CONFIG_MXC4005) += mxc4005.o obj-$(CONFIG_MXC6255) += mxc6255.o obj-$(CONFIG_SCA3000) += sca3000.o +obj-$(CONFIG_SCA3300) += sca3300.o obj-$(CONFIG_STK8312) += stk8312.o obj-$(CONFIG_STK8BA50) += stk8ba50.o diff --git a/drivers/iio/accel/adis16201.c b/drivers/iio/accel/adis16201.c index fe225990de24..7a434e2884d4 100644 --- a/drivers/iio/accel/adis16201.c +++ b/drivers/iio/accel/adis16201.c @@ -8,10 +8,7 @@ #include <linux/device.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/mutex.h> -#include <linux/slab.h> #include <linux/spi/spi.h> -#include <linux/sysfs.h> #include <linux/iio/iio.h> #include <linux/iio/imu/adis.h> diff --git a/drivers/iio/accel/adis16209.c b/drivers/iio/accel/adis16209.c index 6c2d4a967de7..ac08e866d612 100644 --- a/drivers/iio/accel/adis16209.c +++ b/drivers/iio/accel/adis16209.c @@ -7,11 +7,8 @@ #include <linux/device.h> #include <linux/kernel.h> -#include <linux/list.h> #include <linux/module.h> #include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> #include <linux/iio/iio.h> #include <linux/iio/imu/adis.h> diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c index 9c9a896a872a..fc9592407717 100644 --- a/drivers/iio/accel/adxl372.c +++ b/drivers/iio/accel/adxl372.c @@ -1223,14 +1223,14 @@ int adxl372_probe(struct device *dev, struct regmap *regmap, st->dready_trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (st->dready_trig == NULL) return -ENOMEM; st->peak_datardy_trig = devm_iio_trigger_alloc(dev, "%s-dev%d-peak", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!st->peak_datardy_trig) return -ENOMEM; diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index b8a7469cdae4..2edfcb4819b7 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -10,7 +10,6 @@ * BMA023/BMA150/SMB380: 7-bit I2C slave address 0x38 * BMA180: 7-bit I2C slave address 0x40 or 0x41 * BMA250: 7-bit I2C slave address 0x18 or 0x19 - * BMA254: 7-bit I2C slave address 0x18 or 0x19 */ #include <linux/module.h> @@ -38,7 +37,6 @@ enum chip_ids { BMA150, BMA180, BMA250, - BMA254, }; struct bma180_data; @@ -55,11 +53,10 @@ struct bma180_part_info { u8 int_reset_reg, int_reset_mask; u8 sleep_reg, sleep_mask; - u8 bw_reg, bw_mask; + u8 bw_reg, bw_mask, bw_offset; u8 scale_reg, scale_mask; u8 power_reg, power_mask, lowpower_val; u8 int_enable_reg, int_enable_mask; - u8 int_map_reg, int_enable_dataready_int1_mask; u8 softreset_reg, softreset_val; int (*chip_config)(struct bma180_data *data); @@ -112,7 +109,6 @@ struct bma180_part_info { #define BMA023_ID_REG_VAL 0x02 #define BMA180_ID_REG_VAL 0x03 #define BMA250_ID_REG_VAL 0x03 -#define BMA254_ID_REG_VAL 0xfa /* 250 decimal */ /* Chip power modes */ #define BMA180_LOW_POWER 0x03 @@ -127,29 +123,13 @@ struct bma180_part_info { #define BMA250_RANGE_MASK GENMASK(3, 0) /* Range of accel values */ #define BMA250_BW_MASK GENMASK(4, 0) /* Accel bandwidth */ +#define BMA250_BW_OFFSET 8 #define BMA250_SUSPEND_MASK BIT(7) /* chip will sleep */ #define BMA250_LOWPOWER_MASK BIT(6) #define BMA250_DATA_INTEN_MASK BIT(4) #define BMA250_INT1_DATA_MASK BIT(0) #define BMA250_INT_RESET_MASK BIT(7) /* Reset pending interrupts */ -#define BMA254_RANGE_REG 0x0f -#define BMA254_BW_REG 0x10 -#define BMA254_POWER_REG 0x11 -#define BMA254_RESET_REG 0x14 -#define BMA254_INT_ENABLE_REG 0x17 -#define BMA254_INT_MAP_REG 0x1a -#define BMA254_INT_RESET_REG 0x21 - -#define BMA254_RANGE_MASK GENMASK(3, 0) /* Range of accel values */ -#define BMA254_BW_MASK GENMASK(4, 0) /* Accel bandwidth */ -#define BMA254_SUSPEND_MASK BIT(7) /* chip will sleep */ -#define BMA254_LOWPOWER_MASK BIT(6) -#define BMA254_DATA_INTEN_MASK BIT(4) -#define BMA254_INT2_DATA_MASK BIT(7) -#define BMA254_INT1_DATA_MASK BIT(0) -#define BMA254_INT_RESET_MASK BIT(7) /* Reset pending interrupts */ - struct bma180_data { struct regulator *vdd_supply; struct regulator *vddio_supply; @@ -162,7 +142,11 @@ struct bma180_data { int scale; int bw; bool pmode; - u8 buff[16]; /* 3x 16-bit + 8-bit + padding + timestamp */ + /* Ensure timestamp is naturally aligned */ + struct { + s16 chan[4]; + s64 timestamp __aligned(8); + } scan; }; enum bma180_chan { @@ -178,8 +162,8 @@ static int bma023_scale_table[] = { 2452, 4903, 9709, }; static int bma180_bw_table[] = { 10, 20, 40, 75, 150, 300 }; /* Hz */ static int bma180_scale_table[] = { 1275, 1863, 2452, 3727, 4903, 9709, 19417 }; -static int bma25x_bw_table[] = { 8, 16, 31, 63, 125, 250 }; /* Hz */ -static int bma25x_scale_table[] = { 0, 0, 0, 38344, 0, 76590, 0, 0, 153180, 0, +static int bma250_bw_table[] = { 8, 16, 31, 63, 125, 250, 500, 1000 }; /* Hz */ +static int bma250_scale_table[] = { 0, 0, 0, 38344, 0, 76590, 0, 0, 153180, 0, 0, 0, 306458 }; static int bma180_get_data_reg(struct bma180_data *data, enum bma180_chan chan) @@ -283,7 +267,8 @@ static int bma180_set_bw(struct bma180_data *data, int val) for (i = 0; i < data->part_info->num_bw; ++i) { if (data->part_info->bw_table[i] == val) { ret = bma180_set_bits(data, data->part_info->bw_reg, - data->part_info->bw_mask, i); + data->part_info->bw_mask, + i + data->part_info->bw_offset); if (ret) { dev_err(&data->client->dev, "failed to set bandwidth\n"); @@ -425,7 +410,7 @@ err: return ret; } -static int bma25x_chip_config(struct bma180_data *data) +static int bma250_chip_config(struct bma180_data *data) { int ret = bma180_chip_init(data); @@ -444,8 +429,7 @@ static int bma25x_chip_config(struct bma180_data *data) * This enables dataready interrupt on the INT1 pin * FIXME: support using the INT2 pin */ - ret = bma180_set_bits(data, data->part_info->int_map_reg, - data->part_info->int_enable_dataready_int1_mask, 1); + ret = bma180_set_bits(data, BMA250_INT_MAP_REG, BMA250_INT1_DATA_MASK, 1); if (ret) goto err; @@ -482,7 +466,7 @@ err: dev_err(&data->client->dev, "failed to disable the chip\n"); } -static void bma25x_chip_disable(struct bma180_data *data) +static void bma250_chip_disable(struct bma180_data *data) { if (bma180_set_new_data_intr_state(data, false)) goto err; @@ -768,14 +752,6 @@ static const struct iio_chan_spec bma250_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(4), }; -static const struct iio_chan_spec bma254_channels[] = { - BMA180_ACC_CHANNEL(X, 12), - BMA180_ACC_CHANNEL(Y, 12), - BMA180_ACC_CHANNEL(Z, 12), - BMA180_TEMP_CHANNEL, - IIO_CHAN_SOFT_TIMESTAMP(4), -}; - static const struct bma180_part_info bma180_part_info[] = { [BMA023] = { .chip_id = BMA023_ID_REG_VAL, @@ -865,10 +841,10 @@ static const struct bma180_part_info bma180_part_info[] = { .chip_id = BMA250_ID_REG_VAL, .channels = bma250_channels, .num_channels = ARRAY_SIZE(bma250_channels), - .scale_table = bma25x_scale_table, - .num_scales = ARRAY_SIZE(bma25x_scale_table), - .bw_table = bma25x_bw_table, - .num_bw = ARRAY_SIZE(bma25x_bw_table), + .scale_table = bma250_scale_table, + .num_scales = ARRAY_SIZE(bma250_scale_table), + .bw_table = bma250_bw_table, + .num_bw = ARRAY_SIZE(bma250_bw_table), .temp_offset = 48, /* 0 LSB @ 24 degree C */ .int_reset_reg = BMA250_INT_RESET_REG, .int_reset_mask = BMA250_INT_RESET_MASK, @@ -876,6 +852,7 @@ static const struct bma180_part_info bma180_part_info[] = { .sleep_mask = BMA250_SUSPEND_MASK, .bw_reg = BMA250_BW_REG, .bw_mask = BMA250_BW_MASK, + .bw_offset = BMA250_BW_OFFSET, .scale_reg = BMA250_RANGE_REG, .scale_mask = BMA250_RANGE_MASK, .power_reg = BMA250_POWER_REG, @@ -883,41 +860,10 @@ static const struct bma180_part_info bma180_part_info[] = { .lowpower_val = 1, .int_enable_reg = BMA250_INT_ENABLE_REG, .int_enable_mask = BMA250_DATA_INTEN_MASK, - .int_map_reg = BMA250_INT_MAP_REG, - .int_enable_dataready_int1_mask = BMA250_INT1_DATA_MASK, .softreset_reg = BMA250_RESET_REG, .softreset_val = BMA180_RESET_VAL, - .chip_config = bma25x_chip_config, - .chip_disable = bma25x_chip_disable, - }, - [BMA254] = { - .chip_id = BMA254_ID_REG_VAL, - .channels = bma254_channels, - .num_channels = ARRAY_SIZE(bma254_channels), - .scale_table = bma25x_scale_table, - .num_scales = ARRAY_SIZE(bma25x_scale_table), - .bw_table = bma25x_bw_table, - .num_bw = ARRAY_SIZE(bma25x_bw_table), - .temp_offset = 46, /* 0 LSB @ 23 degree C */ - .int_reset_reg = BMA254_INT_RESET_REG, - .int_reset_mask = BMA254_INT_RESET_MASK, - .sleep_reg = BMA254_POWER_REG, - .sleep_mask = BMA254_SUSPEND_MASK, - .bw_reg = BMA254_BW_REG, - .bw_mask = BMA254_BW_MASK, - .scale_reg = BMA254_RANGE_REG, - .scale_mask = BMA254_RANGE_MASK, - .power_reg = BMA254_POWER_REG, - .power_mask = BMA254_LOWPOWER_MASK, - .lowpower_val = 1, - .int_enable_reg = BMA254_INT_ENABLE_REG, - .int_enable_mask = BMA254_DATA_INTEN_MASK, - .int_map_reg = BMA254_INT_MAP_REG, - .int_enable_dataready_int1_mask = BMA254_INT1_DATA_MASK, - .softreset_reg = BMA254_RESET_REG, - .softreset_val = BMA180_RESET_VAL, - .chip_config = bma25x_chip_config, - .chip_disable = bma25x_chip_disable, + .chip_config = bma250_chip_config, + .chip_disable = bma250_chip_disable, }, }; @@ -938,12 +884,12 @@ static irqreturn_t bma180_trigger_handler(int irq, void *p) mutex_unlock(&data->mutex); goto err; } - ((s16 *)data->buff)[i++] = ret; + data->scan.chan[i++] = ret; } mutex_unlock(&data->mutex); - iio_push_to_buffers_with_timestamp(indio_dev, data->buff, time_ns); + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, time_ns); err: iio_trigger_notify_done(indio_dev->trig); @@ -997,8 +943,7 @@ static int bma180_probe(struct i2c_client *client, chip = id->driver_data; data->part_info = &bma180_part_info[chip]; - ret = iio_read_mount_matrix(dev, "mount-matrix", - &data->orientation); + ret = iio_read_mount_matrix(dev, &data->orientation); if (ret) return ret; @@ -1045,7 +990,7 @@ static int bma180_probe(struct i2c_client *client, if (client->irq > 0) { data->trig = iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!data->trig) { ret = -ENOMEM; goto err_chip_disable; @@ -1158,7 +1103,6 @@ static const struct i2c_device_id bma180_ids[] = { { "bma150", BMA150 }, { "bma180", BMA180 }, { "bma250", BMA250 }, - { "bma254", BMA254 }, { "smb380", BMA150 }, { } }; @@ -1183,10 +1127,6 @@ static const struct of_device_id bma180_of_match[] = { .data = (void *)BMA250 }, { - .compatible = "bosch,bma254", - .data = (void *)BMA254 - }, - { .compatible = "bosch,smb380", .data = (void *)BMA150 }, @@ -1209,5 +1149,5 @@ module_i2c_driver(bma180_driver); MODULE_AUTHOR("Kravchenko Oleksandr <x0199363@ti.com>"); MODULE_AUTHOR("Texas Instruments, Inc."); -MODULE_DESCRIPTION("Bosch BMA023/BMA1x0/BMA25x triaxial acceleration sensor"); +MODULE_DESCRIPTION("Bosch BMA023/BMA1x0/BMA250 triaxial acceleration sensor"); MODULE_LICENSE("GPL"); diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c index 36fc9876dbca..0622c7936499 100644 --- a/drivers/iio/accel/bma220_spi.c +++ b/drivers/iio/accel/bma220_spi.c @@ -63,7 +63,11 @@ static const int bma220_scale_table[][2] = { struct bma220_data { struct spi_device *spi_device; struct mutex lock; - s8 buffer[16]; /* 3x8-bit channels + 5x8 padding + 8x8 timestamp */ + struct { + s8 chans[3]; + /* Ensure timestamp is naturally aligned. */ + s64 timestamp __aligned(8); + } scan; u8 tx_buf[2] ____cacheline_aligned; }; @@ -94,12 +98,12 @@ static irqreturn_t bma220_trigger_handler(int irq, void *p) mutex_lock(&data->lock); data->tx_buf[0] = BMA220_REG_ACCEL_X | BMA220_READ_MASK; - ret = spi_write_then_read(spi, data->tx_buf, 1, data->buffer, + ret = spi_write_then_read(spi, data->tx_buf, 1, &data->scan.chans, ARRAY_SIZE(bma220_channels) - 1); if (ret < 0) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, pf->timestamp); err: mutex_unlock(&data->lock); diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c index 7eeba80e32cb..21520e022a21 100644 --- a/drivers/iio/accel/bma400_core.c +++ b/drivers/iio/accel/bma400_core.c @@ -811,7 +811,7 @@ int bma400_probe(struct device *dev, struct regmap *regmap, const char *name) if (ret) return ret; - ret = iio_read_mount_matrix(dev, "mount-matrix", &data->orientation); + ret = iio_read_mount_matrix(dev, &data->orientation); if (ret) return ret; diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c index 04d85ce34e9f..5ce384ebe6c7 100644 --- a/drivers/iio/accel/bmc150-accel-core.c +++ b/drivers/iio/accel/bmc150-accel-core.c @@ -1,14 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * 3-axis accelerometer driver supporting following Bosch-Sensortec chips: - * - BMC150 - * - BMI055 - * - BMA255 - * - BMA250E - * - BMA222 - * - BMA222E - * - BMA280 - * + * 3-axis accelerometer driver supporting many Bosch-Sensortec chips * Copyright (c) 2014, Intel Corporation. */ @@ -157,59 +149,6 @@ struct bmc150_accel_chip_info { const struct bmc150_scale_info scale_table[4]; }; -struct bmc150_accel_interrupt { - const struct bmc150_accel_interrupt_info *info; - atomic_t users; -}; - -struct bmc150_accel_trigger { - struct bmc150_accel_data *data; - struct iio_trigger *indio_trig; - int (*setup)(struct bmc150_accel_trigger *t, bool state); - int intr; - bool enabled; -}; - -enum bmc150_accel_interrupt_id { - BMC150_ACCEL_INT_DATA_READY, - BMC150_ACCEL_INT_ANY_MOTION, - BMC150_ACCEL_INT_WATERMARK, - BMC150_ACCEL_INTERRUPTS, -}; - -enum bmc150_accel_trigger_id { - BMC150_ACCEL_TRIGGER_DATA_READY, - BMC150_ACCEL_TRIGGER_ANY_MOTION, - BMC150_ACCEL_TRIGGERS, -}; - -struct bmc150_accel_data { - struct regmap *regmap; - struct regulator_bulk_data regulators[2]; - struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS]; - struct bmc150_accel_trigger triggers[BMC150_ACCEL_TRIGGERS]; - struct mutex mutex; - u8 fifo_mode, watermark; - s16 buffer[8]; - /* - * Ensure there is sufficient space and correct alignment for - * the timestamp if enabled - */ - struct { - __le16 channels[3]; - s64 ts __aligned(8); - } scan; - u8 bw_bits; - u32 slope_dur; - u32 slope_thres; - u32 range; - int ev_enable_state; - int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */ - const struct bmc150_accel_chip_info *chip_info; - struct i2c_client *second_device; - struct iio_mount_matrix orientation; -}; - static const struct { int val; int val2; @@ -389,7 +328,7 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on) int ret; if (on) { - ret = pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); } else { pm_runtime_mark_last_busy(dev); ret = pm_runtime_put_autosuspend(dev); @@ -398,9 +337,6 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on) if (ret < 0) { dev_err(dev, "Failed: %s for %d\n", __func__, on); - if (on) - pm_runtime_put_noidle(dev); - return ret; } @@ -439,8 +375,8 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on) * Onda V80 plus * Predia Basic Tablet */ -static bool bmc150_apply_acpi_orientation(struct device *dev, - struct iio_mount_matrix *orientation) +static bool bmc150_apply_bosc0200_acpi_orientation(struct device *dev, + struct iio_mount_matrix *orientation) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; struct iio_dev *indio_dev = dev_get_drvdata(dev); @@ -450,9 +386,6 @@ static bool bmc150_apply_acpi_orientation(struct device *dev, acpi_status status; int i, j, val[3]; - if (!adev || !acpi_dev_hid_uid_match(adev, "BOSC0200", NULL)) - return false; - if (strcmp(dev_name(dev), "i2c-BOSC0200:base") == 0) { alt_name = "ROMK"; label = "accel-base"; @@ -508,6 +441,33 @@ unknown_format: kfree(buffer.pointer); return false; } + +static bool bmc150_apply_dual250e_acpi_orientation(struct device *dev, + struct iio_mount_matrix *orientation) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + + if (strcmp(dev_name(dev), "i2c-DUAL250E:base") == 0) + indio_dev->label = "accel-base"; + else + indio_dev->label = "accel-display"; + + return false; /* DUAL250E fwnodes have no mount matrix info */ +} + +static bool bmc150_apply_acpi_orientation(struct device *dev, + struct iio_mount_matrix *orientation) +{ + struct acpi_device *adev = ACPI_COMPANION(dev); + + if (adev && acpi_dev_hid_uid_match(adev, "BOSC0200", NULL)) + return bmc150_apply_bosc0200_acpi_orientation(dev, orientation); + + if (adev && acpi_dev_hid_uid_match(adev, "DUAL250E", NULL)) + return bmc150_apply_dual250e_acpi_orientation(dev, orientation); + + return false; +} #else static bool bmc150_apply_acpi_orientation(struct device *dev, struct iio_mount_matrix *orientation) @@ -1128,80 +1088,63 @@ static const struct iio_chan_spec bmc150_accel_channels[] = static const struct iio_chan_spec bma280_accel_channels[] = BMC150_ACCEL_CHANNELS(14); +/* + * The range for the Bosch sensors is typically +-2g/4g/8g/16g, distributed + * over the amount of bits (see above). The scale table can be calculated using + * (range / 2^bits) * g = (range / 2^bits) * 9.80665 m/s^2 + * e.g. for +-2g and 12 bits: (4 / 2^12) * 9.80665 m/s^2 = 0.0095768... m/s^2 + * Multiply 10^6 and round to get the values listed below. + */ static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = { - [bmc150] = { - .name = "BMC150A", - .chip_id = 0xFA, - .channels = bmc150_accel_channels, - .num_channels = ARRAY_SIZE(bmc150_accel_channels), - .scale_table = { {9610, BMC150_ACCEL_DEF_RANGE_2G}, - {19122, BMC150_ACCEL_DEF_RANGE_4G}, - {38344, BMC150_ACCEL_DEF_RANGE_8G}, - {76590, BMC150_ACCEL_DEF_RANGE_16G} }, - }, - [bmi055] = { - .name = "BMI055A", - .chip_id = 0xFA, - .channels = bmc150_accel_channels, - .num_channels = ARRAY_SIZE(bmc150_accel_channels), - .scale_table = { {9610, BMC150_ACCEL_DEF_RANGE_2G}, - {19122, BMC150_ACCEL_DEF_RANGE_4G}, - {38344, BMC150_ACCEL_DEF_RANGE_8G}, - {76590, BMC150_ACCEL_DEF_RANGE_16G} }, - }, - [bma255] = { - .name = "BMA0255", - .chip_id = 0xFA, - .channels = bmc150_accel_channels, - .num_channels = ARRAY_SIZE(bmc150_accel_channels), - .scale_table = { {9610, BMC150_ACCEL_DEF_RANGE_2G}, - {19122, BMC150_ACCEL_DEF_RANGE_4G}, - {38344, BMC150_ACCEL_DEF_RANGE_8G}, - {76590, BMC150_ACCEL_DEF_RANGE_16G} }, - }, - [bma250e] = { - .name = "BMA250E", - .chip_id = 0xF9, - .channels = bma250e_accel_channels, - .num_channels = ARRAY_SIZE(bma250e_accel_channels), - .scale_table = { {38344, BMC150_ACCEL_DEF_RANGE_2G}, - {76590, BMC150_ACCEL_DEF_RANGE_4G}, - {153277, BMC150_ACCEL_DEF_RANGE_8G}, - {306457, BMC150_ACCEL_DEF_RANGE_16G} }, - }, - [bma222] = { + { .name = "BMA222", .chip_id = 0x03, .channels = bma222e_accel_channels, .num_channels = ARRAY_SIZE(bma222e_accel_channels), - /* - * The datasheet page 17 says: - * 15.6, 31.3, 62.5 and 125 mg per LSB. - */ - .scale_table = { {156000, BMC150_ACCEL_DEF_RANGE_2G}, - {313000, BMC150_ACCEL_DEF_RANGE_4G}, - {625000, BMC150_ACCEL_DEF_RANGE_8G}, - {1250000, BMC150_ACCEL_DEF_RANGE_16G} }, + .scale_table = { {153229, BMC150_ACCEL_DEF_RANGE_2G}, + {306458, BMC150_ACCEL_DEF_RANGE_4G}, + {612916, BMC150_ACCEL_DEF_RANGE_8G}, + {1225831, BMC150_ACCEL_DEF_RANGE_16G} }, }, - [bma222e] = { + { .name = "BMA222E", .chip_id = 0xF8, .channels = bma222e_accel_channels, .num_channels = ARRAY_SIZE(bma222e_accel_channels), - .scale_table = { {153277, BMC150_ACCEL_DEF_RANGE_2G}, - {306457, BMC150_ACCEL_DEF_RANGE_4G}, - {612915, BMC150_ACCEL_DEF_RANGE_8G}, + .scale_table = { {153229, BMC150_ACCEL_DEF_RANGE_2G}, + {306458, BMC150_ACCEL_DEF_RANGE_4G}, + {612916, BMC150_ACCEL_DEF_RANGE_8G}, {1225831, BMC150_ACCEL_DEF_RANGE_16G} }, }, - [bma280] = { - .name = "BMA0280", + { + .name = "BMA250E", + .chip_id = 0xF9, + .channels = bma250e_accel_channels, + .num_channels = ARRAY_SIZE(bma250e_accel_channels), + .scale_table = { {38307, BMC150_ACCEL_DEF_RANGE_2G}, + {76614, BMC150_ACCEL_DEF_RANGE_4G}, + {153229, BMC150_ACCEL_DEF_RANGE_8G}, + {306458, BMC150_ACCEL_DEF_RANGE_16G} }, + }, + { + .name = "BMA253/BMA254/BMA255/BMC150/BMI055", + .chip_id = 0xFA, + .channels = bmc150_accel_channels, + .num_channels = ARRAY_SIZE(bmc150_accel_channels), + .scale_table = { {9577, BMC150_ACCEL_DEF_RANGE_2G}, + {19154, BMC150_ACCEL_DEF_RANGE_4G}, + {38307, BMC150_ACCEL_DEF_RANGE_8G}, + {76614, BMC150_ACCEL_DEF_RANGE_16G} }, + }, + { + .name = "BMA280", .chip_id = 0xFB, .channels = bma280_accel_channels, .num_channels = ARRAY_SIZE(bma280_accel_channels), - .scale_table = { {2392, BMC150_ACCEL_DEF_RANGE_2G}, - {4785, BMC150_ACCEL_DEF_RANGE_4G}, - {9581, BMC150_ACCEL_DEF_RANGE_8G}, - {19152, BMC150_ACCEL_DEF_RANGE_16G} }, + .scale_table = { {2394, BMC150_ACCEL_DEF_RANGE_2G}, + {4788, BMC150_ACCEL_DEF_RANGE_4G}, + {9577, BMC150_ACCEL_DEF_RANGE_8G}, + {19154, BMC150_ACCEL_DEF_RANGE_16G} }, }, }; @@ -1470,9 +1413,9 @@ static int bmc150_accel_triggers_setup(struct iio_dev *indio_dev, struct bmc150_accel_trigger *t = &data->triggers[i]; t->indio_trig = devm_iio_trigger_alloc(dev, - bmc150_accel_triggers[i].name, + bmc150_accel_triggers[i].name, indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!t->indio_trig) { ret = -ENOMEM; break; @@ -1688,8 +1631,7 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, data->regmap = regmap; if (!bmc150_apply_acpi_orientation(dev, &data->orientation)) { - ret = iio_read_mount_matrix(dev, "mount-matrix", - &data->orientation); + ret = iio_read_mount_matrix(dev, &data->orientation); if (ret) return ret; } @@ -1807,26 +1749,6 @@ err_disable_regulators: } EXPORT_SYMBOL_GPL(bmc150_accel_core_probe); -struct i2c_client *bmc150_get_second_device(struct i2c_client *client) -{ - struct bmc150_accel_data *data = i2c_get_clientdata(client); - - if (!data) - return NULL; - - return data->second_device; -} -EXPORT_SYMBOL_GPL(bmc150_get_second_device); - -void bmc150_set_second_device(struct i2c_client *client) -{ - struct bmc150_accel_data *data = i2c_get_clientdata(client); - - if (data) - data->second_device = client; -} -EXPORT_SYMBOL_GPL(bmc150_set_second_device); - int bmc150_accel_core_remove(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); @@ -1836,7 +1758,6 @@ int bmc150_accel_core_remove(struct device *dev) pm_runtime_disable(dev); pm_runtime_set_suspended(dev); - pm_runtime_put_noidle(dev); bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1); @@ -1876,6 +1797,9 @@ static int bmc150_accel_resume(struct device *dev) bmc150_accel_fifo_set_mode(data); mutex_unlock(&data->mutex); + if (data->resume_callback) + data->resume_callback(dev); + return 0; } #endif diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c index 69f709319484..999495f0669d 100644 --- a/drivers/iio/accel/bmc150-accel-i2c.c +++ b/drivers/iio/accel/bmc150-accel-i2c.c @@ -1,14 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * 3-axis accelerometer driver supporting following I2C Bosch-Sensortec chips: - * - BMC150 - * - BMI055 - * - BMA255 - * - BMA250E - * - BMA222 - * - BMA222E - * - BMA280 - * + * 3-axis accelerometer driver supporting many I2C Bosch-Sensortec chips * Copyright (c) 2014, Intel Corporation. */ @@ -21,6 +13,164 @@ #include "bmc150-accel.h" +#ifdef CONFIG_ACPI +static const struct acpi_device_id bmc150_acpi_dual_accel_ids[] = { + {"BOSC0200"}, + {"DUAL250E"}, + { } +}; + +/* + * The DUAL250E ACPI device for 360° hinges type 2-in-1s with 1 accelerometer + * in the display and 1 in the hinge has an ACPI-method (DSM) to tell the + * ACPI code about the angle between the 2 halves. This will make the ACPI + * code enable/disable the keyboard and touchpad. We need to call this to avoid + * the keyboard being disabled when the 2-in-1 is turned-on or resumed while + * fully folded into tablet mode (which gets detected with a HALL-sensor). + * If we don't call this then the keyboard won't work even when the 2-in-1 is + * changed to be used in laptop mode after the power-on / resume. + * + * This DSM takes 2 angles, selected by setting aux0 to 0 or 1, these presumably + * define the angle between the gravity vector measured by the accelerometer in + * the display (aux0=0) resp. the base (aux0=1) and some reference vector. + * The 2 angles get subtracted from each other so the reference vector does + * not matter and we can simply leave the second angle at 0. + */ + +#define BMC150_DSM_GUID "7681541e-8827-4239-8d9d-36be7fe12542" +#define DUAL250E_SET_ANGLE_FN_INDEX 3 + +struct dual250e_set_angle_args { + u32 aux0; + u32 ang0; + u32 rawx; + u32 rawy; + u32 rawz; +} __packed; + +static bool bmc150_acpi_set_angle_dsm(struct i2c_client *client, u32 aux0, u32 ang0) +{ + struct acpi_device *adev = ACPI_COMPANION(&client->dev); + struct dual250e_set_angle_args args = { + .aux0 = aux0, + .ang0 = ang0, + }; + union acpi_object args_obj, *obj; + guid_t guid; + + if (!acpi_dev_hid_uid_match(adev, "DUAL250E", NULL)) + return false; + + guid_parse(BMC150_DSM_GUID, &guid); + + if (!acpi_check_dsm(adev->handle, &guid, 0, BIT(DUAL250E_SET_ANGLE_FN_INDEX))) + return false; + + /* + * Note this triggers the following warning: + * "ACPI Warning: \_SB.PCI0.I2C2.ACC1._DSM: Argument #4 type mismatch - + * Found [Buffer], ACPI requires [Package]" + * This is unavoidable since the _DSM implementation expects a "naked" + * buffer, so wrapping it in a package will _not_ work. + */ + args_obj.type = ACPI_TYPE_BUFFER; + args_obj.buffer.length = sizeof(args); + args_obj.buffer.pointer = (u8 *)&args; + + obj = acpi_evaluate_dsm(adev->handle, &guid, 0, DUAL250E_SET_ANGLE_FN_INDEX, &args_obj); + if (!obj) { + dev_err(&client->dev, "Failed to call DSM to enable keyboard and touchpad\n"); + return false; + } + + ACPI_FREE(obj); + return true; +} + +static bool bmc150_acpi_enable_keyboard(struct i2c_client *client) +{ + /* + * The EC must see a change for it to re-enable the kbd, so first + * set the angle to 270° (tent/stand mode) and then change it to + * 90° (laptop mode). + */ + if (!bmc150_acpi_set_angle_dsm(client, 0, 270)) + return false; + + /* The EC needs some time to notice the angle being changed */ + msleep(100); + + return bmc150_acpi_set_angle_dsm(client, 0, 90); +} + +static void bmc150_acpi_resume_work(struct work_struct *work) +{ + struct bmc150_accel_data *data = + container_of(work, struct bmc150_accel_data, resume_work.work); + + bmc150_acpi_enable_keyboard(data->second_device); +} + +static void bmc150_acpi_resume_handler(struct device *dev) +{ + struct bmc150_accel_data *data = iio_priv(dev_get_drvdata(dev)); + + /* + * Delay the bmc150_acpi_enable_keyboard() call till after the system + * resume has completed, otherwise it will not work. + */ + schedule_delayed_work(&data->resume_work, msecs_to_jiffies(1000)); +} + +/* + * Some acpi_devices describe 2 accelerometers in a single ACPI device, + * try instantiating a second i2c_client for an I2cSerialBusV2 ACPI resource + * with index 1. + */ +static void bmc150_acpi_dual_accel_probe(struct i2c_client *client) +{ + struct bmc150_accel_data *data = iio_priv(i2c_get_clientdata(client)); + struct acpi_device *adev = ACPI_COMPANION(&client->dev); + char dev_name[16]; + struct i2c_board_info board_info = { + .type = "bmc150_accel", + .dev_name = dev_name, + .fwnode = client->dev.fwnode, + }; + + if (acpi_match_device_ids(adev, bmc150_acpi_dual_accel_ids)) + return; + + /* + * The 2nd accel sits in the base of 2-in-1s. The suffix is static, as + * there should never be more then 1 ACPI node with 2 accelerometers. + */ + snprintf(dev_name, sizeof(dev_name), "%s:base", acpi_device_hid(adev)); + + board_info.irq = acpi_dev_gpio_irq_get(adev, 1); + + data->second_device = i2c_acpi_new_device(&client->dev, 1, &board_info); + + if (!IS_ERR(data->second_device) && bmc150_acpi_enable_keyboard(data->second_device)) { + INIT_DELAYED_WORK(&data->resume_work, bmc150_acpi_resume_work); + data->resume_callback = bmc150_acpi_resume_handler; + } +} + +static void bmc150_acpi_dual_accel_remove(struct i2c_client *client) +{ + struct bmc150_accel_data *data = iio_priv(i2c_get_clientdata(client)); + + if (data->resume_callback) + cancel_delayed_work_sync(&data->resume_work); + + i2c_unregister_device(data->second_device); +} +#else +static void bmc150_acpi_dual_accel_probe(struct i2c_client *client) {} +static void bmc150_acpi_dual_accel_remove(struct i2c_client *client) {} +#endif + static int bmc150_accel_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -30,7 +180,6 @@ static int bmc150_accel_probe(struct i2c_client *client, i2c_check_functionality(client->adapter, I2C_FUNC_I2C) || i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK); - struct acpi_device __maybe_unused *adev; int ret; regmap = devm_regmap_init_i2c(client, &bmc150_regmap_conf); @@ -47,80 +196,62 @@ static int bmc150_accel_probe(struct i2c_client *client, return ret; /* - * Some BOSC0200 acpi_devices describe 2 accelerometers in a single ACPI - * device, try instantiating a second i2c_client for an I2cSerialBusV2 - * ACPI resource with index 1. The !id check avoids recursion when - * bmc150_accel_probe() gets called for the second client. + * The !id check avoids recursion when probe() gets called + * for the second client. */ -#ifdef CONFIG_ACPI - adev = ACPI_COMPANION(&client->dev); - if (!id && adev && strcmp(acpi_device_hid(adev), "BOSC0200") == 0) { - struct i2c_board_info board_info = { - .type = "bmc150_accel", - /* - * The 2nd accel sits in the base of 2-in-1s. Note this - * name is static, as there should never be more then 1 - * BOSC0200 ACPI node with 2 accelerometers in it. - */ - .dev_name = "BOSC0200:base", - .fwnode = client->dev.fwnode, - .irq = -ENOENT, - }; - struct i2c_client *second_dev; - - second_dev = i2c_acpi_new_device(&client->dev, 1, &board_info); - if (!IS_ERR(second_dev)) - bmc150_set_second_device(second_dev); - } -#endif + if (!id && has_acpi_companion(&client->dev)) + bmc150_acpi_dual_accel_probe(client); return 0; } static int bmc150_accel_remove(struct i2c_client *client) { - struct i2c_client *second_dev = bmc150_get_second_device(client); - - i2c_unregister_device(second_dev); + bmc150_acpi_dual_accel_remove(client); return bmc150_accel_core_remove(&client->dev); } static const struct acpi_device_id bmc150_accel_acpi_match[] = { - {"BSBA0150", bmc150}, - {"BMC150A", bmc150}, - {"BMI055A", bmi055}, - {"BMA0255", bma255}, - {"BMA250E", bma250e}, - {"BMA222", bma222}, - {"BMA222E", bma222e}, - {"BMA0280", bma280}, + {"BMA0255"}, + {"BMA0280"}, + {"BMA222"}, + {"BMA222E"}, + {"BMA250E"}, + {"BMC150A"}, + {"BMI055A"}, {"BOSC0200"}, + {"BSBA0150"}, + {"DUAL250E"}, { }, }; MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match); static const struct i2c_device_id bmc150_accel_id[] = { - {"bmc150_accel", bmc150}, - {"bmi055_accel", bmi055}, - {"bma255", bma255}, - {"bma250e", bma250e}, - {"bma222", bma222}, - {"bma222e", bma222e}, - {"bma280", bma280}, + {"bma222"}, + {"bma222e"}, + {"bma250e"}, + {"bma253"}, + {"bma254"}, + {"bma255"}, + {"bma280"}, + {"bmc150_accel"}, + {"bmi055_accel"}, {} }; MODULE_DEVICE_TABLE(i2c, bmc150_accel_id); static const struct of_device_id bmc150_accel_of_match[] = { - { .compatible = "bosch,bmc150_accel" }, - { .compatible = "bosch,bmi055_accel" }, - { .compatible = "bosch,bma255" }, - { .compatible = "bosch,bma250e" }, { .compatible = "bosch,bma222" }, { .compatible = "bosch,bma222e" }, + { .compatible = "bosch,bma250e" }, + { .compatible = "bosch,bma253" }, + { .compatible = "bosch,bma254" }, + { .compatible = "bosch,bma255" }, { .compatible = "bosch,bma280" }, + { .compatible = "bosch,bmc150_accel" }, + { .compatible = "bosch,bmi055_accel" }, { }, }; MODULE_DEVICE_TABLE(of, bmc150_accel_of_match); diff --git a/drivers/iio/accel/bmc150-accel-spi.c b/drivers/iio/accel/bmc150-accel-spi.c index 74a8aee4f612..54b8c9c8068b 100644 --- a/drivers/iio/accel/bmc150-accel-spi.c +++ b/drivers/iio/accel/bmc150-accel-spi.c @@ -34,26 +34,27 @@ static int bmc150_accel_remove(struct spi_device *spi) } static const struct acpi_device_id bmc150_accel_acpi_match[] = { - {"BSBA0150", bmc150}, - {"BMC150A", bmc150}, - {"BMI055A", bmi055}, - {"BMA0255", bma255}, - {"BMA250E", bma250e}, - {"BMA222", bma222}, - {"BMA222E", bma222e}, - {"BMA0280", bma280}, + {"BMA0255"}, + {"BMA0280"}, + {"BMA222"}, + {"BMA222E"}, + {"BMA250E"}, + {"BMC150A"}, + {"BMI055A"}, + {"BSBA0150"}, { }, }; MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match); static const struct spi_device_id bmc150_accel_id[] = { - {"bmc150_accel", bmc150}, - {"bmi055_accel", bmi055}, - {"bma255", bma255}, - {"bma250e", bma250e}, - {"bma222", bma222}, - {"bma222e", bma222e}, - {"bma280", bma280}, + {"bma222"}, + {"bma222e"}, + {"bma250e"}, + {"bma253"}, + {"bma255"}, + {"bma280"}, + {"bmc150_accel"}, + {"bmi055_accel"}, {} }; MODULE_DEVICE_TABLE(spi, bmc150_accel_id); diff --git a/drivers/iio/accel/bmc150-accel.h b/drivers/iio/accel/bmc150-accel.h index 6024f15b9700..47121f070fe9 100644 --- a/drivers/iio/accel/bmc150-accel.h +++ b/drivers/iio/accel/bmc150-accel.h @@ -2,23 +2,75 @@ #ifndef _BMC150_ACCEL_H_ #define _BMC150_ACCEL_H_ +#include <linux/atomic.h> +#include <linux/iio/iio.h> +#include <linux/mutex.h> +#include <linux/regulator/consumer.h> +#include <linux/workqueue.h> + struct regmap; +struct i2c_client; +struct bmc150_accel_chip_info; +struct bmc150_accel_interrupt_info; + +struct bmc150_accel_interrupt { + const struct bmc150_accel_interrupt_info *info; + atomic_t users; +}; + +struct bmc150_accel_trigger { + struct bmc150_accel_data *data; + struct iio_trigger *indio_trig; + int (*setup)(struct bmc150_accel_trigger *t, bool state); + int intr; + bool enabled; +}; + +enum bmc150_accel_interrupt_id { + BMC150_ACCEL_INT_DATA_READY, + BMC150_ACCEL_INT_ANY_MOTION, + BMC150_ACCEL_INT_WATERMARK, + BMC150_ACCEL_INTERRUPTS, +}; + +enum bmc150_accel_trigger_id { + BMC150_ACCEL_TRIGGER_DATA_READY, + BMC150_ACCEL_TRIGGER_ANY_MOTION, + BMC150_ACCEL_TRIGGERS, +}; -enum { - bmc150, - bmi055, - bma255, - bma250e, - bma222, - bma222e, - bma280, +struct bmc150_accel_data { + struct regmap *regmap; + struct regulator_bulk_data regulators[2]; + struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS]; + struct bmc150_accel_trigger triggers[BMC150_ACCEL_TRIGGERS]; + struct mutex mutex; + u8 fifo_mode, watermark; + s16 buffer[8]; + /* + * Ensure there is sufficient space and correct alignment for + * the timestamp if enabled + */ + struct { + __le16 channels[3]; + s64 ts __aligned(8); + } scan; + u8 bw_bits; + u32 slope_dur; + u32 slope_thres; + u32 range; + int ev_enable_state; + int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */ + const struct bmc150_accel_chip_info *chip_info; + struct i2c_client *second_device; + void (*resume_callback)(struct device *dev); + struct delayed_work resume_work; + struct iio_mount_matrix orientation; }; int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, const char *name, bool block_supported); int bmc150_accel_core_remove(struct device *dev); -struct i2c_client *bmc150_get_second_device(struct i2c_client *second_device); -void bmc150_set_second_device(struct i2c_client *second_device); extern const struct dev_pm_ops bmc150_accel_pm_ops; extern const struct regmap_config bmc150_regmap_conf; diff --git a/drivers/iio/accel/bmi088-accel-core.c b/drivers/iio/accel/bmi088-accel-core.c index 12d00658e46f..a06dae5c971d 100644 --- a/drivers/iio/accel/bmi088-accel-core.c +++ b/drivers/iio/accel/bmi088-accel-core.c @@ -285,11 +285,17 @@ static int bmi088_accel_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_RAW: switch (chan->type) { case IIO_TEMP: - pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret) + return ret; + ret = bmi088_accel_get_temp(data, val); goto out_read_raw_pm_put; case IIO_ACCEL: - pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret) + return ret; + ret = iio_device_claim_direct_mode(indio_dev); if (ret) goto out_read_raw_pm_put; @@ -319,7 +325,10 @@ static int bmi088_accel_read_raw(struct iio_dev *indio_dev, *val = BMI088_ACCEL_TEMP_UNIT; return IIO_VAL_INT; case IIO_ACCEL: - pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret) + return ret; + ret = regmap_read(data->regmap, BMI088_ACCEL_REG_ACC_RANGE, val); if (ret) @@ -334,7 +343,10 @@ static int bmi088_accel_read_raw(struct iio_dev *indio_dev, return -EINVAL; } case IIO_CHAN_INFO_SAMP_FREQ: - pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret) + return ret; + ret = bmi088_accel_get_sample_freq(data, val, val2); goto out_read_raw_pm_put; default: @@ -376,7 +388,10 @@ static int bmi088_accel_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: - pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret) + return ret; + ret = bmi088_accel_set_sample_freq(data, val); pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); @@ -496,7 +511,6 @@ int bmi088_accel_core_probe(struct device *dev, struct regmap *regmap, if (ret) return ret; - indio_dev->dev.parent = dev; indio_dev->channels = data->chip_info->channels; indio_dev->num_channels = data->chip_info->num_channels; indio_dev->name = name ? name : data->chip_info->name; @@ -531,7 +545,6 @@ int bmi088_accel_core_remove(struct device *dev) pm_runtime_disable(dev); pm_runtime_set_suspended(dev); - pm_runtime_put_noidle(dev); bmi088_accel_power_down(data); return 0; diff --git a/drivers/iio/accel/fxls8962af-core.c b/drivers/iio/accel/fxls8962af-core.c new file mode 100644 index 000000000000..078d87865fde --- /dev/null +++ b/drivers/iio/accel/fxls8962af-core.c @@ -0,0 +1,968 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * NXP FXLS8962AF/FXLS8964AF Accelerometer Core Driver + * + * Copyright 2021 Connected Cars A/S + * + * Datasheet: + * https://www.nxp.com/docs/en/data-sheet/FXLS8962AF.pdf + * https://www.nxp.com/docs/en/data-sheet/FXLS8964AF.pdf + * + * Errata: + * https://www.nxp.com/docs/en/errata/ES_FXLS8962AF.pdf + */ + +#include <linux/bits.h> +#include <linux/bitfield.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/of_irq.h> +#include <linux/pm_runtime.h> +#include <linux/regulator/consumer.h> +#include <linux/regmap.h> + +#include <linux/iio/buffer.h> +#include <linux/iio/iio.h> +#include <linux/iio/kfifo_buf.h> +#include <linux/iio/sysfs.h> + +#include "fxls8962af.h" + +#define FXLS8962AF_INT_STATUS 0x00 +#define FXLS8962AF_INT_STATUS_SRC_BOOT BIT(0) +#define FXLS8962AF_INT_STATUS_SRC_BUF BIT(5) +#define FXLS8962AF_INT_STATUS_SRC_DRDY BIT(7) +#define FXLS8962AF_TEMP_OUT 0x01 +#define FXLS8962AF_VECM_LSB 0x02 +#define FXLS8962AF_OUT_X_LSB 0x04 +#define FXLS8962AF_OUT_Y_LSB 0x06 +#define FXLS8962AF_OUT_Z_LSB 0x08 +#define FXLS8962AF_BUF_STATUS 0x0b +#define FXLS8962AF_BUF_STATUS_BUF_CNT GENMASK(5, 0) +#define FXLS8962AF_BUF_STATUS_BUF_OVF BIT(6) +#define FXLS8962AF_BUF_STATUS_BUF_WMRK BIT(7) +#define FXLS8962AF_BUF_X_LSB 0x0c +#define FXLS8962AF_BUF_Y_LSB 0x0e +#define FXLS8962AF_BUF_Z_LSB 0x10 + +#define FXLS8962AF_PROD_REV 0x12 +#define FXLS8962AF_WHO_AM_I 0x13 + +#define FXLS8962AF_SYS_MODE 0x14 +#define FXLS8962AF_SENS_CONFIG1 0x15 +#define FXLS8962AF_SENS_CONFIG1_ACTIVE BIT(0) +#define FXLS8962AF_SENS_CONFIG1_RST BIT(7) +#define FXLS8962AF_SC1_FSR_MASK GENMASK(2, 1) +#define FXLS8962AF_SC1_FSR_PREP(x) FIELD_PREP(FXLS8962AF_SC1_FSR_MASK, (x)) +#define FXLS8962AF_SC1_FSR_GET(x) FIELD_GET(FXLS8962AF_SC1_FSR_MASK, (x)) + +#define FXLS8962AF_SENS_CONFIG2 0x16 +#define FXLS8962AF_SENS_CONFIG3 0x17 +#define FXLS8962AF_SC3_WAKE_ODR_MASK GENMASK(7, 4) +#define FXLS8962AF_SC3_WAKE_ODR_PREP(x) FIELD_PREP(FXLS8962AF_SC3_WAKE_ODR_MASK, (x)) +#define FXLS8962AF_SC3_WAKE_ODR_GET(x) FIELD_GET(FXLS8962AF_SC3_WAKE_ODR_MASK, (x)) +#define FXLS8962AF_SENS_CONFIG4 0x18 +#define FXLS8962AF_SC4_INT_PP_OD_MASK BIT(1) +#define FXLS8962AF_SC4_INT_PP_OD_PREP(x) FIELD_PREP(FXLS8962AF_SC4_INT_PP_OD_MASK, (x)) +#define FXLS8962AF_SC4_INT_POL_MASK BIT(0) +#define FXLS8962AF_SC4_INT_POL_PREP(x) FIELD_PREP(FXLS8962AF_SC4_INT_POL_MASK, (x)) +#define FXLS8962AF_SENS_CONFIG5 0x19 + +#define FXLS8962AF_WAKE_IDLE_LSB 0x1b +#define FXLS8962AF_SLEEP_IDLE_LSB 0x1c +#define FXLS8962AF_ASLP_COUNT_LSB 0x1e + +#define FXLS8962AF_INT_EN 0x20 +#define FXLS8962AF_INT_EN_BUF_EN BIT(6) +#define FXLS8962AF_INT_PIN_SEL 0x21 +#define FXLS8962AF_INT_PIN_SEL_MASK GENMASK(7, 0) +#define FXLS8962AF_INT_PIN_SEL_INT1 0x00 +#define FXLS8962AF_INT_PIN_SEL_INT2 GENMASK(7, 0) + +#define FXLS8962AF_OFF_X 0x22 +#define FXLS8962AF_OFF_Y 0x23 +#define FXLS8962AF_OFF_Z 0x24 + +#define FXLS8962AF_BUF_CONFIG1 0x26 +#define FXLS8962AF_BC1_BUF_MODE_MASK GENMASK(6, 5) +#define FXLS8962AF_BC1_BUF_MODE_PREP(x) FIELD_PREP(FXLS8962AF_BC1_BUF_MODE_MASK, (x)) +#define FXLS8962AF_BUF_CONFIG2 0x27 +#define FXLS8962AF_BUF_CONFIG2_BUF_WMRK GENMASK(5, 0) + +#define FXLS8962AF_ORIENT_STATUS 0x28 +#define FXLS8962AF_ORIENT_CONFIG 0x29 +#define FXLS8962AF_ORIENT_DBCOUNT 0x2a +#define FXLS8962AF_ORIENT_BF_ZCOMP 0x2b +#define FXLS8962AF_ORIENT_THS_REG 0x2c + +#define FXLS8962AF_SDCD_INT_SRC1 0x2d +#define FXLS8962AF_SDCD_INT_SRC2 0x2e +#define FXLS8962AF_SDCD_CONFIG1 0x2f +#define FXLS8962AF_SDCD_CONFIG2 0x30 +#define FXLS8962AF_SDCD_OT_DBCNT 0x31 +#define FXLS8962AF_SDCD_WT_DBCNT 0x32 +#define FXLS8962AF_SDCD_LTHS_LSB 0x33 +#define FXLS8962AF_SDCD_UTHS_LSB 0x35 + +#define FXLS8962AF_SELF_TEST_CONFIG1 0x37 +#define FXLS8962AF_SELF_TEST_CONFIG2 0x38 + +#define FXLS8962AF_MAX_REG 0x38 + +#define FXLS8962AF_DEVICE_ID 0x62 +#define FXLS8964AF_DEVICE_ID 0x84 + +/* Raw temp channel offset */ +#define FXLS8962AF_TEMP_CENTER_VAL 25 + +#define FXLS8962AF_AUTO_SUSPEND_DELAY_MS 2000 + +#define FXLS8962AF_FIFO_LENGTH 32 +#define FXLS8962AF_SCALE_TABLE_LEN 4 +#define FXLS8962AF_SAMP_FREQ_TABLE_LEN 13 + +static const int fxls8962af_scale_table[FXLS8962AF_SCALE_TABLE_LEN][2] = { + {0, IIO_G_TO_M_S_2(980000)}, + {0, IIO_G_TO_M_S_2(1950000)}, + {0, IIO_G_TO_M_S_2(3910000)}, + {0, IIO_G_TO_M_S_2(7810000)}, +}; + +static const int fxls8962af_samp_freq_table[FXLS8962AF_SAMP_FREQ_TABLE_LEN][2] = { + {3200, 0}, {1600, 0}, {800, 0}, {400, 0}, {200, 0}, {100, 0}, + {50, 0}, {25, 0}, {12, 500000}, {6, 250000}, {3, 125000}, + {1, 563000}, {0, 781000}, +}; + +struct fxls8962af_chip_info { + const char *name; + const struct iio_chan_spec *channels; + int num_channels; + u8 chip_id; +}; + +struct fxls8962af_data { + struct regmap *regmap; + const struct fxls8962af_chip_info *chip_info; + struct regulator *vdd_reg; + struct { + __le16 channels[3]; + s64 ts __aligned(8); + } scan; + int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */ + struct iio_mount_matrix orientation; + u8 watermark; +}; + +const struct regmap_config fxls8962af_regmap_conf = { + .reg_bits = 8, + .val_bits = 8, + .max_register = FXLS8962AF_MAX_REG, +}; +EXPORT_SYMBOL_GPL(fxls8962af_regmap_conf); + +enum { + fxls8962af_idx_x, + fxls8962af_idx_y, + fxls8962af_idx_z, + fxls8962af_idx_ts, +}; + +enum fxls8962af_int_pin { + FXLS8962AF_PIN_INT1, + FXLS8962AF_PIN_INT2, +}; + +static int fxls8962af_power_on(struct fxls8962af_data *data) +{ + struct device *dev = regmap_get_device(data->regmap); + int ret; + + ret = pm_runtime_resume_and_get(dev); + if (ret) + dev_err(dev, "failed to power on\n"); + + return ret; +} + +static int fxls8962af_power_off(struct fxls8962af_data *data) +{ + struct device *dev = regmap_get_device(data->regmap); + int ret; + + pm_runtime_mark_last_busy(dev); + ret = pm_runtime_put_autosuspend(dev); + if (ret) + dev_err(dev, "failed to power off\n"); + + return ret; +} + +static int fxls8962af_standby(struct fxls8962af_data *data) +{ + return regmap_update_bits(data->regmap, FXLS8962AF_SENS_CONFIG1, + FXLS8962AF_SENS_CONFIG1_ACTIVE, 0); +} + +static int fxls8962af_active(struct fxls8962af_data *data) +{ + return regmap_update_bits(data->regmap, FXLS8962AF_SENS_CONFIG1, + FXLS8962AF_SENS_CONFIG1_ACTIVE, 1); +} + +static int fxls8962af_is_active(struct fxls8962af_data *data) +{ + unsigned int reg; + int ret; + + ret = regmap_read(data->regmap, FXLS8962AF_SENS_CONFIG1, ®); + if (ret) + return ret; + + return reg & FXLS8962AF_SENS_CONFIG1_ACTIVE; +} + +static int fxls8962af_get_out(struct fxls8962af_data *data, + struct iio_chan_spec const *chan, int *val) +{ + struct device *dev = regmap_get_device(data->regmap); + __le16 raw_val; + int is_active; + int ret; + + is_active = fxls8962af_is_active(data); + if (!is_active) { + ret = fxls8962af_power_on(data); + if (ret) + return ret; + } + + ret = regmap_bulk_read(data->regmap, chan->address, + &raw_val, (chan->scan_type.storagebits / 8)); + + if (!is_active) + fxls8962af_power_off(data); + + if (ret) { + dev_err(dev, "failed to get out reg 0x%lx\n", chan->address); + return ret; + } + + *val = sign_extend32(le16_to_cpu(raw_val), + chan->scan_type.realbits - 1); + + return IIO_VAL_INT; +} + +static int fxls8962af_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SCALE: + *type = IIO_VAL_INT_PLUS_NANO; + *vals = (int *)fxls8962af_scale_table; + *length = ARRAY_SIZE(fxls8962af_scale_table) * 2; + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_SAMP_FREQ: + *type = IIO_VAL_INT_PLUS_MICRO; + *vals = (int *)fxls8962af_samp_freq_table; + *length = ARRAY_SIZE(fxls8962af_samp_freq_table) * 2; + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + +static int fxls8962af_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SCALE: + return IIO_VAL_INT_PLUS_NANO; + case IIO_CHAN_INFO_SAMP_FREQ: + return IIO_VAL_INT_PLUS_MICRO; + default: + return IIO_VAL_INT_PLUS_NANO; + } +} + +static int fxls8962af_update_config(struct fxls8962af_data *data, u8 reg, + u8 mask, u8 val) +{ + int ret; + int is_active; + + is_active = fxls8962af_is_active(data); + if (is_active) { + ret = fxls8962af_standby(data); + if (ret) + return ret; + } + + ret = regmap_update_bits(data->regmap, reg, mask, val); + if (ret) + return ret; + + if (is_active) { + ret = fxls8962af_active(data); + if (ret) + return ret; + } + + return 0; +} + +static int fxls8962af_set_full_scale(struct fxls8962af_data *data, u32 scale) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(fxls8962af_scale_table); i++) + if (scale == fxls8962af_scale_table[i][1]) + break; + + if (i == ARRAY_SIZE(fxls8962af_scale_table)) + return -EINVAL; + + return fxls8962af_update_config(data, FXLS8962AF_SENS_CONFIG1, + FXLS8962AF_SC1_FSR_MASK, + FXLS8962AF_SC1_FSR_PREP(i)); +} + +static unsigned int fxls8962af_read_full_scale(struct fxls8962af_data *data, + int *val) +{ + int ret; + unsigned int reg; + u8 range_idx; + + ret = regmap_read(data->regmap, FXLS8962AF_SENS_CONFIG1, ®); + if (ret) + return ret; + + range_idx = FXLS8962AF_SC1_FSR_GET(reg); + + *val = fxls8962af_scale_table[range_idx][1]; + + return IIO_VAL_INT_PLUS_NANO; +} + +static int fxls8962af_set_samp_freq(struct fxls8962af_data *data, u32 val, + u32 val2) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(fxls8962af_samp_freq_table); i++) + if (val == fxls8962af_samp_freq_table[i][0] && + val2 == fxls8962af_samp_freq_table[i][1]) + break; + + if (i == ARRAY_SIZE(fxls8962af_samp_freq_table)) + return -EINVAL; + + return fxls8962af_update_config(data, FXLS8962AF_SENS_CONFIG3, + FXLS8962AF_SC3_WAKE_ODR_MASK, + FXLS8962AF_SC3_WAKE_ODR_PREP(i)); +} + +static unsigned int fxls8962af_read_samp_freq(struct fxls8962af_data *data, + int *val, int *val2) +{ + int ret; + unsigned int reg; + u8 range_idx; + + ret = regmap_read(data->regmap, FXLS8962AF_SENS_CONFIG3, ®); + if (ret) + return ret; + + range_idx = FXLS8962AF_SC3_WAKE_ODR_GET(reg); + + *val = fxls8962af_samp_freq_table[range_idx][0]; + *val2 = fxls8962af_samp_freq_table[range_idx][1]; + + return IIO_VAL_INT_PLUS_MICRO; +} + +static int fxls8962af_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct fxls8962af_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_TEMP: + case IIO_ACCEL: + return fxls8962af_get_out(data, chan, val); + default: + return -EINVAL; + } + case IIO_CHAN_INFO_OFFSET: + if (chan->type != IIO_TEMP) + return -EINVAL; + + *val = FXLS8962AF_TEMP_CENTER_VAL; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + return fxls8962af_read_full_scale(data, val2); + case IIO_CHAN_INFO_SAMP_FREQ: + return fxls8962af_read_samp_freq(data, val, val2); + default: + return -EINVAL; + } +} + +static int fxls8962af_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct fxls8962af_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + if (val != 0) + return -EINVAL; + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = fxls8962af_set_full_scale(data, val2); + + iio_device_release_direct_mode(indio_dev); + return ret; + case IIO_CHAN_INFO_SAMP_FREQ: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = fxls8962af_set_samp_freq(data, val, val2); + + iio_device_release_direct_mode(indio_dev); + return ret; + default: + return -EINVAL; + } +} + +static int fxls8962af_set_watermark(struct iio_dev *indio_dev, unsigned val) +{ + struct fxls8962af_data *data = iio_priv(indio_dev); + + if (val > FXLS8962AF_FIFO_LENGTH) + val = FXLS8962AF_FIFO_LENGTH; + + data->watermark = val; + + return 0; +} + +#define FXLS8962AF_CHANNEL(axis, reg, idx) { \ + .type = IIO_ACCEL, \ + .address = reg, \ + .modified = 1, \ + .channel2 = IIO_MOD_##axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = idx, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 12, \ + .storagebits = 16, \ + .shift = 4, \ + .endianness = IIO_BE, \ + }, \ +} + +#define FXLS8962AF_TEMP_CHANNEL { \ + .type = IIO_TEMP, \ + .address = FXLS8962AF_TEMP_OUT, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_OFFSET),\ + .scan_index = -1, \ + .scan_type = { \ + .realbits = 8, \ + .storagebits = 8, \ + }, \ +} + +static const struct iio_chan_spec fxls8962af_channels[] = { + FXLS8962AF_CHANNEL(X, FXLS8962AF_OUT_X_LSB, fxls8962af_idx_x), + FXLS8962AF_CHANNEL(Y, FXLS8962AF_OUT_Y_LSB, fxls8962af_idx_y), + FXLS8962AF_CHANNEL(Z, FXLS8962AF_OUT_Z_LSB, fxls8962af_idx_z), + IIO_CHAN_SOFT_TIMESTAMP(fxls8962af_idx_ts), + FXLS8962AF_TEMP_CHANNEL, +}; + +static const struct fxls8962af_chip_info fxls_chip_info_table[] = { + [fxls8962af] = { + .chip_id = FXLS8962AF_DEVICE_ID, + .name = "fxls8962af", + .channels = fxls8962af_channels, + .num_channels = ARRAY_SIZE(fxls8962af_channels), + }, + [fxls8964af] = { + .chip_id = FXLS8964AF_DEVICE_ID, + .name = "fxls8964af", + .channels = fxls8962af_channels, + .num_channels = ARRAY_SIZE(fxls8962af_channels), + }, +}; + +static const struct iio_info fxls8962af_info = { + .read_raw = &fxls8962af_read_raw, + .write_raw = &fxls8962af_write_raw, + .write_raw_get_fmt = fxls8962af_write_raw_get_fmt, + .read_avail = fxls8962af_read_avail, + .hwfifo_set_watermark = fxls8962af_set_watermark, +}; + +static int fxls8962af_reset(struct fxls8962af_data *data) +{ + struct device *dev = regmap_get_device(data->regmap); + unsigned int reg; + int ret; + + ret = regmap_update_bits(data->regmap, FXLS8962AF_SENS_CONFIG1, + FXLS8962AF_SENS_CONFIG1_RST, + FXLS8962AF_SENS_CONFIG1_RST); + if (ret) + return ret; + + /* TBOOT1, TBOOT2, specifies we have to wait between 1 - 17.7ms */ + ret = regmap_read_poll_timeout(data->regmap, FXLS8962AF_INT_STATUS, reg, + (reg & FXLS8962AF_INT_STATUS_SRC_BOOT), + 1000, 18000); + if (ret == -ETIMEDOUT) + dev_err(dev, "reset timeout, int_status = 0x%x\n", reg); + + return ret; +} + +static int __fxls8962af_fifo_set_mode(struct fxls8962af_data *data, bool onoff) +{ + int ret; + + /* Enable watermark at max fifo size */ + ret = regmap_update_bits(data->regmap, FXLS8962AF_BUF_CONFIG2, + FXLS8962AF_BUF_CONFIG2_BUF_WMRK, + data->watermark); + if (ret) + return ret; + + return regmap_update_bits(data->regmap, FXLS8962AF_BUF_CONFIG1, + FXLS8962AF_BC1_BUF_MODE_MASK, + FXLS8962AF_BC1_BUF_MODE_PREP(onoff)); +} + +static int fxls8962af_buffer_preenable(struct iio_dev *indio_dev) +{ + return fxls8962af_power_on(iio_priv(indio_dev)); +} + +static int fxls8962af_buffer_postenable(struct iio_dev *indio_dev) +{ + struct fxls8962af_data *data = iio_priv(indio_dev); + int ret; + + fxls8962af_standby(data); + + /* Enable buffer interrupt */ + ret = regmap_update_bits(data->regmap, FXLS8962AF_INT_EN, + FXLS8962AF_INT_EN_BUF_EN, + FXLS8962AF_INT_EN_BUF_EN); + if (ret) + return ret; + + ret = __fxls8962af_fifo_set_mode(data, true); + + fxls8962af_active(data); + + return ret; +} + +static int fxls8962af_buffer_predisable(struct iio_dev *indio_dev) +{ + struct fxls8962af_data *data = iio_priv(indio_dev); + int ret; + + fxls8962af_standby(data); + + /* Disable buffer interrupt */ + ret = regmap_update_bits(data->regmap, FXLS8962AF_INT_EN, + FXLS8962AF_INT_EN_BUF_EN, 0); + if (ret) + return ret; + + ret = __fxls8962af_fifo_set_mode(data, false); + + fxls8962af_active(data); + + return ret; +} + +static int fxls8962af_buffer_postdisable(struct iio_dev *indio_dev) +{ + struct fxls8962af_data *data = iio_priv(indio_dev); + + return fxls8962af_power_off(data); +} + +static const struct iio_buffer_setup_ops fxls8962af_buffer_ops = { + .preenable = fxls8962af_buffer_preenable, + .postenable = fxls8962af_buffer_postenable, + .predisable = fxls8962af_buffer_predisable, + .postdisable = fxls8962af_buffer_postdisable, +}; + +static int fxls8962af_i2c_raw_read_errata3(struct fxls8962af_data *data, + u16 *buffer, int samples, + int sample_length) +{ + int i, ret; + + for (i = 0; i < samples; i++) { + ret = regmap_raw_read(data->regmap, FXLS8962AF_BUF_X_LSB, + &buffer[i * 3], sample_length); + if (ret) + return ret; + } + + return ret; +} + +static int fxls8962af_fifo_transfer(struct fxls8962af_data *data, + u16 *buffer, int samples) +{ + struct device *dev = regmap_get_device(data->regmap); + int sample_length = 3 * sizeof(*buffer); + int total_length = samples * sample_length; + int ret; + + if (i2c_verify_client(dev)) + /* + * Due to errata bug: + * E3: FIFO burst read operation error using I2C interface + * We have to avoid burst reads on I2C.. + */ + ret = fxls8962af_i2c_raw_read_errata3(data, buffer, samples, + sample_length); + else + ret = regmap_raw_read(data->regmap, FXLS8962AF_BUF_X_LSB, buffer, + total_length); + + if (ret) + dev_err(dev, "Error transferring data from fifo: %d\n", ret); + + return ret; +} + +static int fxls8962af_fifo_flush(struct iio_dev *indio_dev) +{ + struct fxls8962af_data *data = iio_priv(indio_dev); + struct device *dev = regmap_get_device(data->regmap); + u16 buffer[FXLS8962AF_FIFO_LENGTH * 3]; + uint64_t sample_period; + unsigned int reg; + int64_t tstamp; + int ret, i; + u8 count; + + ret = regmap_read(data->regmap, FXLS8962AF_BUF_STATUS, ®); + if (ret) + return ret; + + if (reg & FXLS8962AF_BUF_STATUS_BUF_OVF) { + dev_err(dev, "Buffer overflow"); + return -EOVERFLOW; + } + + count = reg & FXLS8962AF_BUF_STATUS_BUF_CNT; + if (!count) + return 0; + + data->old_timestamp = data->timestamp; + data->timestamp = iio_get_time_ns(indio_dev); + + /* + * Approximate timestamps for each of the sample based on the sampling, + * frequency, timestamp for last sample and number of samples. + */ + sample_period = (data->timestamp - data->old_timestamp); + do_div(sample_period, count); + tstamp = data->timestamp - (count - 1) * sample_period; + + ret = fxls8962af_fifo_transfer(data, buffer, count); + if (ret) + return ret; + + /* Demux hw FIFO into kfifo. */ + for (i = 0; i < count; i++) { + int j, bit; + + j = 0; + for_each_set_bit(bit, indio_dev->active_scan_mask, + indio_dev->masklength) { + memcpy(&data->scan.channels[j++], &buffer[i * 3 + bit], + sizeof(data->scan.channels[0])); + } + + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, + tstamp); + + tstamp += sample_period; + } + + return count; +} + +static irqreturn_t fxls8962af_interrupt(int irq, void *p) +{ + struct iio_dev *indio_dev = p; + struct fxls8962af_data *data = iio_priv(indio_dev); + unsigned int reg; + int ret; + + ret = regmap_read(data->regmap, FXLS8962AF_INT_STATUS, ®); + if (ret) + return IRQ_NONE; + + if (reg & FXLS8962AF_INT_STATUS_SRC_BUF) { + ret = fxls8962af_fifo_flush(indio_dev); + if (ret) + return IRQ_NONE; + + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static void fxls8962af_regulator_disable(void *data_ptr) +{ + struct fxls8962af_data *data = data_ptr; + + regulator_disable(data->vdd_reg); +} + +static void fxls8962af_pm_disable(void *dev_ptr) +{ + struct device *dev = dev_ptr; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_put_noidle(dev); + + fxls8962af_standby(iio_priv(indio_dev)); +} + +static void fxls8962af_get_irq(struct device_node *of_node, + enum fxls8962af_int_pin *pin) +{ + int irq; + + irq = of_irq_get_byname(of_node, "INT2"); + if (irq > 0) { + *pin = FXLS8962AF_PIN_INT2; + return; + } + + *pin = FXLS8962AF_PIN_INT1; +} + +static int fxls8962af_irq_setup(struct iio_dev *indio_dev, int irq) +{ + struct fxls8962af_data *data = iio_priv(indio_dev); + struct device *dev = regmap_get_device(data->regmap); + unsigned long irq_type; + bool irq_active_high; + enum fxls8962af_int_pin int_pin; + u8 int_pin_sel; + int ret; + + fxls8962af_get_irq(dev->of_node, &int_pin); + switch (int_pin) { + case FXLS8962AF_PIN_INT1: + int_pin_sel = FXLS8962AF_INT_PIN_SEL_INT1; + break; + case FXLS8962AF_PIN_INT2: + int_pin_sel = FXLS8962AF_INT_PIN_SEL_INT2; + break; + default: + dev_err(dev, "unsupported int pin selected\n"); + return -EINVAL; + } + + ret = regmap_update_bits(data->regmap, FXLS8962AF_INT_PIN_SEL, + FXLS8962AF_INT_PIN_SEL_MASK, int_pin_sel); + if (ret) + return ret; + + irq_type = irqd_get_trigger_type(irq_get_irq_data(irq)); + + switch (irq_type) { + case IRQF_TRIGGER_HIGH: + case IRQF_TRIGGER_RISING: + irq_active_high = true; + break; + case IRQF_TRIGGER_LOW: + case IRQF_TRIGGER_FALLING: + irq_active_high = false; + break; + default: + dev_info(dev, "mode %lx unsupported\n", irq_type); + return -EINVAL; + } + + ret = regmap_update_bits(data->regmap, FXLS8962AF_SENS_CONFIG4, + FXLS8962AF_SC4_INT_POL_MASK, + FXLS8962AF_SC4_INT_POL_PREP(irq_active_high)); + if (ret) + return ret; + + if (device_property_read_bool(dev, "drive-open-drain")) { + ret = regmap_update_bits(data->regmap, FXLS8962AF_SENS_CONFIG4, + FXLS8962AF_SC4_INT_PP_OD_MASK, + FXLS8962AF_SC4_INT_PP_OD_PREP(1)); + if (ret) + return ret; + + irq_type |= IRQF_SHARED; + } + + return devm_request_threaded_irq(dev, + irq, + NULL, fxls8962af_interrupt, + irq_type | IRQF_ONESHOT, + indio_dev->name, indio_dev); +} + +int fxls8962af_core_probe(struct device *dev, struct regmap *regmap, int irq) +{ + struct fxls8962af_data *data; + struct iio_dev *indio_dev; + unsigned int reg; + int ret, i; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + dev_set_drvdata(dev, indio_dev); + data->regmap = regmap; + + ret = iio_read_mount_matrix(dev, &data->orientation); + if (ret) + return ret; + + data->vdd_reg = devm_regulator_get(dev, "vdd"); + if (IS_ERR(data->vdd_reg)) + return dev_err_probe(dev, PTR_ERR(data->vdd_reg), + "Failed to get vdd regulator\n"); + + ret = regulator_enable(data->vdd_reg); + if (ret) { + dev_err(dev, "Failed to enable vdd regulator: %d\n", ret); + return ret; + } + + ret = devm_add_action_or_reset(dev, fxls8962af_regulator_disable, data); + if (ret) + return ret; + + ret = regmap_read(data->regmap, FXLS8962AF_WHO_AM_I, ®); + if (ret) + return ret; + + for (i = 0; i < ARRAY_SIZE(fxls_chip_info_table); i++) { + if (fxls_chip_info_table[i].chip_id == reg) { + data->chip_info = &fxls_chip_info_table[i]; + break; + } + } + if (i == ARRAY_SIZE(fxls_chip_info_table)) { + dev_err(dev, "failed to match device in table\n"); + return -ENXIO; + } + + indio_dev->channels = data->chip_info->channels; + indio_dev->num_channels = data->chip_info->num_channels; + indio_dev->name = data->chip_info->name; + indio_dev->info = &fxls8962af_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = fxls8962af_reset(data); + if (ret) + return ret; + + if (irq) { + ret = fxls8962af_irq_setup(indio_dev, irq); + if (ret) + return ret; + + ret = devm_iio_kfifo_buffer_setup(dev, indio_dev, + INDIO_BUFFER_SOFTWARE, + &fxls8962af_buffer_ops); + if (ret) + return ret; + } + + ret = pm_runtime_set_active(dev); + if (ret) + return ret; + + pm_runtime_enable(dev); + pm_runtime_set_autosuspend_delay(dev, FXLS8962AF_AUTO_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(dev); + + ret = devm_add_action_or_reset(dev, fxls8962af_pm_disable, dev); + if (ret) + return ret; + + return devm_iio_device_register(dev, indio_dev); +} +EXPORT_SYMBOL_GPL(fxls8962af_core_probe); + +static int __maybe_unused fxls8962af_runtime_suspend(struct device *dev) +{ + struct fxls8962af_data *data = iio_priv(dev_get_drvdata(dev)); + int ret; + + ret = fxls8962af_standby(data); + if (ret) { + dev_err(dev, "powering off device failed\n"); + return ret; + } + + return 0; +} + +static int __maybe_unused fxls8962af_runtime_resume(struct device *dev) +{ + struct fxls8962af_data *data = iio_priv(dev_get_drvdata(dev)); + + return fxls8962af_active(data); +} + +const struct dev_pm_ops fxls8962af_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(fxls8962af_runtime_suspend, + fxls8962af_runtime_resume, NULL) +}; +EXPORT_SYMBOL_GPL(fxls8962af_pm_ops); + +MODULE_AUTHOR("Sean Nyekjaer <sean@geanix.com>"); +MODULE_DESCRIPTION("NXP FXLS8962AF/FXLS8964AF accelerometer driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/accel/fxls8962af-i2c.c b/drivers/iio/accel/fxls8962af-i2c.c new file mode 100644 index 000000000000..cfb004b20455 --- /dev/null +++ b/drivers/iio/accel/fxls8962af-i2c.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * NXP FXLS8962AF/FXLS8964AF Accelerometer I2C Driver + * + * Copyright 2021 Connected Cars A/S + */ + +#include <linux/dev_printk.h> +#include <linux/err.h> +#include <linux/i2c.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/regmap.h> + +#include "fxls8962af.h" + +static int fxls8962af_probe(struct i2c_client *client) +{ + struct regmap *regmap; + + regmap = devm_regmap_init_i2c(client, &fxls8962af_regmap_conf); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "Failed to initialize i2c regmap\n"); + return PTR_ERR(regmap); + } + + return fxls8962af_core_probe(&client->dev, regmap, client->irq); +} + +static const struct i2c_device_id fxls8962af_id[] = { + { "fxls8962af", fxls8962af }, + { "fxls8964af", fxls8964af }, + {} +}; +MODULE_DEVICE_TABLE(i2c, fxls8962af_id); + +static const struct of_device_id fxls8962af_of_match[] = { + { .compatible = "nxp,fxls8962af" }, + { .compatible = "nxp,fxls8964af" }, + {} +}; +MODULE_DEVICE_TABLE(of, fxls8962af_of_match); + +static struct i2c_driver fxls8962af_driver = { + .driver = { + .name = "fxls8962af_i2c", + .of_match_table = fxls8962af_of_match, + .pm = &fxls8962af_pm_ops, + }, + .probe_new = fxls8962af_probe, + .id_table = fxls8962af_id, +}; +module_i2c_driver(fxls8962af_driver); + +MODULE_AUTHOR("Sean Nyekjaer <sean@geanix.com>"); +MODULE_DESCRIPTION("NXP FXLS8962AF/FXLS8964AF accelerometer i2c driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/accel/fxls8962af-spi.c b/drivers/iio/accel/fxls8962af-spi.c new file mode 100644 index 000000000000..57108d3d480b --- /dev/null +++ b/drivers/iio/accel/fxls8962af-spi.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * NXP FXLS8962AF/FXLS8964AF Accelerometer SPI Driver + * + * Copyright 2021 Connected Cars A/S + */ + +#include <linux/dev_printk.h> +#include <linux/err.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/spi/spi.h> +#include <linux/regmap.h> + +#include "fxls8962af.h" + +static int fxls8962af_probe(struct spi_device *spi) +{ + struct regmap *regmap; + + regmap = devm_regmap_init_spi(spi, &fxls8962af_regmap_conf); + if (IS_ERR(regmap)) { + dev_err(&spi->dev, "Failed to initialize spi regmap\n"); + return PTR_ERR(regmap); + } + + return fxls8962af_core_probe(&spi->dev, regmap, spi->irq); +} + +static const struct of_device_id fxls8962af_spi_of_match[] = { + { .compatible = "nxp,fxls8962af" }, + { .compatible = "nxp,fxls8964af" }, + {} +}; +MODULE_DEVICE_TABLE(of, fxls8962af_spi_of_match); + +static const struct spi_device_id fxls8962af_spi_id_table[] = { + { "fxls8962af", fxls8962af }, + { "fxls8964af", fxls8964af }, + {} +}; +MODULE_DEVICE_TABLE(spi, fxls8962af_spi_id_table); + +static struct spi_driver fxls8962af_driver = { + .driver = { + .name = "fxls8962af_spi", + .pm = &fxls8962af_pm_ops, + .of_match_table = fxls8962af_spi_of_match, + }, + .probe = fxls8962af_probe, + .id_table = fxls8962af_spi_id_table, +}; +module_spi_driver(fxls8962af_driver); + +MODULE_AUTHOR("Sean Nyekjaer <sean@geanix.com>"); +MODULE_DESCRIPTION("NXP FXLS8962AF/FXLS8964AF accelerometer spi driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/accel/fxls8962af.h b/drivers/iio/accel/fxls8962af.h new file mode 100644 index 000000000000..b67572c3ef06 --- /dev/null +++ b/drivers/iio/accel/fxls8962af.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2021 Connected Cars A/S + */ +#ifndef _FXLS8962AF_H_ +#define _FXLS8962AF_H_ + +struct regmap; +struct device; + +enum { + fxls8962af, + fxls8964af, +}; + +int fxls8962af_core_probe(struct device *dev, struct regmap *regmap, int irq); +int fxls8962af_core_remove(struct device *dev); + +extern const struct dev_pm_ops fxls8962af_pm_ops; +extern const struct regmap_config fxls8962af_regmap_conf; + +#endif /* _FXLS8962AF_H_ */ diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c index 2f9465cb382f..55cdca818b3b 100644 --- a/drivers/iio/accel/hid-sensor-accel-3d.c +++ b/drivers/iio/accel/hid-sensor-accel-3d.c @@ -6,13 +6,10 @@ #include <linux/device.h> #include <linux/platform_device.h> #include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/irq.h> +#include <linux/mod_devicetable.h> #include <linux/slab.h> -#include <linux/delay.h> #include <linux/hid-sensor-hub.h> #include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> #include <linux/iio/buffer.h> #include "../common/hid-sensors/hid-sensor-trigger.h" @@ -28,8 +25,11 @@ struct accel_3d_state { struct hid_sensor_hub_callbacks callbacks; struct hid_sensor_common common_attributes; struct hid_sensor_hub_attribute_info accel[ACCEL_3D_CHANNEL_MAX]; - /* Reserve for 3 channels + padding + timestamp */ - u32 accel_val[ACCEL_3D_CHANNEL_MAX + 3]; + /* Ensure timestamp is naturally aligned */ + struct { + u32 accel_val[3]; + s64 timestamp __aligned(8); + } scan; int scale_pre_decml; int scale_post_decml; int scale_precision; @@ -245,8 +245,8 @@ static int accel_3d_proc_event(struct hid_sensor_hub_device *hsdev, accel_state->timestamp = iio_get_time_ns(indio_dev); hid_sensor_push_data(indio_dev, - accel_state->accel_val, - sizeof(accel_state->accel_val), + &accel_state->scan, + sizeof(accel_state->scan), accel_state->timestamp); accel_state->timestamp = 0; @@ -271,7 +271,7 @@ static int accel_3d_capture_sample(struct hid_sensor_hub_device *hsdev, case HID_USAGE_SENSOR_ACCEL_Y_AXIS: case HID_USAGE_SENSOR_ACCEL_Z_AXIS: offset = usage_id - HID_USAGE_SENSOR_ACCEL_X_AXIS; - accel_state->accel_val[CHANNEL_SCAN_INDEX_X + offset] = + accel_state->scan.accel_val[CHANNEL_SCAN_INDEX_X + offset] = *(u32 *)raw_data; ret = 0; break; @@ -462,3 +462,4 @@ module_platform_driver(hid_accel_3d_platform_driver); MODULE_DESCRIPTION("HID Sensor Accel 3D"); MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(IIO_HID); diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index ff724bc17a45..a51fdd3c9b5b 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -51,13 +51,15 @@ #define KXTF9_REG_TILT_POS_CUR 0x10 #define KXTF9_REG_TILT_POS_PREV 0x11 #define KXTF9_REG_INT_SRC1 0x15 -#define KXCJK1013_REG_INT_SRC1 0x16 /* compatible, but called INT_SRC2 in KXTF9 ds */ +#define KXTF9_REG_INT_SRC2 0x16 +#define KXCJK1013_REG_INT_SRC1 0x16 #define KXCJK1013_REG_INT_SRC2 0x17 #define KXCJK1013_REG_STATUS_REG 0x18 #define KXCJK1013_REG_INT_REL 0x1A #define KXCJK1013_REG_CTRL1 0x1B #define KXTF9_REG_CTRL2 0x1C -#define KXCJK1013_REG_CTRL2 0x1D /* mostly compatible, CTRL_REG3 in KTXF9 ds */ +#define KXTF9_REG_CTRL3 0x1D +#define KXCJK1013_REG_CTRL2 0x1D #define KXCJK1013_REG_INT_CTRL1 0x1E #define KXCJK1013_REG_INT_CTRL2 0x1F #define KXTF9_REG_INT_CTRL3 0x20 @@ -77,6 +79,45 @@ #define KXTF9_REG_HYST_SET 0x5F #define KXCJK1013_REG_WAKE_THRES 0x6A +/* Everything up to 0x11 is equal to KXCJK1013/KXTF9 above */ +#define KX023_REG_INS1 0x12 +#define KX023_REG_INS2 0x13 +#define KX023_REG_INS3 0x14 +#define KX023_REG_STAT 0x15 +#define KX023_REG_INT_REL 0x17 +#define KX023_REG_CNTL1 0x18 +#define KX023_REG_CNTL2 0x19 +#define KX023_REG_CNTL3 0x1A +#define KX023_REG_ODCNTL 0x1B +#define KX023_REG_INC1 0x1C +#define KX023_REG_INC2 0x1D +#define KX023_REG_INC3 0x1E +#define KX023_REG_INC4 0x1F +#define KX023_REG_INC5 0x20 +#define KX023_REG_INC6 0x21 +#define KX023_REG_TILT_TIMER 0x22 +#define KX023_REG_WUFC 0x23 +#define KX023_REG_TDTRC 0x24 +#define KX023_REG_TDTC 0x25 +#define KX023_REG_TTH 0x26 +#define KX023_REG_TTL 0x27 +#define KX023_REG_FTD 0x28 +#define KX023_REG_STD 0x29 +#define KX023_REG_TLT 0x2A +#define KX023_REG_TWS 0x2B +#define KX023_REG_ATH 0x30 +#define KX023_REG_TILT_ANGLE_LL 0x32 +#define KX023_REG_TILT_ANGLE_HL 0x33 +#define KX023_REG_HYST_SET 0x34 +#define KX023_REG_LP_CNTL 0x35 +#define KX023_REG_BUF_CNTL1 0x3A +#define KX023_REG_BUF_CNTL2 0x3B +#define KX023_REG_BUF_STATUS_1 0x3C +#define KX023_REG_BUF_STATUS_2 0x3D +#define KX023_REG_BUF_CLEAR 0x3E +#define KX023_REG_BUF_READ 0x3F +#define KX023_REG_SELF_TEST 0x60 + #define KXCJK1013_REG_CTRL1_BIT_PC1 BIT(7) #define KXCJK1013_REG_CTRL1_BIT_RES BIT(6) #define KXCJK1013_REG_CTRL1_BIT_DRDY BIT(5) @@ -117,6 +158,14 @@ #define KXCJK1013_REG_INT_SRC2_BIT_XP BIT(4) #define KXCJK1013_REG_INT_SRC2_BIT_XN BIT(5) +/* KX023 interrupt routing to INT1. INT2 can be configured with INC6 */ +#define KX023_REG_INC4_BFI1 BIT(6) +#define KX023_REG_INC4_WMI1 BIT(5) +#define KX023_REG_INC4_DRDY1 BIT(4) +#define KX023_REG_INC4_TDTI1 BIT(2) +#define KX023_REG_INC4_WUFI1 BIT(1) +#define KX023_REG_INC4_TPI1 BIT(0) + #define KXCJK1013_DEFAULT_WAKE_THRES 1 enum kx_chipset { @@ -124,6 +173,7 @@ enum kx_chipset { KXCJ91008, KXTJ21009, KXTF9, + KX0231025, KX_MAX_CHIPS /* this must be last */ }; @@ -133,6 +183,63 @@ enum kx_acpi_type { ACPI_KIOX010A, }; +struct kx_chipset_regs { + u8 int_src1; + u8 int_src2; + u8 int_rel; + u8 ctrl1; + u8 wuf_ctrl; + u8 int_ctrl1; + u8 data_ctrl; + u8 wake_timer; + u8 wake_thres; +}; + +static const struct kx_chipset_regs kxcjk1013_regs = { + .int_src1 = KXCJK1013_REG_INT_SRC1, + .int_src2 = KXCJK1013_REG_INT_SRC2, + .int_rel = KXCJK1013_REG_INT_REL, + .ctrl1 = KXCJK1013_REG_CTRL1, + .wuf_ctrl = KXCJK1013_REG_CTRL2, + .int_ctrl1 = KXCJK1013_REG_INT_CTRL1, + .data_ctrl = KXCJK1013_REG_DATA_CTRL, + .wake_timer = KXCJK1013_REG_WAKE_TIMER, + .wake_thres = KXCJK1013_REG_WAKE_THRES, +}; + +static const struct kx_chipset_regs kxtf9_regs = { + /* .int_src1 was moved to INT_SRC2 on KXTF9 */ + .int_src1 = KXTF9_REG_INT_SRC2, + /* .int_src2 is not available */ + .int_rel = KXCJK1013_REG_INT_REL, + .ctrl1 = KXCJK1013_REG_CTRL1, + .wuf_ctrl = KXTF9_REG_CTRL3, + .int_ctrl1 = KXCJK1013_REG_INT_CTRL1, + .data_ctrl = KXCJK1013_REG_DATA_CTRL, + .wake_timer = KXCJK1013_REG_WAKE_TIMER, + .wake_thres = KXTF9_REG_WAKE_THRESH, +}; + +/* The registers have totally different names but the bits are compatible */ +static const struct kx_chipset_regs kx0231025_regs = { + .int_src1 = KX023_REG_INS2, + .int_src2 = KX023_REG_INS3, + .int_rel = KX023_REG_INT_REL, + .ctrl1 = KX023_REG_CNTL1, + .wuf_ctrl = KX023_REG_CNTL3, + .int_ctrl1 = KX023_REG_INC1, + .data_ctrl = KX023_REG_ODCNTL, + .wake_timer = KX023_REG_WUFC, + .wake_thres = KX023_REG_ATH, +}; + +enum kxcjk1013_axis { + AXIS_X, + AXIS_Y, + AXIS_Z, + AXIS_MAX +}; + struct kxcjk1013_data { struct regulator_bulk_data regulators[2]; struct i2c_client *client; @@ -140,7 +247,11 @@ struct kxcjk1013_data { struct iio_trigger *motion_trig; struct iio_mount_matrix orientation; struct mutex mutex; - s16 buffer[8]; + /* Ensure timestamp naturally aligned */ + struct { + s16 chans[AXIS_MAX]; + s64 timestamp __aligned(8); + } scan; u8 odr_bits; u8 range; int wake_thres; @@ -152,13 +263,7 @@ struct kxcjk1013_data { int64_t timestamp; enum kx_chipset chipset; enum kx_acpi_type acpi_type; -}; - -enum kxcjk1013_axis { - AXIS_X, - AXIS_Y, - AXIS_Z, - AXIS_MAX, + const struct kx_chipset_regs *regs; }; enum kxcjk1013_mode { @@ -268,6 +373,22 @@ static const struct { {0x05, 5100}, {0x06, 2700}, }, + /* KX023-1025 */ + { + /* First 4 are not in datasheet, taken from KXCTJ2-1009 */ + {0x08, 1240000}, + {0x09, 621000}, + {0x0A, 309000}, + {0x0B, 151000}, + {0, 81000}, + {0x01, 40000}, + {0x02, 22000}, + {0x03, 12000}, + {0x04, 7000}, + {0x05, 4400}, + {0x06, 3000}, + {0x07, 3000}, + }, }; static const struct { @@ -309,7 +430,7 @@ static int kxcjk1013_set_mode(struct kxcjk1013_data *data, { int ret; - ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); + ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1); if (ret < 0) { dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); return ret; @@ -320,8 +441,7 @@ static int kxcjk1013_set_mode(struct kxcjk1013_data *data, else ret |= KXCJK1013_REG_CTRL1_BIT_PC1; - ret = i2c_smbus_write_byte_data(data->client, - KXCJK1013_REG_CTRL1, ret); + ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret); if (ret < 0) { dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); return ret; @@ -335,7 +455,7 @@ static int kxcjk1013_get_mode(struct kxcjk1013_data *data, { int ret; - ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); + ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1); if (ret < 0) { dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); return ret; @@ -353,7 +473,7 @@ static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index) { int ret; - ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); + ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1); if (ret < 0) { dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); return ret; @@ -364,9 +484,7 @@ static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index) ret |= (KXCJK1013_scale_table[range_index].gsel_0 << 3); ret |= (KXCJK1013_scale_table[range_index].gsel_1 << 4); - ret = i2c_smbus_write_byte_data(data->client, - KXCJK1013_REG_CTRL1, - ret); + ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret); if (ret < 0) { dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); return ret; @@ -400,7 +518,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) if (ret < 0) return ret; - ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); + ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1); if (ret < 0) { dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); return ret; @@ -409,8 +527,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) /* Set 12 bit mode */ ret |= KXCJK1013_REG_CTRL1_BIT_RES; - ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_CTRL1, - ret); + ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret); if (ret < 0) { dev_err(&data->client->dev, "Error reading reg_ctrl\n"); return ret; @@ -421,7 +538,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) if (ret < 0) return ret; - ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_DATA_CTRL); + ret = i2c_smbus_read_byte_data(data->client, data->regs->data_ctrl); if (ret < 0) { dev_err(&data->client->dev, "Error reading reg_data_ctrl\n"); return ret; @@ -430,7 +547,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) data->odr_bits = ret; /* Set up INT polarity */ - ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1); + ret = i2c_smbus_read_byte_data(data->client, data->regs->int_ctrl1); if (ret < 0) { dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); return ret; @@ -441,13 +558,23 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) else ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEA; - ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1, - ret); + ret = i2c_smbus_write_byte_data(data->client, data->regs->int_ctrl1, ret); if (ret < 0) { dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); return ret; } + /* On KX023, route all used interrupts to INT1 for now */ + if (data->chipset == KX0231025 && data->client->irq > 0) { + ret = i2c_smbus_write_byte_data(data->client, KX023_REG_INC4, + KX023_REG_INC4_DRDY1 | + KX023_REG_INC4_WUFI1); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_inc4\n"); + return ret; + } + } + ret = kxcjk1013_set_mode(data, OPERATION); if (ret < 0) return ret; @@ -478,7 +605,7 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) int ret; if (on) - ret = pm_runtime_get_sync(&data->client->dev); + ret = pm_runtime_resume_and_get(&data->client->dev); else { pm_runtime_mark_last_busy(&data->client->dev); ret = pm_runtime_put_autosuspend(&data->client->dev); @@ -486,8 +613,6 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) if (ret < 0) { dev_err(&data->client->dev, "Failed: %s for %d\n", __func__, on); - if (on) - pm_runtime_put_noidle(&data->client->dev); return ret; } #endif @@ -497,10 +622,9 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data) { - int waketh_reg, ret; + int ret; - ret = i2c_smbus_write_byte_data(data->client, - KXCJK1013_REG_WAKE_TIMER, + ret = i2c_smbus_write_byte_data(data->client, data->regs->wake_timer, data->wake_dur); if (ret < 0) { dev_err(&data->client->dev, @@ -508,9 +632,7 @@ static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data) return ret; } - waketh_reg = data->chipset == KXTF9 ? - KXTF9_REG_WAKE_THRESH : KXCJK1013_REG_WAKE_THRES; - ret = i2c_smbus_write_byte_data(data->client, waketh_reg, + ret = i2c_smbus_write_byte_data(data->client, data->regs->wake_thres, data->wake_thres); if (ret < 0) { dev_err(&data->client->dev, "Error writing reg_wake_thres\n"); @@ -539,7 +661,7 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data, if (ret < 0) return ret; - ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1); + ret = i2c_smbus_read_byte_data(data->client, data->regs->int_ctrl1); if (ret < 0) { dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); return ret; @@ -550,14 +672,13 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data, else ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN; - ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1, - ret); + ret = i2c_smbus_write_byte_data(data->client, data->regs->int_ctrl1, ret); if (ret < 0) { dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); return ret; } - ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); + ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1); if (ret < 0) { dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); return ret; @@ -568,8 +689,7 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data, else ret &= ~KXCJK1013_REG_CTRL1_BIT_WUFE; - ret = i2c_smbus_write_byte_data(data->client, - KXCJK1013_REG_CTRL1, ret); + ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret); if (ret < 0) { dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); return ret; @@ -599,7 +719,7 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data, if (ret < 0) return ret; - ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1); + ret = i2c_smbus_read_byte_data(data->client, data->regs->int_ctrl1); if (ret < 0) { dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); return ret; @@ -610,14 +730,13 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data, else ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN; - ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1, - ret); + ret = i2c_smbus_write_byte_data(data->client, data->regs->int_ctrl1, ret); if (ret < 0) { dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); return ret; } - ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); + ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1); if (ret < 0) { dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); return ret; @@ -628,8 +747,7 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data, else ret &= ~KXCJK1013_REG_CTRL1_BIT_DRDY; - ret = i2c_smbus_write_byte_data(data->client, - KXCJK1013_REG_CTRL1, ret); + ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret); if (ret < 0) { dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); return ret; @@ -701,7 +819,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2) if (ret < 0) return ret; - ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_DATA_CTRL, + ret = i2c_smbus_write_byte_data(data->client, data->regs->data_ctrl, odr_setting->odr_bits); if (ret < 0) { dev_err(&data->client->dev, "Error writing data_ctrl\n"); @@ -710,7 +828,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2) data->odr_bits = odr_setting->odr_bits; - ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_CTRL2, + ret = i2c_smbus_write_byte_data(data->client, data->regs->wuf_ctrl, odr_setting->wuf_bits); if (ret < 0) { dev_err(&data->client->dev, "Error writing reg_ctrl2\n"); @@ -1094,12 +1212,12 @@ static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p) ret = i2c_smbus_read_i2c_block_data_or_emulated(data->client, KXCJK1013_REG_XOUT_L, AXIS_MAX * 2, - (u8 *)data->buffer); + (u8 *)data->scan.chans); mutex_unlock(&data->mutex); if (ret < 0) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, data->timestamp); err: iio_trigger_notify_done(indio_dev->trig); @@ -1113,7 +1231,7 @@ static void kxcjk1013_trig_reen(struct iio_trigger *trig) struct kxcjk1013_data *data = iio_priv(indio_dev); int ret; - ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_REL); + ret = i2c_smbus_read_byte_data(data->client, data->regs->int_rel); if (ret < 0) dev_err(&data->client->dev, "Error reading reg_int_rel\n"); } @@ -1166,8 +1284,7 @@ static void kxcjk1013_report_motion_event(struct iio_dev *indio_dev) { struct kxcjk1013_data *data = iio_priv(indio_dev); - int ret = i2c_smbus_read_byte_data(data->client, - KXCJK1013_REG_INT_SRC2); + int ret = i2c_smbus_read_byte_data(data->client, data->regs->int_src2); if (ret < 0) { dev_err(&data->client->dev, "Error reading reg_int_src2\n"); return; @@ -1234,7 +1351,7 @@ static irqreturn_t kxcjk1013_event_handler(int irq, void *private) struct kxcjk1013_data *data = iio_priv(indio_dev); int ret; - ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_SRC1); + ret = i2c_smbus_read_byte_data(data->client, data->regs->int_src1); if (ret < 0) { dev_err(&data->client->dev, "Error reading reg_int_src1\n"); goto ack_intr; @@ -1257,7 +1374,7 @@ ack_intr: if (data->dready_trigger_on) return IRQ_HANDLED; - ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_REL); + ret = i2c_smbus_read_byte_data(data->client, data->regs->int_rel); if (ret < 0) dev_err(&data->client->dev, "Error reading reg_int_rel\n"); @@ -1338,8 +1455,7 @@ static int kxcjk1013_probe(struct i2c_client *client, } else { data->active_high_intr = true; /* default polarity */ - ret = iio_read_mount_matrix(&client->dev, "mount-matrix", - &data->orientation); + ret = iio_read_mount_matrix(&client->dev, &data->orientation); if (ret) return ret; } @@ -1378,6 +1494,22 @@ static int kxcjk1013_probe(struct i2c_client *client, } else return -ENODEV; + switch (data->chipset) { + case KXCJK1013: + case KXCJ91008: + case KXTJ21009: + data->regs = &kxcjk1013_regs; + break; + case KXTF9: + data->regs = &kxtf9_regs; + break; + case KX0231025: + data->regs = &kx0231025_regs; + break; + default: + return -EINVAL; + } + ret = kxcjk1013_chip_init(data); if (ret < 0) return ret; @@ -1404,7 +1536,7 @@ static int kxcjk1013_probe(struct i2c_client *client, data->dready_trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!data->dready_trig) { ret = -ENOMEM; goto err_poweroff; @@ -1413,7 +1545,7 @@ static int kxcjk1013_probe(struct i2c_client *client, data->motion_trig = devm_iio_trigger_alloc(&client->dev, "%s-any-motion-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!data->motion_trig) { ret = -ENOMEM; goto err_poweroff; @@ -1485,7 +1617,6 @@ static int kxcjk1013_remove(struct i2c_client *client) pm_runtime_disable(&client->dev); pm_runtime_set_suspended(&client->dev); - pm_runtime_put_noidle(&client->dev); if (data->dready_trig) { iio_triggered_buffer_cleanup(indio_dev); @@ -1593,6 +1724,7 @@ static const struct i2c_device_id kxcjk1013_id[] = { {"kxcj91008", KXCJ91008}, {"kxtj21009", KXTJ21009}, {"kxtf9", KXTF9}, + {"kx023-1025", KX0231025}, {"SMO8500", KXCJ91008}, {} }; @@ -1604,6 +1736,7 @@ static const struct of_device_id kxcjk1013_of_match[] = { { .compatible = "kionix,kxcj91008", }, { .compatible = "kionix,kxtj21009", }, { .compatible = "kionix,kxtf9", }, + { .compatible = "kionix,kx023-1025", }, { } }; MODULE_DEVICE_TABLE(of, kxcjk1013_of_match); diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index 0e18b92e2099..bf7ed9e7d00f 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -420,7 +420,7 @@ int kxsd9_common_probe(struct device *dev, indio_dev->available_scan_masks = kxsd9_scan_masks; /* Read the mounting matrix, if present */ - ret = iio_read_mount_matrix(dev, "mount-matrix", &st->orientation); + ret = iio_read_mount_matrix(dev, &st->orientation); if (ret) return ret; diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 4d307dfb9169..715b8138fb71 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -221,7 +221,7 @@ static int mma8452_set_runtime_pm_state(struct i2c_client *client, bool on) int ret; if (on) { - ret = pm_runtime_get_sync(&client->dev); + ret = pm_runtime_resume_and_get(&client->dev); } else { pm_runtime_mark_last_busy(&client->dev); ret = pm_runtime_put_autosuspend(&client->dev); @@ -230,8 +230,6 @@ static int mma8452_set_runtime_pm_state(struct i2c_client *client, bool on) if (ret < 0) { dev_err(&client->dev, "failed to change power state to %d\n", on); - if (on) - pm_runtime_put_noidle(&client->dev); return ret; } @@ -1461,7 +1459,7 @@ static int mma8452_trigger_setup(struct iio_dev *indio_dev) trig = devm_iio_trigger_alloc(&data->client->dev, "%s-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!trig) return -ENOMEM; @@ -1711,7 +1709,6 @@ static int mma8452_remove(struct i2c_client *client) pm_runtime_disable(&client->dev); pm_runtime_set_suspended(&client->dev); - pm_runtime_put_noidle(&client->dev); iio_triggered_buffer_cleanup(indio_dev); mma8452_trigger_cleanup(indio_dev); diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c index 08a2303cc9df..4c359fb05480 100644 --- a/drivers/iio/accel/mma9551.c +++ b/drivers/iio/accel/mma9551.c @@ -515,7 +515,6 @@ static int mma9551_remove(struct i2c_client *client) pm_runtime_disable(&client->dev); pm_runtime_set_suspended(&client->dev); - pm_runtime_put_noidle(&client->dev); mutex_lock(&data->mutex); mma9551_set_device_state(data->client, false); diff --git a/drivers/iio/accel/mma9551_core.c b/drivers/iio/accel/mma9551_core.c index 666e7a04a7d7..fbf2e2c45678 100644 --- a/drivers/iio/accel/mma9551_core.c +++ b/drivers/iio/accel/mma9551_core.c @@ -664,7 +664,7 @@ int mma9551_set_power_state(struct i2c_client *client, bool on) int ret; if (on) - ret = pm_runtime_get_sync(&client->dev); + ret = pm_runtime_resume_and_get(&client->dev); else { pm_runtime_mark_last_busy(&client->dev); ret = pm_runtime_put_autosuspend(&client->dev); @@ -673,8 +673,6 @@ int mma9551_set_power_state(struct i2c_client *client, bool on) if (ret < 0) { dev_err(&client->dev, "failed to change power state to %d\n", on); - if (on) - pm_runtime_put_noidle(&client->dev); return ret; } diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c index c15908faa381..ba3ecb3b57dc 100644 --- a/drivers/iio/accel/mma9553.c +++ b/drivers/iio/accel/mma9553.c @@ -1154,7 +1154,6 @@ static int mma9553_remove(struct i2c_client *client) pm_runtime_disable(&client->dev); pm_runtime_set_suspended(&client->dev); - pm_runtime_put_noidle(&client->dev); mutex_lock(&data->mutex); mma9551_set_device_state(data->client, false); diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c index fb3cbaa62bd8..b3afbf064915 100644 --- a/drivers/iio/accel/mxc4005.c +++ b/drivers/iio/accel/mxc4005.c @@ -56,7 +56,11 @@ struct mxc4005_data { struct mutex mutex; struct regmap *regmap; struct iio_trigger *dready_trig; - __be16 buffer[8]; + /* Ensure timestamp is naturally aligned */ + struct { + __be16 chans[3]; + s64 timestamp __aligned(8); + } scan; bool trigger_enabled; }; @@ -135,7 +139,7 @@ static int mxc4005_read_xyz(struct mxc4005_data *data) int ret; ret = regmap_bulk_read(data->regmap, MXC4005_REG_XOUT_UPPER, - data->buffer, sizeof(data->buffer)); + data->scan.chans, sizeof(data->scan.chans)); if (ret < 0) { dev_err(data->dev, "failed to read axes\n"); return ret; @@ -301,7 +305,7 @@ static irqreturn_t mxc4005_trigger_handler(int irq, void *private) if (ret < 0) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, pf->timestamp); err: @@ -433,7 +437,7 @@ static int mxc4005_probe(struct i2c_client *client, data->dready_trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!data->dready_trig) return -ENOMEM; diff --git a/drivers/iio/accel/sca3300.c b/drivers/iio/accel/sca3300.c new file mode 100644 index 000000000000..f7ef8ecfd34a --- /dev/null +++ b/drivers/iio/accel/sca3300.c @@ -0,0 +1,472 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Murata SCA3300 3-axis industrial accelerometer + * + * Copyright (c) 2021 Vaisala Oyj. All rights reserved. + */ + +#include <linux/bitops.h> +#include <linux/crc8.h> +#include <linux/delay.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/spi/spi.h> + +#include <asm/unaligned.h> + +#include <linux/iio/buffer.h> +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> + +#define SCA3300_ALIAS "sca3300" + +#define SCA3300_CRC8_POLYNOMIAL 0x1d + +/* Device mode register */ +#define SCA3300_REG_MODE 0xd +#define SCA3300_MODE_SW_RESET 0x20 + +/* Last register in map */ +#define SCA3300_REG_SELBANK 0x1f + +/* Device status and mask */ +#define SCA3300_REG_STATUS 0x6 +#define SCA3300_STATUS_MASK GENMASK(8, 0) + +/* Device ID */ +#define SCA3300_REG_WHOAMI 0x10 +#define SCA3300_WHOAMI_ID 0x51 + +/* Device return status and mask */ +#define SCA3300_VALUE_RS_ERROR 0x3 +#define SCA3300_MASK_RS_STATUS GENMASK(1, 0) + +enum sca3300_scan_indexes { + SCA3300_ACC_X = 0, + SCA3300_ACC_Y, + SCA3300_ACC_Z, + SCA3300_TEMP, + SCA3300_TIMESTAMP, +}; + +#define SCA3300_ACCEL_CHANNEL(index, reg, axis) { \ + .type = IIO_ACCEL, \ + .address = reg, \ + .modified = 1, \ + .channel2 = IIO_MOD_##axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ + .info_mask_shared_by_type_available = \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ + .scan_index = index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_CPU, \ + }, \ +} + +static const struct iio_chan_spec sca3300_channels[] = { + SCA3300_ACCEL_CHANNEL(SCA3300_ACC_X, 0x1, X), + SCA3300_ACCEL_CHANNEL(SCA3300_ACC_Y, 0x2, Y), + SCA3300_ACCEL_CHANNEL(SCA3300_ACC_Z, 0x3, Z), + { + .type = IIO_TEMP, + .address = 0x5, + .scan_index = SCA3300_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_CPU, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(4), +}; + +static const int sca3300_lp_freq[] = {70, 70, 70, 10}; +static const int sca3300_accel_scale[][2] = {{0, 370}, {0, 741}, {0, 185}, {0, 185}}; + +static const unsigned long sca3300_scan_masks[] = { + BIT(SCA3300_ACC_X) | BIT(SCA3300_ACC_Y) | BIT(SCA3300_ACC_Z) | + BIT(SCA3300_TEMP), + 0 +}; + +/** + * struct sca3300_data - device data + * @spi: SPI device structure + * @lock: Data buffer lock + * @scan: Triggered buffer. Four channel 16-bit data + 64-bit timestamp + * @txbuf: Transmit buffer + * @rxbuf: Receive buffer + */ +struct sca3300_data { + struct spi_device *spi; + struct mutex lock; + struct { + s16 channels[4]; + s64 ts __aligned(sizeof(s64)); + } scan; + u8 txbuf[4] ____cacheline_aligned; + u8 rxbuf[4]; +}; + +DECLARE_CRC8_TABLE(sca3300_crc_table); + +static int sca3300_transfer(struct sca3300_data *sca_data, int *val) +{ + /* Consecutive requests min. 10 us delay (Datasheet section 5.1.2) */ + struct spi_delay delay = { .value = 10, .unit = SPI_DELAY_UNIT_USECS }; + int32_t ret; + int rs; + u8 crc; + struct spi_transfer xfers[2] = { + { + .tx_buf = sca_data->txbuf, + .len = ARRAY_SIZE(sca_data->txbuf), + .delay = delay, + .cs_change = 1, + }, + { + .rx_buf = sca_data->rxbuf, + .len = ARRAY_SIZE(sca_data->rxbuf), + .delay = delay, + } + }; + + /* inverted crc value as described in device data sheet */ + crc = ~crc8(sca3300_crc_table, &sca_data->txbuf[0], 3, CRC8_INIT_VALUE); + sca_data->txbuf[3] = crc; + + ret = spi_sync_transfer(sca_data->spi, xfers, ARRAY_SIZE(xfers)); + if (ret) { + dev_err(&sca_data->spi->dev, + "transfer error, error: %d\n", ret); + return -EIO; + } + + crc = ~crc8(sca3300_crc_table, &sca_data->rxbuf[0], 3, CRC8_INIT_VALUE); + if (sca_data->rxbuf[3] != crc) { + dev_err(&sca_data->spi->dev, "CRC checksum mismatch"); + return -EIO; + } + + /* get return status */ + rs = sca_data->rxbuf[0] & SCA3300_MASK_RS_STATUS; + if (rs == SCA3300_VALUE_RS_ERROR) + ret = -EINVAL; + + *val = sign_extend32(get_unaligned_be16(&sca_data->rxbuf[1]), 15); + + return ret; +} + +static int sca3300_error_handler(struct sca3300_data *sca_data) +{ + int ret; + int val; + + mutex_lock(&sca_data->lock); + sca_data->txbuf[0] = SCA3300_REG_STATUS << 2; + ret = sca3300_transfer(sca_data, &val); + mutex_unlock(&sca_data->lock); + /* + * Return status error is cleared after reading status register once, + * expect EINVAL here. + */ + if (ret != -EINVAL) { + dev_err(&sca_data->spi->dev, + "error reading device status: %d\n", ret); + return ret; + } + + dev_err(&sca_data->spi->dev, "device status: 0x%lx\n", + val & SCA3300_STATUS_MASK); + + return 0; +} + +static int sca3300_read_reg(struct sca3300_data *sca_data, u8 reg, int *val) +{ + int ret; + + mutex_lock(&sca_data->lock); + sca_data->txbuf[0] = reg << 2; + ret = sca3300_transfer(sca_data, val); + mutex_unlock(&sca_data->lock); + if (ret != -EINVAL) + return ret; + + return sca3300_error_handler(sca_data); +} + +static int sca3300_write_reg(struct sca3300_data *sca_data, u8 reg, int val) +{ + int reg_val = 0; + int ret; + + mutex_lock(&sca_data->lock); + /* BIT(7) for write operation */ + sca_data->txbuf[0] = BIT(7) | (reg << 2); + put_unaligned_be16(val, &sca_data->txbuf[1]); + ret = sca3300_transfer(sca_data, ®_val); + mutex_unlock(&sca_data->lock); + if (ret != -EINVAL) + return ret; + + return sca3300_error_handler(sca_data); +} + +static int sca3300_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct sca3300_data *data = iio_priv(indio_dev); + int reg_val; + int ret; + int i; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + if (val) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(sca3300_accel_scale); i++) { + if (val2 == sca3300_accel_scale[i][1]) + return sca3300_write_reg(data, SCA3300_REG_MODE, i); + } + return -EINVAL; + + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + ret = sca3300_read_reg(data, SCA3300_REG_MODE, ®_val); + if (ret) + return ret; + /* freq. change is possible only for mode 3 and 4 */ + if (reg_val == 2 && val == sca3300_lp_freq[3]) + return sca3300_write_reg(data, SCA3300_REG_MODE, 3); + if (reg_val == 3 && val == sca3300_lp_freq[2]) + return sca3300_write_reg(data, SCA3300_REG_MODE, 2); + return -EINVAL; + default: + return -EINVAL; + } +} + +static int sca3300_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct sca3300_data *data = iio_priv(indio_dev); + int ret; + int reg_val; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = sca3300_read_reg(data, chan->address, val); + if (ret) + return ret; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + ret = sca3300_read_reg(data, SCA3300_REG_MODE, ®_val); + if (ret) + return ret; + *val = 0; + *val2 = sca3300_accel_scale[reg_val][1]; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + ret = sca3300_read_reg(data, SCA3300_REG_MODE, ®_val); + if (ret) + return ret; + *val = sca3300_lp_freq[reg_val]; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static irqreturn_t sca3300_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct sca3300_data *data = iio_priv(indio_dev); + int bit, ret, val, i = 0; + + for_each_set_bit(bit, indio_dev->active_scan_mask, + indio_dev->masklength) { + ret = sca3300_read_reg(data, sca3300_channels[bit].address, + &val); + if (ret) { + dev_err_ratelimited(&data->spi->dev, + "failed to read register, error: %d\n", ret); + /* handled, but bailing out due to errors */ + goto out; + } + data->scan.channels[i++] = val; + } + + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, + iio_get_time_ns(indio_dev)); +out: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +/* + * sca3300_init - Device init sequence. See datasheet rev 2 section + * 4.2 Start-Up Sequence for details. + */ +static int sca3300_init(struct sca3300_data *sca_data, + struct iio_dev *indio_dev) +{ + int value = 0; + int ret; + + ret = sca3300_write_reg(sca_data, SCA3300_REG_MODE, + SCA3300_MODE_SW_RESET); + if (ret) + return ret; + + /* + * Wait 1ms after SW-reset command. + * Wait 15ms for settling of signal paths. + */ + usleep_range(16e3, 50e3); + + ret = sca3300_read_reg(sca_data, SCA3300_REG_WHOAMI, &value); + if (ret) + return ret; + + if (value != SCA3300_WHOAMI_ID) { + dev_err(&sca_data->spi->dev, + "device id not expected value, %d != %u\n", + value, SCA3300_WHOAMI_ID); + return -ENODEV; + } + return 0; +} + +static int sca3300_debugfs_reg_access(struct iio_dev *indio_dev, + unsigned int reg, unsigned int writeval, + unsigned int *readval) +{ + struct sca3300_data *data = iio_priv(indio_dev); + int value; + int ret; + + if (reg > SCA3300_REG_SELBANK) + return -EINVAL; + + if (!readval) + return sca3300_write_reg(data, reg, writeval); + + ret = sca3300_read_reg(data, reg, &value); + if (ret) + return ret; + + *readval = value; + + return 0; +} + +static int sca3300_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SCALE: + *vals = (const int *)sca3300_accel_scale; + *length = ARRAY_SIZE(sca3300_accel_scale) * 2 - 2; + *type = IIO_VAL_INT_PLUS_MICRO; + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + *vals = &sca3300_lp_freq[2]; + *length = 2; + *type = IIO_VAL_INT; + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + +static const struct iio_info sca3300_info = { + .read_raw = sca3300_read_raw, + .write_raw = sca3300_write_raw, + .debugfs_reg_access = &sca3300_debugfs_reg_access, + .read_avail = sca3300_read_avail, +}; + +static int sca3300_probe(struct spi_device *spi) +{ + struct sca3300_data *sca_data; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*sca_data)); + if (!indio_dev) + return -ENOMEM; + + sca_data = iio_priv(indio_dev); + mutex_init(&sca_data->lock); + sca_data->spi = spi; + + crc8_populate_msb(sca3300_crc_table, SCA3300_CRC8_POLYNOMIAL); + + indio_dev->info = &sca3300_info; + indio_dev->name = SCA3300_ALIAS; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = sca3300_channels; + indio_dev->num_channels = ARRAY_SIZE(sca3300_channels); + indio_dev->available_scan_masks = sca3300_scan_masks; + + ret = sca3300_init(sca_data, indio_dev); + if (ret) { + dev_err(&spi->dev, "failed to init device, error: %d\n", ret); + return ret; + } + + ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, + iio_pollfunc_store_time, + sca3300_trigger_handler, NULL); + if (ret) { + dev_err(&spi->dev, + "iio triggered buffer setup failed, error: %d\n", ret); + return ret; + } + + ret = devm_iio_device_register(&spi->dev, indio_dev); + if (ret) { + dev_err(&spi->dev, "iio device register failed, error: %d\n", + ret); + } + + return ret; +} + +static const struct of_device_id sca3300_dt_ids[] = { + { .compatible = "murata,sca3300"}, + {} +}; +MODULE_DEVICE_TABLE(of, sca3300_dt_ids); + +static struct spi_driver sca3300_driver = { + .driver = { + .name = SCA3300_ALIAS, + .of_match_table = sca3300_dt_ids, + }, + .probe = sca3300_probe, +}; +module_spi_driver(sca3300_driver); + +MODULE_AUTHOR("Tomas Melin <tomas.melin@vaisala.com>"); +MODULE_DESCRIPTION("Murata SCA3300 SPI Accelerometer"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h index 5d356288e001..f5b0b8bbaff7 100644 --- a/drivers/iio/accel/st_accel.h +++ b/drivers/iio/accel/st_accel.h @@ -62,18 +62,6 @@ enum st_accel_type { #define LIS2DE12_ACCEL_DEV_NAME "lis2de12" #define LIS2HH12_ACCEL_DEV_NAME "lis2hh12" -/** -* struct st_sensors_platform_data - default accel platform data -* @drdy_int_pin: default accel DRDY is available on INT1 pin. -*/ -static __maybe_unused const struct st_sensors_platform_data default_accel_pdata = { - .drdy_int_pin = 1, -}; - -const struct st_sensor_settings *st_accel_get_settings(const char *name); -int st_accel_common_probe(struct iio_dev *indio_dev); -void st_accel_common_remove(struct iio_dev *indio_dev); - #ifdef CONFIG_IIO_BUFFER int st_accel_allocate_ring(struct iio_dev *indio_dev); void st_accel_deallocate_ring(struct iio_dev *indio_dev); diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 43c50167d220..28fceac9f2f6 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -41,51 +41,74 @@ #define ST_ACCEL_FS_AVL_200G 200 #define ST_ACCEL_FS_AVL_400G 400 +static const struct iio_mount_matrix * +st_accel_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct st_sensor_data *adata = iio_priv(indio_dev); + + return &adata->mount_matrix; +} + +static const struct iio_chan_spec_ext_info st_accel_mount_matrix_ext_info[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_accel_get_mount_matrix), + { } +}; + static const struct iio_chan_spec st_accel_8bit_channels[] = { - ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, + ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 8, 8, - ST_ACCEL_DEFAULT_OUT_X_L_ADDR+1), - ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, + ST_ACCEL_DEFAULT_OUT_X_L_ADDR+1, + st_accel_mount_matrix_ext_info), + ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 8, 8, - ST_ACCEL_DEFAULT_OUT_Y_L_ADDR+1), - ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, + ST_ACCEL_DEFAULT_OUT_Y_L_ADDR+1, + st_accel_mount_matrix_ext_info), + ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 8, 8, - ST_ACCEL_DEFAULT_OUT_Z_L_ADDR+1), + ST_ACCEL_DEFAULT_OUT_Z_L_ADDR+1, + st_accel_mount_matrix_ext_info), IIO_CHAN_SOFT_TIMESTAMP(3) }; static const struct iio_chan_spec st_accel_12bit_channels[] = { - ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, + ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 12, 16, - ST_ACCEL_DEFAULT_OUT_X_L_ADDR), - ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, + ST_ACCEL_DEFAULT_OUT_X_L_ADDR, + st_accel_mount_matrix_ext_info), + ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 12, 16, - ST_ACCEL_DEFAULT_OUT_Y_L_ADDR), - ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, + ST_ACCEL_DEFAULT_OUT_Y_L_ADDR, + st_accel_mount_matrix_ext_info), + ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 12, 16, - ST_ACCEL_DEFAULT_OUT_Z_L_ADDR), + ST_ACCEL_DEFAULT_OUT_Z_L_ADDR, + st_accel_mount_matrix_ext_info), IIO_CHAN_SOFT_TIMESTAMP(3) }; static const struct iio_chan_spec st_accel_16bit_channels[] = { - ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, + ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16, - ST_ACCEL_DEFAULT_OUT_X_L_ADDR), - ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, + ST_ACCEL_DEFAULT_OUT_X_L_ADDR, + st_accel_mount_matrix_ext_info), + ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16, - ST_ACCEL_DEFAULT_OUT_Y_L_ADDR), - ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, + ST_ACCEL_DEFAULT_OUT_Y_L_ADDR, + st_accel_mount_matrix_ext_info), + ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16, - ST_ACCEL_DEFAULT_OUT_Z_L_ADDR), + ST_ACCEL_DEFAULT_OUT_Z_L_ADDR, + st_accel_mount_matrix_ext_info), IIO_CHAN_SOFT_TIMESTAMP(3) }; @@ -980,7 +1003,99 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .multi_read_bit = true, .bootime = 2, }, + { + .wai = 0x49, + .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, + .sensors_supported = { + [0] = LSM9DS0_IMU_DEV_NAME, + }, + .ch = (struct iio_chan_spec *)st_accel_16bit_channels, + .odr = { + .addr = 0x20, + .mask = GENMASK(7, 4), + .odr_avl = { + { 3, 0x01, }, + { 6, 0x02, }, + { 12, 0x03, }, + { 25, 0x04, }, + { 50, 0x05, }, + { 100, 0x06, }, + { 200, 0x07, }, + { 400, 0x08, }, + { 800, 0x09, }, + { 1600, 0x0a, }, + }, + }, + .pw = { + .addr = 0x20, + .mask = GENMASK(7, 4), + .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, + }, + .enable_axis = { + .addr = ST_SENSORS_DEFAULT_AXIS_ADDR, + .mask = ST_SENSORS_DEFAULT_AXIS_MASK, + }, + .fs = { + .addr = 0x21, + .mask = GENMASK(5, 3), + .fs_avl = { + [0] = { + .num = ST_ACCEL_FS_AVL_2G, + .value = 0x00, + .gain = IIO_G_TO_M_S_2(61), + }, + [1] = { + .num = ST_ACCEL_FS_AVL_4G, + .value = 0x01, + .gain = IIO_G_TO_M_S_2(122), + }, + [2] = { + .num = ST_ACCEL_FS_AVL_6G, + .value = 0x02, + .gain = IIO_G_TO_M_S_2(183), + }, + [3] = { + .num = ST_ACCEL_FS_AVL_8G, + .value = 0x03, + .gain = IIO_G_TO_M_S_2(244), + }, + [4] = { + .num = ST_ACCEL_FS_AVL_16G, + .value = 0x04, + .gain = IIO_G_TO_M_S_2(732), + }, + }, + }, + .bdu = { + .addr = 0x20, + .mask = BIT(3), + }, + .drdy_irq = { + .int1 = { + .addr = 0x22, + .mask = BIT(2), + }, + .int2 = { + .addr = 0x23, + .mask = BIT(3), + }, + .stat_drdy = { + .addr = ST_SENSORS_DEFAULT_STAT_ADDR, + .mask = GENMASK(2, 0), + }, + }, + .sim = { + .addr = 0x21, + .value = BIT(0), + }, + .multi_read_bit = true, + .bootime = 2, + }, +}; +/* Default accel DRDY is available on INT1 pin */ +static const struct st_sensors_platform_data default_accel_pdata = { + .drdy_int_pin = 1, }; static int st_accel_read_raw(struct iio_dev *indio_dev, @@ -1070,25 +1185,10 @@ static const struct iio_trigger_ops st_accel_trigger_ops = { #endif #ifdef CONFIG_ACPI -static const struct iio_mount_matrix * -get_mount_matrix(const struct iio_dev *indio_dev, - const struct iio_chan_spec *chan) -{ - struct st_sensor_data *adata = iio_priv(indio_dev); - - return adata->mount_matrix; -} - -static const struct iio_chan_spec_ext_info mount_matrix_ext_info[] = { - IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, get_mount_matrix), - { }, -}; - /* Read ST-specific _ONT orientation data from ACPI and generate an * appropriate mount matrix. */ -static int apply_acpi_orientation(struct iio_dev *indio_dev, - struct iio_chan_spec *channels) +static int apply_acpi_orientation(struct iio_dev *indio_dev) { struct st_sensor_data *adata = iio_priv(indio_dev); struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; @@ -1177,14 +1277,6 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev, } /* Convert our integer matrix to a string-based iio_mount_matrix */ - adata->mount_matrix = devm_kmalloc(&indio_dev->dev, - sizeof(*adata->mount_matrix), - GFP_KERNEL); - if (!adata->mount_matrix) { - ret = -ENOMEM; - goto out; - } - for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { int matrix_val = final_ont[i][j]; @@ -1203,26 +1295,25 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev, default: goto out; } - adata->mount_matrix->rotation[i * 3 + j] = str_value; + adata->mount_matrix.rotation[i * 3 + j] = str_value; } } - /* Expose the mount matrix via ext_info */ - for (i = 0; i < indio_dev->num_channels; i++) - channels[i].ext_info = mount_matrix_ext_info; - ret = 0; dev_info(&indio_dev->dev, "computed mount matrix from ACPI\n"); out: kfree(buffer.pointer); + if (ret) + dev_dbg(&indio_dev->dev, + "failed to apply ACPI orientation data: %d\n", ret); + return ret; } #else /* !CONFIG_ACPI */ -static int apply_acpi_orientation(struct iio_dev *indio_dev, - struct iio_chan_spec *channels) +static int apply_acpi_orientation(struct iio_dev *indio_dev) { - return 0; + return -EINVAL; } #endif @@ -1248,38 +1339,30 @@ int st_accel_common_probe(struct iio_dev *indio_dev) { struct st_sensor_data *adata = iio_priv(indio_dev); struct st_sensors_platform_data *pdata = dev_get_platdata(adata->dev); - struct iio_chan_spec *channels; - size_t channels_size; int err; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &accel_info; - err = st_sensors_power_enable(indio_dev); - if (err) - return err; - err = st_sensors_verify_id(indio_dev); if (err < 0) - goto st_accel_power_off; + return err; adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS; + indio_dev->channels = adata->sensor_settings->ch; indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; - channels_size = indio_dev->num_channels * sizeof(struct iio_chan_spec); - channels = devm_kmemdup(&indio_dev->dev, - adata->sensor_settings->ch, - channels_size, GFP_KERNEL); - if (!channels) { - err = -ENOMEM; - goto st_accel_power_off; + /* + * First try specific ACPI methods to retrieve orientation then try the + * generic function. + */ + err = apply_acpi_orientation(indio_dev); + if (err) { + err = iio_read_mount_matrix(adata->dev, &adata->mount_matrix); + if (err) + return err; } - if (apply_acpi_orientation(indio_dev, channels)) - dev_warn(&indio_dev->dev, - "failed to apply ACPI orientation data: %d\n", err); - - indio_dev->channels = channels; adata->current_fullscale = &adata->sensor_settings->fs.fs_avl[0]; adata->odr = adata->sensor_settings->odr.odr_avl[0].hz; @@ -1288,11 +1371,11 @@ int st_accel_common_probe(struct iio_dev *indio_dev) err = st_sensors_init_sensor(indio_dev, pdata); if (err < 0) - goto st_accel_power_off; + return err; err = st_accel_allocate_ring(indio_dev); if (err < 0) - goto st_accel_power_off; + return err; if (adata->irq > 0) { err = st_sensors_allocate_trigger(indio_dev, @@ -1315,9 +1398,6 @@ st_accel_device_register_error: st_sensors_deallocate_trigger(indio_dev); st_accel_probe_trigger_error: st_accel_deallocate_ring(indio_dev); -st_accel_power_off: - st_sensors_power_disable(indio_dev); - return err; } EXPORT_SYMBOL(st_accel_common_probe); @@ -1326,8 +1406,6 @@ void st_accel_common_remove(struct iio_dev *indio_dev) { struct st_sensor_data *adata = iio_priv(indio_dev); - st_sensors_power_disable(indio_dev); - iio_device_unregister(indio_dev); if (adata->irq > 0) st_sensors_deallocate_trigger(indio_dev); diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index 360e16f2cadb..95e305b88d5e 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -174,16 +174,29 @@ static int st_accel_i2c_probe(struct i2c_client *client) if (ret < 0) return ret; + ret = st_sensors_power_enable(indio_dev); + if (ret) + return ret; + ret = st_accel_common_probe(indio_dev); if (ret < 0) - return ret; + goto st_accel_power_off; return 0; + +st_accel_power_off: + st_sensors_power_disable(indio_dev); + + return ret; } static int st_accel_i2c_remove(struct i2c_client *client) { - st_accel_common_remove(i2c_get_clientdata(client)); + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + st_sensors_power_disable(indio_dev); + + st_accel_common_remove(indio_dev); return 0; } diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c index 568ff1bae0ee..83d3308ce5cc 100644 --- a/drivers/iio/accel/st_accel_spi.c +++ b/drivers/iio/accel/st_accel_spi.c @@ -123,16 +123,29 @@ static int st_accel_spi_probe(struct spi_device *spi) if (err < 0) return err; + err = st_sensors_power_enable(indio_dev); + if (err) + return err; + err = st_accel_common_probe(indio_dev); if (err < 0) - return err; + goto st_accel_power_off; return 0; + +st_accel_power_off: + st_sensors_power_disable(indio_dev); + + return err; } static int st_accel_spi_remove(struct spi_device *spi) { - st_accel_common_remove(spi_get_drvdata(spi)); + struct iio_dev *indio_dev = spi_get_drvdata(spi); + + st_sensors_power_disable(indio_dev); + + st_accel_common_remove(indio_dev); return 0; } diff --git a/drivers/iio/accel/stk8312.c b/drivers/iio/accel/stk8312.c index 157d8faefb9e..43c621d0f11e 100644 --- a/drivers/iio/accel/stk8312.c +++ b/drivers/iio/accel/stk8312.c @@ -7,7 +7,6 @@ * IIO driver for STK8312; 7-bit I2C address: 0x3D. */ -#include <linux/acpi.h> #include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/kernel.h> @@ -103,7 +102,11 @@ struct stk8312_data { u8 mode; struct iio_trigger *dready_trig; bool dready_trigger_on; - s8 buffer[16]; /* 3x8-bit channels + 5x8 padding + 64-bit timestamp */ + /* Ensure timestamp is naturally aligned */ + struct { + s8 chans[3]; + s64 timestamp __aligned(8); + } scan; }; static IIO_CONST_ATTR(in_accel_scale_available, STK8312_SCALE_AVAIL); @@ -438,7 +441,7 @@ static irqreturn_t stk8312_trigger_handler(int irq, void *p) ret = i2c_smbus_read_i2c_block_data(data->client, STK8312_REG_XOUT, STK8312_ALL_CHANNEL_SIZE, - data->buffer); + data->scan.chans); if (ret < STK8312_ALL_CHANNEL_SIZE) { dev_err(&data->client->dev, "register read failed\n"); mutex_unlock(&data->lock); @@ -452,12 +455,12 @@ static irqreturn_t stk8312_trigger_handler(int irq, void *p) mutex_unlock(&data->lock); goto err; } - data->buffer[i++] = ret; + data->scan.chans[i++] = ret; } } mutex_unlock(&data->lock); - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, pf->timestamp); err: iio_trigger_notify_done(indio_dev->trig); @@ -552,7 +555,7 @@ static int stk8312_probe(struct i2c_client *client, data->dready_trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!data->dready_trig) { ret = -ENOMEM; goto err_power_off; @@ -635,23 +638,17 @@ static SIMPLE_DEV_PM_OPS(stk8312_pm_ops, stk8312_suspend, stk8312_resume); #endif static const struct i2c_device_id stk8312_i2c_id[] = { - {"STK8312", 0}, + /* Deprecated in favour of lowercase form */ + { "STK8312", 0 }, + { "stk8312", 0 }, {} }; MODULE_DEVICE_TABLE(i2c, stk8312_i2c_id); -static const struct acpi_device_id stk8312_acpi_id[] = { - {"STK8312", 0}, - {} -}; - -MODULE_DEVICE_TABLE(acpi, stk8312_acpi_id); - static struct i2c_driver stk8312_driver = { .driver = { .name = STK8312_DRIVER_NAME, .pm = STK8312_PM_OPS, - .acpi_match_table = ACPI_PTR(stk8312_acpi_id), }, .probe = stk8312_probe, .remove = stk8312_remove, diff --git a/drivers/iio/accel/stk8ba50.c b/drivers/iio/accel/stk8ba50.c index 7cf9cb7e8666..e137a34b5c9a 100644 --- a/drivers/iio/accel/stk8ba50.c +++ b/drivers/iio/accel/stk8ba50.c @@ -91,12 +91,11 @@ struct stk8ba50_data { u8 sample_rate_idx; struct iio_trigger *dready_trig; bool dready_trigger_on; - /* - * 3 x 16-bit channels (10-bit data, 6-bit padding) + - * 1 x 16 padding + - * 4 x 16 64-bit timestamp - */ - s16 buffer[8]; + /* Ensure timestamp is naturally aligned */ + struct { + s16 chans[3]; + s64 timetamp __aligned(8); + } scan; }; #define STK8BA50_ACCEL_CHANNEL(index, reg, axis) { \ @@ -324,7 +323,7 @@ static irqreturn_t stk8ba50_trigger_handler(int irq, void *p) ret = i2c_smbus_read_i2c_block_data(data->client, STK8BA50_REG_XOUT, STK8BA50_ALL_CHANNEL_SIZE, - (u8 *)data->buffer); + (u8 *)data->scan.chans); if (ret < STK8BA50_ALL_CHANNEL_SIZE) { dev_err(&data->client->dev, "register read failed\n"); goto err; @@ -337,10 +336,10 @@ static irqreturn_t stk8ba50_trigger_handler(int irq, void *p) if (ret < 0) goto err; - data->buffer[i++] = ret; + data->scan.chans[i++] = ret; } } - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, pf->timestamp); err: mutex_unlock(&data->lock); @@ -448,7 +447,7 @@ static int stk8ba50_probe(struct i2c_client *client, data->dready_trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!data->dready_trig) { ret = -ENOMEM; goto err_power_off; diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index c7946c439612..db0c8fb60515 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -1190,6 +1190,18 @@ config TI_TLC4541 This driver can also be built as a module. If so, the module will be called ti-tlc4541. +config TI_TSC2046 + tristate "Texas Instruments TSC2046 ADC driver" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for ADC functionality of Texas + Instruments TSC2046 touch screen controller. + + This driver can also be built as a module. If so, the module will be + called ti-tsc2046. + config TWL4030_MADC tristate "TWL4030 MADC (Monitoring A/D Converter)" depends on TWL4030_CORE diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index a226657d19c0..f70d877c555a 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -106,6 +106,7 @@ obj-$(CONFIG_TI_ADS124S08) += ti-ads124s08.o obj-$(CONFIG_TI_ADS131E08) += ti-ads131e08.o obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o obj-$(CONFIG_TI_TLC4541) += ti-tlc4541.o +obj-$(CONFIG_TI_TSC2046) += ti-tsc2046.o obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o obj-$(CONFIG_VF610_ADC) += vf610_adc.o diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index a27db78ea13e..e45c600fccc0 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -862,6 +862,11 @@ static void ad7124_reg_disable(void *r) regulator_disable(r); } +static void ad7124_clk_disable(void *c) +{ + clk_disable_unprepare(c); +} + static int ad7124_probe(struct spi_device *spi) { const struct ad7124_chip_info *info; @@ -883,8 +888,6 @@ static int ad7124_probe(struct spi_device *spi) ad_sd_init(&st->sd, indio_dev, spi, &ad7124_sigma_delta_info); - spi_set_drvdata(spi, indio_dev); - indio_dev->name = st->chip_info->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &ad7124_info; @@ -922,48 +925,28 @@ static int ad7124_probe(struct spi_device *spi) if (ret < 0) return ret; + ret = devm_add_action_or_reset(&spi->dev, ad7124_clk_disable, st->mclk); + if (ret) + return ret; + ret = ad7124_soft_reset(st); if (ret < 0) - goto error_clk_disable_unprepare; + return ret; ret = ad7124_check_chip_id(st); if (ret) - goto error_clk_disable_unprepare; + return ret; ret = ad7124_setup(st); if (ret < 0) - goto error_clk_disable_unprepare; + return ret; - ret = ad_sd_setup_buffer_and_trigger(indio_dev); + ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev); if (ret < 0) - goto error_clk_disable_unprepare; - - ret = iio_device_register(indio_dev); - if (ret < 0) { - dev_err(&spi->dev, "Failed to register iio device\n"); - goto error_remove_trigger; - } - - return 0; - -error_remove_trigger: - ad_sd_cleanup_buffer_and_trigger(indio_dev); -error_clk_disable_unprepare: - clk_disable_unprepare(st->mclk); - - return ret; -} - -static int ad7124_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad7124_state *st = iio_priv(indio_dev); + return ret; - iio_device_unregister(indio_dev); - ad_sd_cleanup_buffer_and_trigger(indio_dev); - clk_disable_unprepare(st->mclk); + return devm_iio_device_register(&spi->dev, indio_dev); - return 0; } static const struct of_device_id ad7124_of_match[] = { @@ -981,7 +964,6 @@ static struct spi_driver ad71124_driver = { .of_match_table = ad7124_of_match, }, .probe = ad7124_probe, - .remove = ad7124_remove, }; module_spi_driver(ad71124_driver); diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c index 1141cc13a124..ee8ed9481025 100644 --- a/drivers/iio/adc/ad7192.c +++ b/drivers/iio/adc/ad7192.c @@ -326,7 +326,7 @@ static int ad7192_of_clock_select(struct ad7192_state *st) clock_sel = AD7192_CLK_INT; /* use internal clock */ - if (PTR_ERR(st->mclk) == -ENOENT) { + if (st->mclk) { if (of_property_read_bool(np, "adi,int-clock-output-enable")) clock_sel = AD7192_CLK_INT_CO; } else { @@ -908,6 +908,16 @@ static int ad7192_channels_config(struct iio_dev *indio_dev) return 0; } +static void ad7192_reg_disable(void *reg) +{ + regulator_disable(reg); +} + +static void ad7192_clk_disable(void *clk) +{ + clk_disable_unprepare(clk); +} + static int ad7192_probe(struct spi_device *spi) { struct ad7192_state *st; @@ -937,33 +947,38 @@ static int ad7192_probe(struct spi_device *spi) return ret; } + ret = devm_add_action_or_reset(&spi->dev, ad7192_reg_disable, st->avdd); + if (ret) + return ret; + st->dvdd = devm_regulator_get(&spi->dev, "dvdd"); - if (IS_ERR(st->dvdd)) { - ret = PTR_ERR(st->dvdd); - goto error_disable_avdd; - } + if (IS_ERR(st->dvdd)) + return PTR_ERR(st->dvdd); ret = regulator_enable(st->dvdd); if (ret) { dev_err(&spi->dev, "Failed to enable specified DVdd supply\n"); - goto error_disable_avdd; + return ret; } + ret = devm_add_action_or_reset(&spi->dev, ad7192_reg_disable, st->dvdd); + if (ret) + return ret; + ret = regulator_get_voltage(st->avdd); if (ret < 0) { dev_err(&spi->dev, "Device tree error, reference voltage undefined\n"); - goto error_disable_avdd; + return ret; } st->int_vref_mv = ret / 1000; - spi_set_drvdata(spi, indio_dev); st->chip_info = of_device_get_match_data(&spi->dev); indio_dev->name = st->chip_info->name; indio_dev->modes = INDIO_DIRECT_MODE; ret = ad7192_channels_config(indio_dev); if (ret < 0) - goto error_disable_dvdd; + return ret; if (st->chip_info->chip_id == CHIPID_AD7195) indio_dev->info = &ad7195_info; @@ -972,17 +987,15 @@ static int ad7192_probe(struct spi_device *spi) ad_sd_init(&st->sd, indio_dev, spi, &ad7192_sigma_delta_info); - ret = ad_sd_setup_buffer_and_trigger(indio_dev); + ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev); if (ret) - goto error_disable_dvdd; + return ret; st->fclk = AD7192_INT_FREQ_MHZ; - st->mclk = devm_clk_get(&st->sd.spi->dev, "mclk"); - if (IS_ERR(st->mclk) && PTR_ERR(st->mclk) != -ENOENT) { - ret = PTR_ERR(st->mclk); - goto error_remove_trigger; - } + st->mclk = devm_clk_get_optional(&spi->dev, "mclk"); + if (IS_ERR(st->mclk)) + return PTR_ERR(st->mclk); st->clock_sel = ad7192_of_clock_select(st); @@ -990,55 +1003,26 @@ static int ad7192_probe(struct spi_device *spi) st->clock_sel == AD7192_CLK_EXT_MCLK2) { ret = clk_prepare_enable(st->mclk); if (ret < 0) - goto error_remove_trigger; + return ret; + + ret = devm_add_action_or_reset(&spi->dev, ad7192_clk_disable, + st->mclk); + if (ret) + return ret; st->fclk = clk_get_rate(st->mclk); if (!ad7192_valid_external_frequency(st->fclk)) { - ret = -EINVAL; dev_err(&spi->dev, "External clock frequency out of bounds\n"); - goto error_disable_clk; + return -EINVAL; } } ret = ad7192_setup(st, spi->dev.of_node); if (ret) - goto error_disable_clk; - - ret = iio_device_register(indio_dev); - if (ret < 0) - goto error_disable_clk; - return 0; - -error_disable_clk: - if (st->clock_sel == AD7192_CLK_EXT_MCLK1_2 || - st->clock_sel == AD7192_CLK_EXT_MCLK2) - clk_disable_unprepare(st->mclk); -error_remove_trigger: - ad_sd_cleanup_buffer_and_trigger(indio_dev); -error_disable_dvdd: - regulator_disable(st->dvdd); -error_disable_avdd: - regulator_disable(st->avdd); - - return ret; -} - -static int ad7192_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad7192_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - if (st->clock_sel == AD7192_CLK_EXT_MCLK1_2 || - st->clock_sel == AD7192_CLK_EXT_MCLK2) - clk_disable_unprepare(st->mclk); - ad_sd_cleanup_buffer_and_trigger(indio_dev); - - regulator_disable(st->dvdd); - regulator_disable(st->avdd); + return ret; - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static const struct of_device_id ad7192_of_match[] = { @@ -1056,7 +1040,6 @@ static struct spi_driver ad7192_driver = { .of_match_table = ad7192_of_match, }, .probe = ad7192_probe, - .remove = ad7192_remove, }; module_spi_driver(ad7192_driver); diff --git a/drivers/iio/adc/ad7298.c b/drivers/iio/adc/ad7298.c index d2163cb62f4f..3f4e73f7d35a 100644 --- a/drivers/iio/adc/ad7298.c +++ b/drivers/iio/adc/ad7298.c @@ -13,6 +13,7 @@ #include <linux/regulator/consumer.h> #include <linux/err.h> #include <linux/delay.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/interrupt.h> #include <linux/bitops.h> @@ -346,6 +347,12 @@ static int ad7298_probe(struct spi_device *spi) return devm_iio_device_register(&spi->dev, indio_dev); } +static const struct acpi_device_id ad7298_acpi_ids[] = { + { "INT3494", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, ad7298_acpi_ids); + static const struct spi_device_id ad7298_id[] = { {"ad7298", 0}, {} @@ -355,6 +362,7 @@ MODULE_DEVICE_TABLE(spi, ad7298_id); static struct spi_driver ad7298_driver = { .driver = { .name = "ad7298", + .acpi_match_table = ad7298_acpi_ids, }, .probe = ad7298_probe, .id_table = ad7298_id, diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c index 9e9ff07cf972..a1e8b32671cf 100644 --- a/drivers/iio/adc/ad7476.c +++ b/drivers/iio/adc/ad7476.c @@ -32,12 +32,14 @@ struct ad7476_chip_info { /* channels used when convst gpio is defined */ struct iio_chan_spec convst_channel[2]; void (*reset)(struct ad7476_state *); + bool has_vref; + bool has_vdrive; }; struct ad7476_state { struct spi_device *spi; const struct ad7476_chip_info *chip_info; - struct regulator *reg; + struct regulator *ref_reg; struct gpio_desc *convst_gpio; struct spi_transfer xfer; struct spi_message msg; @@ -52,13 +54,17 @@ struct ad7476_state { }; enum ad7476_supported_device_ids { + ID_AD7091, ID_AD7091R, + ID_AD7273, + ID_AD7274, ID_AD7276, ID_AD7277, ID_AD7278, ID_AD7466, ID_AD7467, ID_AD7468, + ID_AD7475, ID_AD7495, ID_AD7940, ID_ADC081S, @@ -145,8 +151,8 @@ static int ad7476_read_raw(struct iio_dev *indio_dev, GENMASK(st->chip_info->channel[0].scan_type.realbits - 1, 0); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - if (!st->chip_info->int_vref_uv) { - scale_uv = regulator_get_voltage(st->reg); + if (st->ref_reg) { + scale_uv = regulator_get_voltage(st->ref_reg); if (scale_uv < 0) return scale_uv; } else { @@ -187,13 +193,32 @@ static int ad7476_read_raw(struct iio_dev *indio_dev, BIT(IIO_CHAN_INFO_RAW)) static const struct ad7476_chip_info ad7476_chip_info_tbl[] = { + [ID_AD7091] = { + .channel[0] = AD7091R_CHAN(12), + .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), + .convst_channel[0] = AD7091R_CONVST_CHAN(12), + .convst_channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), + .reset = ad7091_reset, + }, [ID_AD7091R] = { .channel[0] = AD7091R_CHAN(12), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), .convst_channel[0] = AD7091R_CONVST_CHAN(12), .convst_channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), + .int_vref_uv = 2500000, + .has_vref = true, .reset = ad7091_reset, }, + [ID_AD7273] = { + .channel[0] = AD7940_CHAN(10), + .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), + .has_vref = true, + }, + [ID_AD7274] = { + .channel[0] = AD7940_CHAN(12), + .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), + .has_vref = true, + }, [ID_AD7276] = { .channel[0] = AD7940_CHAN(12), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), @@ -218,10 +243,17 @@ static const struct ad7476_chip_info ad7476_chip_info_tbl[] = { .channel[0] = AD7476_CHAN(8), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, + [ID_AD7475] = { + .channel[0] = AD7476_CHAN(12), + .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), + .has_vref = true, + .has_vdrive = true, + }, [ID_AD7495] = { .channel[0] = AD7476_CHAN(12), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), .int_vref_uv = 2500000, + .has_vdrive = true, }, [ID_AD7940] = { .channel[0] = AD7940_CHAN(14), @@ -254,6 +286,7 @@ static const struct ad7476_chip_info ad7476_chip_info_tbl[] = { [ID_LTC2314_14] = { .channel[0] = AD7940_CHAN(14), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), + .has_vref = true, }, }; @@ -263,15 +296,16 @@ static const struct iio_info ad7476_info = { static void ad7476_reg_disable(void *data) { - struct ad7476_state *st = data; + struct regulator *reg = data; - regulator_disable(st->reg); + regulator_disable(reg); } static int ad7476_probe(struct spi_device *spi) { struct ad7476_state *st; struct iio_dev *indio_dev; + struct regulator *reg; int ret; indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); @@ -282,27 +316,79 @@ static int ad7476_probe(struct spi_device *spi) st->chip_info = &ad7476_chip_info_tbl[spi_get_device_id(spi)->driver_data]; - st->reg = devm_regulator_get(&spi->dev, "vcc"); - if (IS_ERR(st->reg)) - return PTR_ERR(st->reg); + reg = devm_regulator_get(&spi->dev, "vcc"); + if (IS_ERR(reg)) + return PTR_ERR(reg); - ret = regulator_enable(st->reg); + ret = regulator_enable(reg); if (ret) return ret; - ret = devm_add_action_or_reset(&spi->dev, ad7476_reg_disable, - st); + ret = devm_add_action_or_reset(&spi->dev, ad7476_reg_disable, reg); if (ret) return ret; + /* Either vcc or vref (below) as appropriate */ + if (!st->chip_info->int_vref_uv) + st->ref_reg = reg; + + if (st->chip_info->has_vref) { + + /* If a device has an internal reference vref is optional */ + if (st->chip_info->int_vref_uv) { + reg = devm_regulator_get_optional(&spi->dev, "vref"); + if (IS_ERR(reg) && (PTR_ERR(reg) != -ENODEV)) + return PTR_ERR(reg); + } else { + reg = devm_regulator_get(&spi->dev, "vref"); + if (IS_ERR(reg)) + return PTR_ERR(reg); + } + + if (!IS_ERR(reg)) { + ret = regulator_enable(reg); + if (ret) + return ret; + + ret = devm_add_action_or_reset(&spi->dev, + ad7476_reg_disable, + reg); + if (ret) + return ret; + st->ref_reg = reg; + } else { + /* + * Can only get here if device supports both internal + * and external reference, but the regulator connected + * to the external reference is not connected. + * Set the reference regulator pointer to NULL to + * indicate this. + */ + st->ref_reg = NULL; + } + } + + if (st->chip_info->has_vdrive) { + reg = devm_regulator_get(&spi->dev, "vdrive"); + if (IS_ERR(reg)) + return PTR_ERR(reg); + + ret = regulator_enable(reg); + if (ret) + return ret; + + ret = devm_add_action_or_reset(&spi->dev, ad7476_reg_disable, + reg); + if (ret) + return ret; + } + st->convst_gpio = devm_gpiod_get_optional(&spi->dev, "adi,conversion-start", GPIOD_OUT_LOW); if (IS_ERR(st->convst_gpio)) return PTR_ERR(st->convst_gpio); - spi_set_drvdata(spi, indio_dev); - st->spi = spi; indio_dev->name = spi_get_device_id(spi)->name; @@ -333,17 +419,17 @@ static int ad7476_probe(struct spi_device *spi) } static const struct spi_device_id ad7476_id[] = { - {"ad7091", ID_AD7091R}, + {"ad7091", ID_AD7091}, {"ad7091r", ID_AD7091R}, - {"ad7273", ID_AD7277}, - {"ad7274", ID_AD7276}, + {"ad7273", ID_AD7273}, + {"ad7274", ID_AD7274}, {"ad7276", ID_AD7276}, {"ad7277", ID_AD7277}, {"ad7278", ID_AD7278}, {"ad7466", ID_AD7466}, {"ad7467", ID_AD7467}, {"ad7468", ID_AD7468}, - {"ad7475", ID_AD7466}, + {"ad7475", ID_AD7475}, {"ad7476", ID_AD7466}, {"ad7476a", ID_AD7466}, {"ad7477", ID_AD7467}, diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index 0af0bb4d5a7f..0a60ecc69d38 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -663,7 +663,8 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, } st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", - indio_dev->name, indio_dev->id); + indio_dev->name, + iio_device_id(indio_dev)); if (!st->trig) return -ENOMEM; diff --git a/drivers/iio/adc/ad7766.c b/drivers/iio/adc/ad7766.c index 1e41759f3ee5..51ee9482e0df 100644 --- a/drivers/iio/adc/ad7766.c +++ b/drivers/iio/adc/ad7766.c @@ -248,7 +248,8 @@ static int ad7766_probe(struct spi_device *spi) if (spi->irq > 0) { ad7766->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d", - indio_dev->name, indio_dev->id); + indio_dev->name, + iio_device_id(indio_dev)); if (!ad7766->trig) return -ENOMEM; @@ -272,8 +273,6 @@ static int ad7766_probe(struct spi_device *spi) return ret; } - spi_set_drvdata(spi, indio_dev); - ad7766->spi = spi; /* First byte always 0 */ @@ -289,10 +288,7 @@ static int ad7766_probe(struct spi_device *spi) if (ret) return ret; - ret = devm_iio_device_register(&spi->dev, indio_dev); - if (ret) - return ret; - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static const struct spi_device_id ad7766_id[] = { diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c index 60f21fed6dcb..2c5c8a3672b2 100644 --- a/drivers/iio/adc/ad7768-1.c +++ b/drivers/iio/adc/ad7768-1.c @@ -614,7 +614,6 @@ static int ad7768_probe(struct spi_device *spi) st->mclk_freq = clk_get_rate(st->mclk); - spi_set_drvdata(spi, indio_dev); mutex_init(&st->lock); indio_dev->channels = ad7768_channels; @@ -630,7 +629,8 @@ static int ad7768_probe(struct spi_device *spi) } st->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d", - indio_dev->name, indio_dev->id); + indio_dev->name, + iio_device_id(indio_dev)); if (!st->trig) return -ENOMEM; diff --git a/drivers/iio/adc/ad7780.c b/drivers/iio/adc/ad7780.c index 42e7e8e595d1..42bb952f4738 100644 --- a/drivers/iio/adc/ad7780.c +++ b/drivers/iio/adc/ad7780.c @@ -300,6 +300,11 @@ static int ad7780_init_gpios(struct device *dev, struct ad7780_state *st) return 0; } +static void ad7780_reg_disable(void *reg) +{ + regulator_disable(reg); +} + static int ad7780_probe(struct spi_device *spi) { struct ad7780_state *st; @@ -318,8 +323,6 @@ static int ad7780_probe(struct spi_device *spi) st->chip_info = &ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data]; - spi_set_drvdata(spi, indio_dev); - indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = &st->chip_info->channel; @@ -340,35 +343,15 @@ static int ad7780_probe(struct spi_device *spi) return ret; } - ret = ad_sd_setup_buffer_and_trigger(indio_dev); + ret = devm_add_action_or_reset(&spi->dev, ad7780_reg_disable, st->reg); if (ret) - goto error_disable_reg; + return ret; - ret = iio_device_register(indio_dev); + ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev); if (ret) - goto error_cleanup_buffer_and_trigger; - - return 0; - -error_cleanup_buffer_and_trigger: - ad_sd_cleanup_buffer_and_trigger(indio_dev); -error_disable_reg: - regulator_disable(st->reg); - - return ret; -} - -static int ad7780_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad7780_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - ad_sd_cleanup_buffer_and_trigger(indio_dev); - - regulator_disable(st->reg); + return ret; - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static const struct spi_device_id ad7780_id[] = { @@ -385,7 +368,6 @@ static struct spi_driver ad7780_driver = { .name = "ad7780", }, .probe = ad7780_probe, - .remove = ad7780_remove, .id_table = ad7780_id, }; module_spi_driver(ad7780_driver); diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c index d57ad966e17c..cb579aa89f39 100644 --- a/drivers/iio/adc/ad7791.c +++ b/drivers/iio/adc/ad7791.c @@ -394,6 +394,11 @@ static int ad7791_setup(struct ad7791_state *st, st->mode); } +static void ad7791_reg_disable(void *reg) +{ + regulator_disable(reg); +} + static int ad7791_probe(struct spi_device *spi) { struct ad7791_platform_data *pdata = spi->dev.platform_data; @@ -420,11 +425,13 @@ static int ad7791_probe(struct spi_device *spi) if (ret) return ret; + ret = devm_add_action_or_reset(&spi->dev, ad7791_reg_disable, st->reg); + if (ret) + return ret; + st->info = &ad7791_chip_infos[spi_get_device_id(spi)->driver_data]; ad_sd_init(&st->sd, indio_dev, spi, &ad7791_sigma_delta_info); - spi_set_drvdata(spi, indio_dev); - indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = st->info->channels; @@ -434,39 +441,15 @@ static int ad7791_probe(struct spi_device *spi) else indio_dev->info = &ad7791_no_filter_info; - ret = ad_sd_setup_buffer_and_trigger(indio_dev); + ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev); if (ret) - goto error_disable_reg; + return ret; ret = ad7791_setup(st, pdata); if (ret) - goto error_remove_trigger; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_remove_trigger; - - return 0; - -error_remove_trigger: - ad_sd_cleanup_buffer_and_trigger(indio_dev); -error_disable_reg: - regulator_disable(st->reg); - - return ret; -} - -static int ad7791_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad7791_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - ad_sd_cleanup_buffer_and_trigger(indio_dev); - - regulator_disable(st->reg); + return ret; - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static const struct spi_device_id ad7791_spi_ids[] = { @@ -484,7 +467,6 @@ static struct spi_driver ad7791_driver = { .name = "ad7791", }, .probe = ad7791_probe, - .remove = ad7791_remove, .id_table = ad7791_spi_ids, }; module_spi_driver(ad7791_driver); diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c index 440ef4c7be07..ef3e2d3ecb0c 100644 --- a/drivers/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c @@ -769,6 +769,11 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { }, }; +static void ad7793_reg_disable(void *reg) +{ + regulator_disable(reg); +} + static int ad7793_probe(struct spi_device *spi) { const struct ad7793_platform_data *pdata = spi->dev.platform_data; @@ -803,11 +808,13 @@ static int ad7793_probe(struct spi_device *spi) if (ret) return ret; + ret = devm_add_action_or_reset(&spi->dev, ad7793_reg_disable, st->reg); + if (ret) + return ret; + vref_mv = regulator_get_voltage(st->reg); - if (vref_mv < 0) { - ret = vref_mv; - goto error_disable_reg; - } + if (vref_mv < 0) + return vref_mv; vref_mv /= 1000; } else { @@ -817,50 +824,21 @@ static int ad7793_probe(struct spi_device *spi) st->chip_info = &ad7793_chip_info_tbl[spi_get_device_id(spi)->driver_data]; - spi_set_drvdata(spi, indio_dev); - indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = st->chip_info->channels; indio_dev->num_channels = st->chip_info->num_channels; indio_dev->info = st->chip_info->iio_info; - ret = ad_sd_setup_buffer_and_trigger(indio_dev); + ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev); if (ret) - goto error_disable_reg; + return ret; ret = ad7793_setup(indio_dev, pdata, vref_mv); if (ret) - goto error_remove_trigger; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_remove_trigger; - - return 0; - -error_remove_trigger: - ad_sd_cleanup_buffer_and_trigger(indio_dev); -error_disable_reg: - if (pdata->refsel != AD7793_REFSEL_INTERNAL) - regulator_disable(st->reg); - - return ret; -} - -static int ad7793_remove(struct spi_device *spi) -{ - const struct ad7793_platform_data *pdata = spi->dev.platform_data; - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad7793_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - ad_sd_cleanup_buffer_and_trigger(indio_dev); - - if (pdata->refsel != AD7793_REFSEL_INTERNAL) - regulator_disable(st->reg); + return ret; - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static const struct spi_device_id ad7793_id[] = { @@ -882,7 +860,6 @@ static struct spi_driver ad7793_driver = { .name = "ad7793", }, .probe = ad7793_probe, - .remove = ad7793_remove, .id_table = ad7793_id, }; module_spi_driver(ad7793_driver); diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c index 9b3cbe1ddc6f..f64999714a4d 100644 --- a/drivers/iio/adc/ad7887.c +++ b/drivers/iio/adc/ad7887.c @@ -268,7 +268,6 @@ static int ad7887_probe(struct spi_device *spi) st->chip_info = &ad7887_chip_info_tbl[spi_get_device_id(spi)->driver_data]; - spi_set_drvdata(spi, indio_dev); st->spi = spi; indio_dev->name = spi_get_device_id(spi)->name; diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c index 19a45dd43796..dbfc8517cb8a 100644 --- a/drivers/iio/adc/ad9467.c +++ b/drivers/iio/adc/ad9467.c @@ -434,8 +434,6 @@ static int ad9467_probe(struct spi_device *spi) mdelay(10); } - spi_set_drvdata(spi, st); - conv->chip_info = &info->axi_adc_info; id = ad9467_spi_read(spi, AN877_ADC_REG_CHIP_ID); diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index e777ec718973..1d652d9b2f5c 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -470,91 +470,65 @@ EXPORT_SYMBOL_GPL(ad_sd_validate_trigger); static const struct iio_trigger_ops ad_sd_trigger_ops = { }; -static int ad_sd_probe_trigger(struct iio_dev *indio_dev) +static int devm_ad_sd_probe_trigger(struct device *dev, struct iio_dev *indio_dev) { struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev); int ret; - sigma_delta->trig = iio_trigger_alloc(&sigma_delta->spi->dev, - "%s-dev%d", indio_dev->name, - indio_dev->id); - if (sigma_delta->trig == NULL) { - ret = -ENOMEM; - goto error_ret; + if (dev != &sigma_delta->spi->dev) { + dev_err(dev, "Trigger parent should be '%s', got '%s'\n", + dev_name(dev), dev_name(&sigma_delta->spi->dev)); + return -EFAULT; } + + sigma_delta->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, + iio_device_id(indio_dev)); + if (sigma_delta->trig == NULL) + return -ENOMEM; + sigma_delta->trig->ops = &ad_sd_trigger_ops; init_completion(&sigma_delta->completion); sigma_delta->irq_dis = true; - ret = request_irq(sigma_delta->spi->irq, - ad_sd_data_rdy_trig_poll, - sigma_delta->info->irq_flags | IRQF_NO_AUTOEN, - indio_dev->name, - sigma_delta); + ret = devm_request_irq(dev, sigma_delta->spi->irq, + ad_sd_data_rdy_trig_poll, + sigma_delta->info->irq_flags | IRQF_NO_AUTOEN, + indio_dev->name, + sigma_delta); if (ret) - goto error_free_trig; + return ret; iio_trigger_set_drvdata(sigma_delta->trig, sigma_delta); - ret = iio_trigger_register(sigma_delta->trig); + ret = devm_iio_trigger_register(dev, sigma_delta->trig); if (ret) - goto error_free_irq; + return ret; /* select default trigger */ indio_dev->trig = iio_trigger_get(sigma_delta->trig); return 0; - -error_free_irq: - free_irq(sigma_delta->spi->irq, sigma_delta); -error_free_trig: - iio_trigger_free(sigma_delta->trig); -error_ret: - return ret; -} - -static void ad_sd_remove_trigger(struct iio_dev *indio_dev) -{ - struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev); - - iio_trigger_unregister(sigma_delta->trig); - free_irq(sigma_delta->spi->irq, sigma_delta); - iio_trigger_free(sigma_delta->trig); } /** - * ad_sd_setup_buffer_and_trigger() - + * devm_ad_sd_setup_buffer_and_trigger() - Device-managed buffer & trigger setup + * @dev: Device object to which to bind the life-time of the resources attached * @indio_dev: The IIO device */ -int ad_sd_setup_buffer_and_trigger(struct iio_dev *indio_dev) +int devm_ad_sd_setup_buffer_and_trigger(struct device *dev, struct iio_dev *indio_dev) { int ret; - ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, - &ad_sd_trigger_handler, &ad_sd_buffer_setup_ops); + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, + &iio_pollfunc_store_time, + &ad_sd_trigger_handler, + &ad_sd_buffer_setup_ops); if (ret) return ret; - ret = ad_sd_probe_trigger(indio_dev); - if (ret) { - iio_triggered_buffer_cleanup(indio_dev); - return ret; - } - - return 0; -} -EXPORT_SYMBOL_GPL(ad_sd_setup_buffer_and_trigger); - -/** - * ad_sd_cleanup_buffer_and_trigger() - - * @indio_dev: The IIO device - */ -void ad_sd_cleanup_buffer_and_trigger(struct iio_dev *indio_dev) -{ - ad_sd_remove_trigger(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); + return devm_ad_sd_probe_trigger(dev, indio_dev); } -EXPORT_SYMBOL_GPL(ad_sd_cleanup_buffer_and_trigger); +EXPORT_SYMBOL_GPL(devm_ad_sd_setup_buffer_and_trigger); /** * ad_sd_init() - Initializes a ad_sigma_delta struct diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c index d5f6ffc5b5bc..a73e3c2d212f 100644 --- a/drivers/iio/adc/adi-axi-adc.c +++ b/drivers/iio/adc/adi-axi-adc.c @@ -202,29 +202,25 @@ static void adi_axi_adc_conv_unregister(struct adi_axi_adc_conv *conv) kfree(cl); } -static void devm_adi_axi_adc_conv_release(struct device *dev, void *res) +static void devm_adi_axi_adc_conv_release(void *conv) { - adi_axi_adc_conv_unregister(*(struct adi_axi_adc_conv **)res); + adi_axi_adc_conv_unregister(conv); } struct adi_axi_adc_conv *devm_adi_axi_adc_conv_register(struct device *dev, size_t sizeof_priv) { - struct adi_axi_adc_conv **ptr, *conv; - - ptr = devres_alloc(devm_adi_axi_adc_conv_release, sizeof(*ptr), - GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); + struct adi_axi_adc_conv *conv; + int ret; conv = adi_axi_adc_conv_register(dev, sizeof_priv); - if (IS_ERR(conv)) { - devres_free(ptr); - return ERR_CAST(conv); - } + if (IS_ERR(conv)) + return conv; - *ptr = conv; - devres_add(dev, ptr); + ret = devm_add_action_or_reset(dev, devm_adi_axi_adc_conv_release, + conv); + if (ret) + return ERR_PTR(ret); return conv; } diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index a7826f097b95..ea5ca163d879 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -403,7 +403,8 @@ struct at91_adc_state { struct at91_adc_dma dma_st; struct at91_adc_touch touch_st; struct iio_dev *indio_dev; - u16 buffer[AT91_BUFFER_MAX_HWORDS]; + /* Ensure naturally aligned timestamp */ + u16 buffer[AT91_BUFFER_MAX_HWORDS] __aligned(8); /* * lock to prevent concurrent 'single conversion' requests through * sysfs. @@ -997,7 +998,7 @@ static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio, int ret; trig = devm_iio_trigger_alloc(&indio->dev, "%s-dev%d-%s", indio->name, - indio->id, trigger_name); + iio_device_id(indio), trigger_name); if (!trig) return NULL; diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 0b5f0c91d0d7..5a7d3a3a5fa8 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -547,7 +547,7 @@ static int at91_adc_get_trigger_value_by_name(struct iio_dev *idev, char *name = kasprintf(GFP_KERNEL, "%s-dev%d-%s", idev->name, - idev->id, + iio_device_id(idev), triggers[i].name); if (!name) return -ENOMEM; @@ -626,7 +626,7 @@ static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *idev, int ret; trig = iio_trigger_alloc(idev->dev.parent, "%s-dev%d-%s", idev->name, - idev->id, trigger->name); + iio_device_id(idev), trigger->name); if (trig == NULL) return NULL; diff --git a/drivers/iio/adc/dln2-adc.c b/drivers/iio/adc/dln2-adc.c index 0d53ef18e045..16407664182c 100644 --- a/drivers/iio/adc/dln2-adc.c +++ b/drivers/iio/adc/dln2-adc.c @@ -649,7 +649,8 @@ static int dln2_adc_probe(struct platform_device *pdev) indio_dev->setup_ops = &dln2_adc_buffer_setup_ops; dln2->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", - indio_dev->name, indio_dev->id); + indio_dev->name, + iio_device_id(indio_dev)); if (!dln2->trig) { dev_err(dev, "failed to allocate trigger\n"); return -ENOMEM; diff --git a/drivers/iio/adc/ep93xx_adc.c b/drivers/iio/adc/ep93xx_adc.c index c08ab3c6dfaf..a10a4e8d94fd 100644 --- a/drivers/iio/adc/ep93xx_adc.c +++ b/drivers/iio/adc/ep93xx_adc.c @@ -165,10 +165,8 @@ static int ep93xx_adc_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(priv->base)) { - dev_err(&pdev->dev, "Cannot map memory resource\n"); + if (IS_ERR(priv->base)) return PTR_ERR(priv->base); - } iiodev->name = dev_name(&pdev->dev); iiodev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c index 8c98d8c9ab1f..3b3868aa2533 100644 --- a/drivers/iio/adc/exynos_adc.c +++ b/drivers/iio/adc/exynos_adc.c @@ -794,7 +794,7 @@ static int exynos_adc_probe(struct platform_device *pdev) struct s3c2410_ts_mach_info *pdata = dev_get_platdata(&pdev->dev); struct iio_dev *indio_dev = NULL; bool has_ts = false; - int ret = -ENODEV; + int ret; int irq; indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct exynos_adc)); diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c index 074c30970465..8b353e26668e 100644 --- a/drivers/iio/adc/hi8435.c +++ b/drivers/iio/adc/hi8435.c @@ -483,7 +483,6 @@ static int hi8435_probe(struct spi_device *spi) gpiod_set_value_cansleep(reset_gpio, 1); } - spi_set_drvdata(spi, idev); mutex_init(&priv->lock); idev->name = spi_get_device_id(spi)->name; diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c index 6a173531d355..f7ee856a6b8b 100644 --- a/drivers/iio/adc/hx711.c +++ b/drivers/iio/adc/hx711.c @@ -86,9 +86,9 @@ struct hx711_data { struct mutex lock; /* * triggered buffer - * 2x32-bit channel + 64-bit timestamp + * 2x32-bit channel + 64-bit naturally aligned timestamp */ - u32 buffer[4]; + u32 buffer[4] __aligned(8); /* * delay after a rising edge on SCK until the data is ready DOUT * this is dependent on the hx711 where the datasheet tells a diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index 2ae54258b221..a4b2ff9e0dd5 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -843,7 +843,8 @@ static int ina2xx_buffer_enable(struct iio_dev *indio_dev) chip->allow_async_readout); task = kthread_create(ina2xx_capture_thread, (void *)indio_dev, - "%s:%d-%uus", indio_dev->name, indio_dev->id, + "%s:%d-%uus", indio_dev->name, + iio_device_id(indio_dev), sampling_us); if (IS_ERR(task)) return PTR_ERR(task); diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c index e3c8ec107722..655ab02d03d8 100644 --- a/drivers/iio/adc/max1027.c +++ b/drivers/iio/adc/max1027.c @@ -430,8 +430,6 @@ static int max1027_probe(struct spi_device *spi) return -ENOMEM; } - spi_set_drvdata(spi, indio_dev); - st = iio_priv(indio_dev); st->spi = spi; st->info = &max1027_chip_info_tbl[spi_get_device_id(spi)->driver_data]; diff --git a/drivers/iio/adc/max11100.c b/drivers/iio/adc/max11100.c index 6cf21758ca66..eb1ce6a0315c 100644 --- a/drivers/iio/adc/max11100.c +++ b/drivers/iio/adc/max11100.c @@ -12,6 +12,7 @@ #include <linux/module.h> #include <linux/regulator/consumer.h> #include <linux/spi/spi.h> +#include <asm/unaligned.h> #include <linux/iio/iio.h> #include <linux/iio/driver.h> @@ -63,7 +64,7 @@ static int max11100_read_single(struct iio_dev *indio_dev, int *val) return -EINVAL; } - *val = (state->buffer[1] << 8) | state->buffer[2]; + *val = get_unaligned_be16(&state->buffer[1]); return 0; } @@ -101,6 +102,11 @@ static const struct iio_info max11100_info = { .read_raw = max11100_read_raw, }; +static void max11100_regulator_disable(void *reg) +{ + regulator_disable(reg); +} + static int max11100_probe(struct spi_device *spi) { int ret; @@ -111,8 +117,6 @@ static int max11100_probe(struct spi_device *spi) if (!indio_dev) return -ENOMEM; - spi_set_drvdata(spi, indio_dev); - state = iio_priv(indio_dev); state->spi = spi; @@ -130,27 +134,12 @@ static int max11100_probe(struct spi_device *spi) if (ret) return ret; - ret = iio_device_register(indio_dev); + ret = devm_add_action_or_reset(&spi->dev, max11100_regulator_disable, + state->vref_reg); if (ret) - goto disable_regulator; - - return 0; - -disable_regulator: - regulator_disable(state->vref_reg); - - return ret; -} - -static int max11100_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct max11100_state *state = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - regulator_disable(state->vref_reg); + return ret; - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static const struct of_device_id max11100_ids[] = { @@ -165,7 +154,6 @@ static struct spi_driver max11100_driver = { .of_match_table = max11100_ids, }, .probe = max11100_probe, - .remove = max11100_remove, }; module_spi_driver(max11100_driver); diff --git a/drivers/iio/adc/max1118.c b/drivers/iio/adc/max1118.c index 6efb0b43d938..8cec9d949083 100644 --- a/drivers/iio/adc/max1118.c +++ b/drivers/iio/adc/max1118.c @@ -66,9 +66,8 @@ static const struct iio_chan_spec max1118_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(2), }; -static int max1118_read(struct spi_device *spi, int channel) +static int max1118_read(struct iio_dev *indio_dev, int channel) { - struct iio_dev *indio_dev = spi_get_drvdata(spi); struct max1118 *adc = iio_priv(indio_dev); struct spi_transfer xfers[] = { /* @@ -103,9 +102,9 @@ static int max1118_read(struct spi_device *spi, int channel) int ret; if (channel == 0) - ret = spi_sync_transfer(spi, xfers + 1, 2); + ret = spi_sync_transfer(adc->spi, xfers + 1, 2); else - ret = spi_sync_transfer(spi, xfers, 3); + ret = spi_sync_transfer(adc->spi, xfers, 3); if (ret) return ret; @@ -113,11 +112,10 @@ static int max1118_read(struct spi_device *spi, int channel) return adc->data; } -static int max1118_get_vref_mV(struct spi_device *spi) +static int max1118_get_vref_mV(struct iio_dev *indio_dev) { - struct iio_dev *indio_dev = spi_get_drvdata(spi); struct max1118 *adc = iio_priv(indio_dev); - const struct spi_device_id *id = spi_get_device_id(spi); + const struct spi_device_id *id = spi_get_device_id(adc->spi); int vref_uV; switch (id->driver_data) { @@ -144,14 +142,14 @@ static int max1118_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: mutex_lock(&adc->lock); - *val = max1118_read(adc->spi, chan->channel); + *val = max1118_read(indio_dev, chan->channel); mutex_unlock(&adc->lock); if (*val < 0) return *val; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - *val = max1118_get_vref_mV(adc->spi); + *val = max1118_get_vref_mV(indio_dev); if (*val < 0) return *val; *val2 = 8; @@ -180,7 +178,7 @@ static irqreturn_t max1118_trigger_handler(int irq, void *p) indio_dev->masklength) { const struct iio_chan_spec *scan_chan = &indio_dev->channels[scan_index]; - int ret = max1118_read(adc->spi, scan_chan->channel); + int ret = max1118_read(indio_dev, scan_chan->channel); if (ret < 0) { dev_warn(&adc->spi->dev, @@ -201,6 +199,11 @@ out: return IRQ_HANDLED; } +static void max1118_reg_disable(void *reg) +{ + regulator_disable(reg); +} + static int max1118_probe(struct spi_device *spi) { struct iio_dev *indio_dev; @@ -225,9 +228,13 @@ static int max1118_probe(struct spi_device *spi) ret = regulator_enable(adc->reg); if (ret) return ret; - } - spi_set_drvdata(spi, indio_dev); + ret = devm_add_action_or_reset(&spi->dev, max1118_reg_disable, + adc->reg); + if (ret) + return ret; + + } indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &max1118_info; @@ -241,40 +248,14 @@ static int max1118_probe(struct spi_device *spi) * a conversion has been completed, the MAX1117/MAX1118/MAX1119 will go * into AutoShutdown mode until the next conversion is initiated. */ - max1118_read(spi, 0); - - ret = iio_triggered_buffer_setup(indio_dev, NULL, - max1118_trigger_handler, NULL); - if (ret) - goto err_reg_disable; + max1118_read(indio_dev, 0); - ret = iio_device_register(indio_dev); + ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL, + max1118_trigger_handler, NULL); if (ret) - goto err_buffer_cleanup; - - return 0; - -err_buffer_cleanup: - iio_triggered_buffer_cleanup(indio_dev); -err_reg_disable: - if (id->driver_data == max1118) - regulator_disable(adc->reg); - - return ret; -} - -static int max1118_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct max1118 *adc = iio_priv(indio_dev); - const struct spi_device_id *id = spi_get_device_id(spi); - - iio_device_unregister(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - if (id->driver_data == max1118) - return regulator_disable(adc->reg); + return ret; - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static const struct spi_device_id max1118_id[] = { @@ -299,7 +280,6 @@ static struct spi_driver max1118_spi_driver = { .of_match_table = max1118_dt_ids, }, .probe = max1118_probe, - .remove = max1118_remove, .id_table = max1118_id, }; module_spi_driver(max1118_spi_driver); diff --git a/drivers/iio/adc/max1241.c b/drivers/iio/adc/max1241.c index 0cbbb3c56d08..b60f8448f21a 100644 --- a/drivers/iio/adc/max1241.c +++ b/drivers/iio/adc/max1241.c @@ -147,8 +147,6 @@ static int max1241_probe(struct spi_device *spi) adc->spi = spi; mutex_init(&adc->lock); - spi_set_drvdata(spi, indio_dev); - adc->vdd = devm_regulator_get(dev, "vdd"); if (IS_ERR(adc->vdd)) { dev_err(dev, "failed to get vdd regulator\n"); diff --git a/drivers/iio/adc/mp2629_adc.c b/drivers/iio/adc/mp2629_adc.c index 331a9a728217..aca084f1e78a 100644 --- a/drivers/iio/adc/mp2629_adc.c +++ b/drivers/iio/adc/mp2629_adc.c @@ -144,7 +144,6 @@ static int mp2629_adc_probe(struct platform_device *pdev) } indio_dev->name = "mp2629-adc"; - indio_dev->dev.parent = dev; indio_dev->channels = mp2629_channels; indio_dev->num_channels = ARRAY_SIZE(mp2629_channels); indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/mt6360-adc.c b/drivers/iio/adc/mt6360-adc.c index 6b39a139ce28..07c0e6768391 100644 --- a/drivers/iio/adc/mt6360-adc.c +++ b/drivers/iio/adc/mt6360-adc.c @@ -337,7 +337,6 @@ static int mt6360_adc_probe(struct platform_device *pdev) } indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &mt6360_adc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = mt6360_adc_channels; diff --git a/drivers/iio/adc/mxs-lradc-adc.c b/drivers/iio/adc/mxs-lradc-adc.c index 30e29f44ebd2..bca79a93cbe4 100644 --- a/drivers/iio/adc/mxs-lradc-adc.c +++ b/drivers/iio/adc/mxs-lradc-adc.c @@ -115,7 +115,8 @@ struct mxs_lradc_adc { struct device *dev; void __iomem *base; - u32 buffer[10]; + /* Maximum of 8 channels + 8 byte ts */ + u32 buffer[10] __aligned(8); struct iio_trigger *trig; struct completion completion; spinlock_t lock; @@ -455,7 +456,7 @@ static int mxs_lradc_adc_trigger_init(struct iio_dev *iio) struct mxs_lradc_adc *adc = iio_priv(iio); trig = devm_iio_trigger_alloc(&iio->dev, "%s-dev%i", iio->name, - iio->id); + iio_device_id(iio)); if (!trig) return -ENOMEM; diff --git a/drivers/iio/adc/rcar-gyroadc.c b/drivers/iio/adc/rcar-gyroadc.c index 9f38cf3c7dc2..a48895046408 100644 --- a/drivers/iio/adc/rcar-gyroadc.c +++ b/drivers/iio/adc/rcar-gyroadc.c @@ -162,18 +162,13 @@ static const struct iio_chan_spec rcar_gyroadc_iio_channels_3[] = { static int rcar_gyroadc_set_power(struct rcar_gyroadc *priv, bool on) { struct device *dev = priv->dev; - int ret; if (on) { - ret = pm_runtime_get_sync(dev); - if (ret < 0) - pm_runtime_put_noidle(dev); + return pm_runtime_resume_and_get(dev); } else { pm_runtime_mark_last_busy(dev); - ret = pm_runtime_put_autosuspend(dev); + return pm_runtime_put_autosuspend(dev); } - - return ret; } static int rcar_gyroadc_read_raw(struct iio_dev *indio_dev, @@ -535,7 +530,10 @@ static int rcar_gyroadc_probe(struct platform_device *pdev) pm_runtime_use_autosuspend(dev); pm_runtime_enable(dev); - pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret) + goto err_power_up; + rcar_gyroadc_hw_init(priv); rcar_gyroadc_hw_start(priv); @@ -552,6 +550,7 @@ static int rcar_gyroadc_probe(struct platform_device *pdev) err_iio_device_register: rcar_gyroadc_hw_stop(priv); pm_runtime_put_sync(dev); +err_power_up: pm_runtime_disable(dev); pm_runtime_set_suspended(dev); clk_disable_unprepare(priv->clk); diff --git a/drivers/iio/adc/sc27xx_adc.c b/drivers/iio/adc/sc27xx_adc.c index 301cf66de695..00098caf6d9e 100644 --- a/drivers/iio/adc/sc27xx_adc.c +++ b/drivers/iio/adc/sc27xx_adc.c @@ -549,6 +549,7 @@ static const struct of_device_id sc27xx_adc_of_match[] = { { .compatible = "sprd,sc2731-adc", }, { } }; +MODULE_DEVICE_TABLE(of, sc27xx_adc_of_match); static struct platform_driver sc27xx_adc_driver = { .probe = sc27xx_adc_probe, diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index b25386b19373..5088de835bb1 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -449,7 +449,7 @@ static const struct stm32_adc_regspec stm32h7_adc_regspec = { .smp_bits = stm32h7_smp_bits, }; -/** +/* * STM32 ADC registers access routines * @adc: stm32 adc instance * @reg: reg offset in adc instance @@ -851,7 +851,7 @@ static int stm32h7_adc_restore_selfcalib(struct iio_dev *indio_dev) return 0; } -/** +/* * Fixed timeout value for ADC calibration. * worst cases: * - low clock frequency @@ -1158,11 +1158,9 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev, adc->bufi = 0; - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - pm_runtime_put_noidle(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) return ret; - } /* Apply sampling time settings */ stm32_adc_writel(adc, regs->smpr[0], adc->smpr_val[0]); @@ -1364,11 +1362,9 @@ static int stm32_adc_update_scan_mode(struct iio_dev *indio_dev, struct device *dev = indio_dev->dev.parent; int ret; - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - pm_runtime_put_noidle(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) return ret; - } adc->num_conv = bitmap_weight(scan_mask, indio_dev->masklength); @@ -1413,11 +1409,9 @@ static int stm32_adc_debugfs_reg_access(struct iio_dev *indio_dev, struct device *dev = indio_dev->dev.parent; int ret; - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - pm_runtime_put_noidle(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) return ret; - } if (!readval) stm32_adc_writel(adc, reg, writeval); @@ -1537,11 +1531,9 @@ static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev) struct device *dev = indio_dev->dev.parent; int ret; - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - pm_runtime_put_noidle(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) return ret; - } ret = stm32_adc_set_trig(indio_dev, indio_dev->trig); if (ret) { diff --git a/drivers/iio/adc/stm32-dfsdm-core.c b/drivers/iio/adc/stm32-dfsdm-core.c index bb925a11c8ae..a627af9a825e 100644 --- a/drivers/iio/adc/stm32-dfsdm-core.c +++ b/drivers/iio/adc/stm32-dfsdm-core.c @@ -135,11 +135,9 @@ int stm32_dfsdm_start_dfsdm(struct stm32_dfsdm *dfsdm) int ret; if (atomic_inc_return(&priv->n_active_ch) == 1) { - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - pm_runtime_put_noidle(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) goto error_ret; - } /* select clock source, e.g. 0 for "dfsdm" or 1 for "audio" */ clk_src = priv->aclk ? 1 : 0; diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c index b64718daa201..16fc608db36a 100644 --- a/drivers/iio/adc/ti-adc081c.c +++ b/drivers/iio/adc/ti-adc081c.c @@ -146,6 +146,11 @@ out: return IRQ_HANDLED; } +static void adc081c_reg_disable(void *reg) +{ + regulator_disable(reg); +} + static int adc081c_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -175,6 +180,11 @@ static int adc081c_probe(struct i2c_client *client, if (err < 0) return err; + err = devm_add_action_or_reset(&client->dev, adc081c_reg_disable, + adc->ref); + if (err) + return err; + iio->name = dev_name(&client->dev); iio->modes = INDIO_DIRECT_MODE; iio->info = &adc081c_info; @@ -182,38 +192,14 @@ static int adc081c_probe(struct i2c_client *client, iio->channels = model->channels; iio->num_channels = ADC081C_NUM_CHANNELS; - err = iio_triggered_buffer_setup(iio, NULL, adc081c_trigger_handler, NULL); + err = devm_iio_triggered_buffer_setup(&client->dev, iio, NULL, + adc081c_trigger_handler, NULL); if (err < 0) { dev_err(&client->dev, "iio triggered buffer setup failed\n"); - goto err_regulator_disable; + return err; } - err = iio_device_register(iio); - if (err < 0) - goto err_buffer_cleanup; - - i2c_set_clientdata(client, iio); - - return 0; - -err_buffer_cleanup: - iio_triggered_buffer_cleanup(iio); -err_regulator_disable: - regulator_disable(adc->ref); - - return err; -} - -static int adc081c_remove(struct i2c_client *client) -{ - struct iio_dev *iio = i2c_get_clientdata(client); - struct adc081c *adc = iio_priv(iio); - - iio_device_unregister(iio); - iio_triggered_buffer_cleanup(iio); - regulator_disable(adc->ref); - - return 0; + return devm_iio_device_register(&client->dev, iio); } static const struct i2c_device_id adc081c_id[] = { @@ -238,7 +224,6 @@ static struct i2c_driver adc081c_driver = { .of_match_table = adc081c_of_match, }, .probe = adc081c_probe, - .remove = adc081c_remove, .id_table = adc081c_id, }; module_i2c_driver(adc081c_driver); diff --git a/drivers/iio/adc/ti-adc0832.c b/drivers/iio/adc/ti-adc0832.c index 0261b3cfc92b..fb5e72600b96 100644 --- a/drivers/iio/adc/ti-adc0832.c +++ b/drivers/iio/adc/ti-adc0832.c @@ -236,6 +236,11 @@ out: return IRQ_HANDLED; } +static void adc0832_reg_disable(void *reg) +{ + regulator_disable(reg); +} + static int adc0832_probe(struct spi_device *spi) { struct iio_dev *indio_dev; @@ -287,36 +292,17 @@ static int adc0832_probe(struct spi_device *spi) if (ret) return ret; - spi_set_drvdata(spi, indio_dev); - - ret = iio_triggered_buffer_setup(indio_dev, NULL, - adc0832_trigger_handler, NULL); + ret = devm_add_action_or_reset(&spi->dev, adc0832_reg_disable, + adc->reg); if (ret) - goto err_reg_disable; + return ret; - ret = iio_device_register(indio_dev); + ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL, + adc0832_trigger_handler, NULL); if (ret) - goto err_buffer_cleanup; - - return 0; -err_buffer_cleanup: - iio_triggered_buffer_cleanup(indio_dev); -err_reg_disable: - regulator_disable(adc->reg); - - return ret; -} - -static int adc0832_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct adc0832 *adc = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - regulator_disable(adc->reg); + return ret; - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static const struct of_device_id adc0832_dt_ids[] = { @@ -343,7 +329,6 @@ static struct spi_driver adc0832_driver = { .of_match_table = adc0832_dt_ids, }, .probe = adc0832_probe, - .remove = adc0832_remove, .id_table = adc0832_id, }; module_spi_driver(adc0832_driver); diff --git a/drivers/iio/adc/ti-adc084s021.c b/drivers/iio/adc/ti-adc084s021.c index 33aea961d850..ce3f5a3814f9 100644 --- a/drivers/iio/adc/ti-adc084s021.c +++ b/drivers/iio/adc/ti-adc084s021.c @@ -210,9 +210,6 @@ static int adc084s021_probe(struct spi_device *spi) adc = iio_priv(indio_dev); adc->spi = spi; - /* Connect the SPI device and the iio dev */ - spi_set_drvdata(spi, indio_dev); - /* Initiate the Industrial I/O device */ indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/ti-adc108s102.c b/drivers/iio/adc/ti-adc108s102.c index 183b2245e89b..db902aef2abe 100644 --- a/drivers/iio/adc/ti-adc108s102.c +++ b/drivers/iio/adc/ti-adc108s102.c @@ -215,6 +215,11 @@ static const struct iio_info adc108s102_info = { .update_scan_mode = &adc108s102_update_scan_mode, }; +static void adc108s102_reg_disable(void *reg) +{ + regulator_disable(reg); +} + static int adc108s102_probe(struct spi_device *spi) { struct adc108s102_state *st; @@ -239,6 +244,10 @@ static int adc108s102_probe(struct spi_device *spi) dev_err(&spi->dev, "Cannot enable vref regulator\n"); return ret; } + ret = devm_add_action_or_reset(&spi->dev, adc108s102_reg_disable, + st->reg); + if (ret) + return ret; ret = regulator_get_voltage(st->reg); if (ret < 0) { @@ -249,7 +258,6 @@ static int adc108s102_probe(struct spi_device *spi) st->va_millivolt = ret / 1000; } - spi_set_drvdata(spi, indio_dev); st->spi = spi; indio_dev->name = spi->modalias; @@ -266,40 +274,18 @@ static int adc108s102_probe(struct spi_device *spi) spi_message_init_with_transfers(&st->scan_single_msg, &st->scan_single_xfer, 1); - ret = iio_triggered_buffer_setup(indio_dev, NULL, - &adc108s102_trigger_handler, NULL); + ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL, + &adc108s102_trigger_handler, + NULL); if (ret) - goto error_disable_reg; + return ret; - ret = iio_device_register(indio_dev); - if (ret) { + ret = devm_iio_device_register(&spi->dev, indio_dev); + if (ret) dev_err(&spi->dev, "Failed to register IIO device\n"); - goto error_cleanup_triggered_buffer; - } - return 0; - -error_cleanup_triggered_buffer: - iio_triggered_buffer_cleanup(indio_dev); - -error_disable_reg: - regulator_disable(st->reg); - return ret; } -static int adc108s102_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct adc108s102_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - - regulator_disable(st->reg); - - return 0; -} - static const struct of_device_id adc108s102_of_match[] = { { .compatible = "ti,adc108s102" }, { } @@ -327,7 +313,6 @@ static struct spi_driver adc108s102_driver = { .acpi_match_table = ACPI_PTR(adc108s102_acpi_ids), }, .probe = adc108s102_probe, - .remove = adc108s102_remove, .id_table = adc108s102_id, }; module_spi_driver(adc108s102_driver); diff --git a/drivers/iio/adc/ti-adc161s626.c b/drivers/iio/adc/ti-adc161s626.c index 607791ffe7f0..75ca7f1c8726 100644 --- a/drivers/iio/adc/ti-adc161s626.c +++ b/drivers/iio/adc/ti-adc161s626.c @@ -169,6 +169,11 @@ static const struct iio_info ti_adc_info = { .read_raw = ti_adc_read_raw, }; +static void ti_adc_reg_disable(void *reg) +{ + regulator_disable(reg); +} + static int ti_adc_probe(struct spi_device *spi) { struct iio_dev *indio_dev; @@ -182,7 +187,6 @@ static int ti_adc_probe(struct spi_device *spi) indio_dev->info = &ti_adc_info; indio_dev->name = TI_ADC_DRV_NAME; indio_dev->modes = INDIO_DIRECT_MODE; - spi_set_drvdata(spi, indio_dev); data = iio_priv(indio_dev); data->spi = spi; @@ -203,42 +207,24 @@ static int ti_adc_probe(struct spi_device *spi) } data->ref = devm_regulator_get(&spi->dev, "vdda"); - if (!IS_ERR(data->ref)) { - ret = regulator_enable(data->ref); - if (ret < 0) - return ret; - } + if (IS_ERR(data->ref)) + return PTR_ERR(data->ref); - ret = iio_triggered_buffer_setup(indio_dev, NULL, - ti_adc_trigger_handler, NULL); - if (ret) - goto error_regulator_disable; + ret = regulator_enable(data->ref); + if (ret < 0) + return ret; - ret = iio_device_register(indio_dev); + ret = devm_add_action_or_reset(&spi->dev, ti_adc_reg_disable, + data->ref); if (ret) - goto error_unreg_buffer; - - return 0; + return ret; -error_unreg_buffer: - iio_triggered_buffer_cleanup(indio_dev); - -error_regulator_disable: - regulator_disable(data->ref); - - return ret; -} - -static int ti_adc_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ti_adc_data *data = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - regulator_disable(data->ref); + ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL, + ti_adc_trigger_handler, NULL); + if (ret) + return ret; - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static const struct of_device_id ti_adc_dt_ids[] = { @@ -261,7 +247,6 @@ static struct spi_driver ti_adc_driver = { .of_match_table = ti_adc_dt_ids, }, .probe = ti_adc_probe, - .remove = ti_adc_remove, .id_table = ti_adc_id, }; module_spi_driver(ti_adc_driver); diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c index 9fef39bcf997..b0352e91ac16 100644 --- a/drivers/iio/adc/ti-ads1015.c +++ b/drivers/iio/adc/ti-ads1015.c @@ -323,9 +323,7 @@ static int ads1015_set_power_state(struct ads1015_data *data, bool on) struct device *dev = regmap_get_device(data->regmap); if (on) { - ret = pm_runtime_get_sync(dev); - if (ret < 0) - pm_runtime_put_noidle(dev); + ret = pm_runtime_resume_and_get(dev); } else { pm_runtime_mark_last_busy(dev); ret = pm_runtime_put_autosuspend(dev); @@ -395,10 +393,14 @@ static irqreturn_t ads1015_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct ads1015_data *data = iio_priv(indio_dev); - s16 buf[8]; /* 1x s16 ADC val + 3x s16 padding + 4x s16 timestamp */ + /* Ensure natural alignment of timestamp */ + struct { + s16 chan; + s64 timestamp __aligned(8); + } scan; int chan, ret, res; - memset(buf, 0, sizeof(buf)); + memset(&scan, 0, sizeof(scan)); mutex_lock(&data->lock); chan = find_first_bit(indio_dev->active_scan_mask, @@ -409,10 +411,10 @@ static irqreturn_t ads1015_trigger_handler(int irq, void *p) goto err; } - buf[0] = res; + scan.chan = res; mutex_unlock(&data->lock); - iio_push_to_buffers_with_timestamp(indio_dev, buf, + iio_push_to_buffers_with_timestamp(indio_dev, &scan, iio_get_time_ns(indio_dev)); err: @@ -1066,7 +1068,6 @@ static int ads1015_remove(struct i2c_client *client) pm_runtime_disable(&client->dev); pm_runtime_set_suspended(&client->dev); - pm_runtime_put_noidle(&client->dev); /* power down single shot mode */ return ads1015_set_conv_mode(data, ADS1015_SINGLESHOT); diff --git a/drivers/iio/adc/ti-ads124s08.c b/drivers/iio/adc/ti-ads124s08.c index b4a128b19188..17d0da5877a9 100644 --- a/drivers/iio/adc/ti-ads124s08.c +++ b/drivers/iio/adc/ti-ads124s08.c @@ -327,8 +327,6 @@ static int ads124s_probe(struct spi_device *spi) ads124s_priv->chip_info = &ads124s_chip_info_tbl[spi_id->driver_data]; - spi_set_drvdata(spi, indio_dev); - ads124s_priv->spi = spi; indio_dev->name = spi_id->name; diff --git a/drivers/iio/adc/ti-ads131e08.c b/drivers/iio/adc/ti-ads131e08.c index 764dab087b41..0c2025a22575 100644 --- a/drivers/iio/adc/ti-ads131e08.c +++ b/drivers/iio/adc/ti-ads131e08.c @@ -830,7 +830,6 @@ static int ads131e08_probe(struct spi_device *spi) return ret; indio_dev->name = st->info->name; - indio_dev->dev.parent = &spi->dev; indio_dev->info = &ads131e08_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; @@ -850,7 +849,7 @@ static int ads131e08_probe(struct spi_device *spi) } st->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d", - indio_dev->name, indio_dev->id); + indio_dev->name, iio_device_id(indio_dev)); if (!st->trig) { dev_err(&spi->dev, "failed to allocate IIO trigger\n"); return -ENOMEM; diff --git a/drivers/iio/adc/ti-ads8688.c b/drivers/iio/adc/ti-ads8688.c index 16bcb37eebb7..79c803537dc4 100644 --- a/drivers/iio/adc/ti-ads8688.c +++ b/drivers/iio/adc/ti-ads8688.c @@ -383,7 +383,8 @@ static irqreturn_t ads8688_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; - u16 buffer[ADS8688_MAX_CHANNELS + sizeof(s64)/sizeof(u16)]; + /* Ensure naturally aligned timestamp */ + u16 buffer[ADS8688_MAX_CHANNELS + sizeof(s64)/sizeof(u16)] __aligned(8); int i, j = 0; for (i = 0; i < indio_dev->masklength; i++) { diff --git a/drivers/iio/adc/ti-tsc2046.c b/drivers/iio/adc/ti-tsc2046.c new file mode 100644 index 000000000000..170950d5dd49 --- /dev/null +++ b/drivers/iio/adc/ti-tsc2046.c @@ -0,0 +1,712 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Texas Instruments TSC2046 SPI ADC driver + * + * Copyright (c) 2021 Oleksij Rempel <kernel@pengutronix.de>, Pengutronix + */ + +#include <linux/bitfield.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/spi/spi.h> + +#include <asm/unaligned.h> + +#include <linux/iio/buffer.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> +#include <linux/iio/trigger.h> + +/* + * The PENIRQ of TSC2046 controller is implemented as level shifter attached to + * the X+ line. If voltage of the X+ line reaches a specific level the IRQ will + * be activated or deactivated. + * To make this kind of IRQ reusable as trigger following additions were + * implemented: + * - rate limiting: + * For typical touchscreen use case, we need to trigger about each 10ms. + * - hrtimer: + * Continue triggering at least once after the IRQ was deactivated. Then + * deactivate this trigger to stop sampling in order to reduce power + * consumption. + */ + +#define TI_TSC2046_NAME "tsc2046" + +/* This driver doesn't aim at the peak continuous sample rate */ +#define TI_TSC2046_MAX_SAMPLE_RATE 125000 +#define TI_TSC2046_SAMPLE_BITS \ + BITS_PER_TYPE(struct tsc2046_adc_atom) +#define TI_TSC2046_MAX_CLK_FREQ \ + (TI_TSC2046_MAX_SAMPLE_RATE * TI_TSC2046_SAMPLE_BITS) + +#define TI_TSC2046_SAMPLE_INTERVAL_US 10000 + +#define TI_TSC2046_START BIT(7) +#define TI_TSC2046_ADDR GENMASK(6, 4) +#define TI_TSC2046_ADDR_TEMP1 7 +#define TI_TSC2046_ADDR_AUX 6 +#define TI_TSC2046_ADDR_X 5 +#define TI_TSC2046_ADDR_Z2 4 +#define TI_TSC2046_ADDR_Z1 3 +#define TI_TSC2046_ADDR_VBAT 2 +#define TI_TSC2046_ADDR_Y 1 +#define TI_TSC2046_ADDR_TEMP0 0 + +/* + * The mode bit sets the resolution of the ADC. With this bit low, the next + * conversion has 12-bit resolution, whereas with this bit high, the next + * conversion has 8-bit resolution. This driver is optimized for 12-bit mode. + * So, for this driver, this bit should stay zero. + */ +#define TI_TSC2046_8BIT_MODE BIT(3) + +/* + * SER/DFR - The SER/DFR bit controls the reference mode, either single-ended + * (high) or differential (low). + */ +#define TI_TSC2046_SER BIT(2) + +/* + * If VREF_ON and ADC_ON are both zero, then the chip operates in + * auto-wake/suspend mode. In most case this bits should stay zero. + */ +#define TI_TSC2046_PD1_VREF_ON BIT(1) +#define TI_TSC2046_PD0_ADC_ON BIT(0) + +/* + * All supported devices can do 8 or 12bit resolution. This driver + * supports only 12bit mode, here we have a 16bit data transfer, where + * the MSB and the 3 LSB are 0. + */ +#define TI_TSC2046_DATA_12BIT GENMASK(14, 3) + +#define TI_TSC2046_MAX_CHAN 8 + +/* Represents a HW sample */ +struct tsc2046_adc_atom { + /* + * Command transmitted to the controller. This field is empty on the RX + * buffer. + */ + u8 cmd; + /* + * Data received from the controller. This field is empty for the TX + * buffer + */ + __be16 data; +} __packed; + +/* Layout of atomic buffers within big buffer */ +struct tsc2046_adc_group_layout { + /* Group offset within the SPI RX buffer */ + unsigned int offset; + /* + * Amount of tsc2046_adc_atom structs within the same command gathered + * within same group. + */ + unsigned int count; + /* + * Settling samples (tsc2046_adc_atom structs) which should be skipped + * before good samples will start. + */ + unsigned int skip; +}; + +struct tsc2046_adc_dcfg { + const struct iio_chan_spec *channels; + unsigned int num_channels; +}; + +struct tsc2046_adc_ch_cfg { + unsigned int settling_time_us; + unsigned int oversampling_ratio; +}; + +struct tsc2046_adc_priv { + struct spi_device *spi; + const struct tsc2046_adc_dcfg *dcfg; + + struct iio_trigger *trig; + struct hrtimer trig_timer; + spinlock_t trig_lock; + unsigned int trig_more_count; + + struct spi_transfer xfer; + struct spi_message msg; + + struct { + /* Scan data for each channel */ + u16 data[TI_TSC2046_MAX_CHAN]; + /* Timestamp */ + s64 ts __aligned(8); + } scan_buf; + + /* + * Lock to protect the layout and the SPI transfer buffer. + * tsc2046_adc_group_layout can be changed within update_scan_mode(), + * in this case the l[] and tx/rx buffer will be out of sync to each + * other. + */ + struct mutex slock; + struct tsc2046_adc_group_layout l[TI_TSC2046_MAX_CHAN]; + struct tsc2046_adc_atom *rx; + struct tsc2046_adc_atom *tx; + + struct tsc2046_adc_atom *rx_one; + struct tsc2046_adc_atom *tx_one; + + unsigned int count; + unsigned int groups; + u32 effective_speed_hz; + u32 scan_interval_us; + u32 time_per_scan_us; + u32 time_per_bit_ns; + + struct tsc2046_adc_ch_cfg ch_cfg[TI_TSC2046_MAX_CHAN]; +}; + +#define TI_TSC2046_V_CHAN(index, bits, name) \ +{ \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = index, \ + .datasheet_name = "#name", \ + .scan_index = index, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = bits, \ + .storagebits = 16, \ + .endianness = IIO_CPU, \ + }, \ +} + +#define DECLARE_TI_TSC2046_8_CHANNELS(name, bits) \ +const struct iio_chan_spec name ## _channels[] = { \ + TI_TSC2046_V_CHAN(0, bits, TEMP0), \ + TI_TSC2046_V_CHAN(1, bits, Y), \ + TI_TSC2046_V_CHAN(2, bits, VBAT), \ + TI_TSC2046_V_CHAN(3, bits, Z1), \ + TI_TSC2046_V_CHAN(4, bits, Z2), \ + TI_TSC2046_V_CHAN(5, bits, X), \ + TI_TSC2046_V_CHAN(6, bits, AUX), \ + TI_TSC2046_V_CHAN(7, bits, TEMP1), \ + IIO_CHAN_SOFT_TIMESTAMP(8), \ +} + +static DECLARE_TI_TSC2046_8_CHANNELS(tsc2046_adc, 12); + +static const struct tsc2046_adc_dcfg tsc2046_adc_dcfg_tsc2046e = { + .channels = tsc2046_adc_channels, + .num_channels = ARRAY_SIZE(tsc2046_adc_channels), +}; + +/* + * Convert time to a number of samples which can be transferred within this + * time. + */ +static unsigned int tsc2046_adc_time_to_count(struct tsc2046_adc_priv *priv, + unsigned long time) +{ + unsigned int bit_count, sample_count; + + bit_count = DIV_ROUND_UP(time * NSEC_PER_USEC, priv->time_per_bit_ns); + sample_count = DIV_ROUND_UP(bit_count, TI_TSC2046_SAMPLE_BITS); + + dev_dbg(&priv->spi->dev, "Effective speed %u, time per bit: %u, count bits: %u, count samples: %u\n", + priv->effective_speed_hz, priv->time_per_bit_ns, + bit_count, sample_count); + + return sample_count; +} + +static u8 tsc2046_adc_get_cmd(struct tsc2046_adc_priv *priv, int ch_idx, + bool keep_power) +{ + u32 pd; + + /* + * if PD bits are 0, controller will automatically disable ADC, VREF and + * enable IRQ. + */ + if (keep_power) + pd = TI_TSC2046_PD0_ADC_ON; + else + pd = 0; + + return TI_TSC2046_START | FIELD_PREP(TI_TSC2046_ADDR, ch_idx) | pd; +} + +static u16 tsc2046_adc_get_value(struct tsc2046_adc_atom *buf) +{ + return FIELD_GET(TI_TSC2046_DATA_12BIT, get_unaligned_be16(&buf->data)); +} + +static int tsc2046_adc_read_one(struct tsc2046_adc_priv *priv, int ch_idx, + u32 *effective_speed_hz) +{ + struct spi_transfer xfer; + struct spi_message msg; + int ret; + + memset(&xfer, 0, sizeof(xfer)); + priv->tx_one->cmd = tsc2046_adc_get_cmd(priv, ch_idx, false); + priv->tx_one->data = 0; + xfer.tx_buf = priv->tx_one; + xfer.rx_buf = priv->rx_one; + xfer.len = sizeof(*priv->tx_one); + spi_message_init_with_transfers(&msg, &xfer, 1); + + /* + * We aren't using spi_write_then_read() because we need to be able + * to get hold of the effective_speed_hz from the xfer + */ + ret = spi_sync(priv->spi, &msg); + if (ret) { + dev_err_ratelimited(&priv->spi->dev, "SPI transfer failed %pe\n", + ERR_PTR(ret)); + return ret; + } + + if (effective_speed_hz) + *effective_speed_hz = xfer.effective_speed_hz; + + return tsc2046_adc_get_value(priv->rx_one); +} + +static size_t tsc2046_adc_group_set_layout(struct tsc2046_adc_priv *priv, + unsigned int group, + unsigned int ch_idx) +{ + struct tsc2046_adc_ch_cfg *ch = &priv->ch_cfg[ch_idx]; + struct tsc2046_adc_group_layout *cur; + unsigned int max_count, count_skip; + unsigned int offset = 0; + + if (group) + offset = priv->l[group - 1].offset + priv->l[group - 1].count; + + count_skip = tsc2046_adc_time_to_count(priv, ch->settling_time_us); + max_count = count_skip + ch->oversampling_ratio; + + cur = &priv->l[group]; + cur->offset = offset; + cur->count = max_count; + cur->skip = count_skip; + + return sizeof(*priv->tx) * max_count; +} + +static void tsc2046_adc_group_set_cmd(struct tsc2046_adc_priv *priv, + unsigned int group, int ch_idx) +{ + struct tsc2046_adc_group_layout *l = &priv->l[group]; + unsigned int i; + u8 cmd; + + /* + * Do not enable automatic power down on working samples. Otherwise the + * plates will never be completely charged. + */ + cmd = tsc2046_adc_get_cmd(priv, ch_idx, true); + + for (i = 0; i < l->count - 1; i++) + priv->tx[l->offset + i].cmd = cmd; + + /* automatically power down on last sample */ + priv->tx[l->offset + i].cmd = tsc2046_adc_get_cmd(priv, ch_idx, false); +} + +static u16 tsc2046_adc_get_val(struct tsc2046_adc_priv *priv, int group) +{ + struct tsc2046_adc_group_layout *l; + unsigned int val, val_normalized = 0; + int valid_count, i; + + l = &priv->l[group]; + valid_count = l->count - l->skip; + + for (i = 0; i < valid_count; i++) { + val = tsc2046_adc_get_value(&priv->rx[l->offset + l->skip + i]); + val_normalized += val; + } + + return DIV_ROUND_UP(val_normalized, valid_count); +} + +static int tsc2046_adc_scan(struct iio_dev *indio_dev) +{ + struct tsc2046_adc_priv *priv = iio_priv(indio_dev); + struct device *dev = &priv->spi->dev; + int group; + int ret; + + ret = spi_sync(priv->spi, &priv->msg); + if (ret < 0) { + dev_err_ratelimited(dev, "SPI transfer failed: %pe\n", ERR_PTR(ret)); + return ret; + } + + for (group = 0; group < priv->groups; group++) + priv->scan_buf.data[group] = tsc2046_adc_get_val(priv, group); + + ret = iio_push_to_buffers_with_timestamp(indio_dev, &priv->scan_buf, + iio_get_time_ns(indio_dev)); + /* If the consumer is kfifo, we may get a EBUSY here - ignore it. */ + if (ret < 0 && ret != -EBUSY) { + dev_err_ratelimited(dev, "Failed to push scan buffer %pe\n", + ERR_PTR(ret)); + + return ret; + } + + return 0; +} + +static irqreturn_t tsc2046_adc_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct tsc2046_adc_priv *priv = iio_priv(indio_dev); + + mutex_lock(&priv->slock); + tsc2046_adc_scan(indio_dev); + mutex_unlock(&priv->slock); + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int tsc2046_adc_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *active_scan_mask) +{ + struct tsc2046_adc_priv *priv = iio_priv(indio_dev); + unsigned int ch_idx, group = 0; + size_t size; + + mutex_lock(&priv->slock); + + size = 0; + for_each_set_bit(ch_idx, active_scan_mask, indio_dev->num_channels) { + size += tsc2046_adc_group_set_layout(priv, group, ch_idx); + tsc2046_adc_group_set_cmd(priv, group, ch_idx); + group++; + } + + priv->groups = group; + priv->xfer.len = size; + priv->time_per_scan_us = size * 8 * priv->time_per_bit_ns / NSEC_PER_USEC; + + if (priv->scan_interval_us > priv->time_per_scan_us) + dev_warn(&priv->spi->dev, "The scan interval (%d) is less then calculated scan time (%d)\n", + priv->scan_interval_us, priv->time_per_scan_us); + + mutex_unlock(&priv->slock); + + return 0; +} + +static const struct iio_info tsc2046_adc_info = { + .update_scan_mode = tsc2046_adc_update_scan_mode, +}; + +static enum hrtimer_restart tsc2046_adc_trig_more(struct hrtimer *hrtimer) +{ + struct tsc2046_adc_priv *priv = container_of(hrtimer, + struct tsc2046_adc_priv, + trig_timer); + unsigned long flags; + + spin_lock_irqsave(&priv->trig_lock, flags); + + disable_irq_nosync(priv->spi->irq); + + priv->trig_more_count++; + iio_trigger_poll(priv->trig); + + spin_unlock_irqrestore(&priv->trig_lock, flags); + + return HRTIMER_NORESTART; +} + +static irqreturn_t tsc2046_adc_irq(int irq, void *dev_id) +{ + struct iio_dev *indio_dev = dev_id; + struct tsc2046_adc_priv *priv = iio_priv(indio_dev); + + spin_lock(&priv->trig_lock); + + hrtimer_try_to_cancel(&priv->trig_timer); + + priv->trig_more_count = 0; + disable_irq_nosync(priv->spi->irq); + iio_trigger_poll(priv->trig); + + spin_unlock(&priv->trig_lock); + + return IRQ_HANDLED; +} + +static void tsc2046_adc_reenable_trigger(struct iio_trigger *trig) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct tsc2046_adc_priv *priv = iio_priv(indio_dev); + unsigned long flags; + int delta; + + /* + * We can sample it as fast as we can, but usually we do not need so + * many samples. Reduce the sample rate for default (touchscreen) use + * case. + * Currently we do not need a highly precise sample rate. It is enough + * to have calculated numbers. + */ + delta = priv->scan_interval_us - priv->time_per_scan_us; + if (delta > 0) + fsleep(delta); + + spin_lock_irqsave(&priv->trig_lock, flags); + + /* + * We need to trigger at least one extra sample to detect state + * difference on ADC side. + */ + if (!priv->trig_more_count) { + int timeout_ms = DIV_ROUND_UP(priv->scan_interval_us, + USEC_PER_MSEC); + + hrtimer_start(&priv->trig_timer, ms_to_ktime(timeout_ms), + HRTIMER_MODE_REL_SOFT); + } + + enable_irq(priv->spi->irq); + + spin_unlock_irqrestore(&priv->trig_lock, flags); +} + +static int tsc2046_adc_set_trigger_state(struct iio_trigger *trig, bool enable) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct tsc2046_adc_priv *priv = iio_priv(indio_dev); + + if (enable) { + enable_irq(priv->spi->irq); + } else { + disable_irq(priv->spi->irq); + hrtimer_try_to_cancel(&priv->trig_timer); + } + + return 0; +} + +static const struct iio_trigger_ops tsc2046_adc_trigger_ops = { + .set_trigger_state = tsc2046_adc_set_trigger_state, + .reenable = tsc2046_adc_reenable_trigger, +}; + +static int tsc2046_adc_setup_spi_msg(struct tsc2046_adc_priv *priv) +{ + unsigned int ch_idx; + size_t size; + int ret; + + priv->tx_one = devm_kzalloc(&priv->spi->dev, sizeof(*priv->tx_one), + GFP_KERNEL); + if (!priv->tx_one) + return -ENOMEM; + + priv->rx_one = devm_kzalloc(&priv->spi->dev, sizeof(*priv->rx_one), + GFP_KERNEL); + if (!priv->rx_one) + return -ENOMEM; + + /* + * Make dummy read to set initial power state and get real SPI clock + * freq. It seems to be not important which channel is used for this + * case. + */ + ret = tsc2046_adc_read_one(priv, TI_TSC2046_ADDR_TEMP0, + &priv->effective_speed_hz); + if (ret < 0) + return ret; + + /* + * In case SPI controller do not report effective_speed_hz, use + * configure value and hope it will match. + */ + if (!priv->effective_speed_hz) + priv->effective_speed_hz = priv->spi->max_speed_hz; + + + priv->scan_interval_us = TI_TSC2046_SAMPLE_INTERVAL_US; + priv->time_per_bit_ns = DIV_ROUND_UP(NSEC_PER_SEC, + priv->effective_speed_hz); + + /* + * Calculate and allocate maximal size buffer if all channels are + * enabled. + */ + size = 0; + for (ch_idx = 0; ch_idx < priv->dcfg->num_channels; ch_idx++) + size += tsc2046_adc_group_set_layout(priv, ch_idx, ch_idx); + + priv->tx = devm_kzalloc(&priv->spi->dev, size, GFP_KERNEL); + if (!priv->tx) + return -ENOMEM; + + priv->rx = devm_kzalloc(&priv->spi->dev, size, GFP_KERNEL); + if (!priv->rx) + return -ENOMEM; + + priv->xfer.tx_buf = priv->tx; + priv->xfer.rx_buf = priv->rx; + priv->xfer.len = size; + spi_message_init_with_transfers(&priv->msg, &priv->xfer, 1); + + return 0; +} + +static void tsc2046_adc_parse_fwnode(struct tsc2046_adc_priv *priv) +{ + struct fwnode_handle *child; + struct device *dev = &priv->spi->dev; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(priv->ch_cfg); i++) { + priv->ch_cfg[i].settling_time_us = 1; + priv->ch_cfg[i].oversampling_ratio = 1; + } + + device_for_each_child_node(dev, child) { + u32 stl, overs, reg; + int ret; + + ret = fwnode_property_read_u32(child, "reg", ®); + if (ret) { + dev_err(dev, "invalid reg on %pfw, err: %pe\n", child, + ERR_PTR(ret)); + continue; + } + + if (reg >= ARRAY_SIZE(priv->ch_cfg)) { + dev_err(dev, "%pfw: Unsupported reg value: %i, max supported is: %zu.\n", + child, reg, ARRAY_SIZE(priv->ch_cfg)); + continue; + } + + ret = fwnode_property_read_u32(child, "settling-time-us", &stl); + if (!ret) + priv->ch_cfg[reg].settling_time_us = stl; + + ret = fwnode_property_read_u32(child, "oversampling-ratio", + &overs); + if (!ret) + priv->ch_cfg[reg].oversampling_ratio = overs; + } +} + +static int tsc2046_adc_probe(struct spi_device *spi) +{ + const struct tsc2046_adc_dcfg *dcfg; + struct device *dev = &spi->dev; + struct tsc2046_adc_priv *priv; + struct iio_dev *indio_dev; + struct iio_trigger *trig; + int ret; + + if (spi->max_speed_hz > TI_TSC2046_MAX_CLK_FREQ) { + dev_err(dev, "SPI max_speed_hz is too high: %d Hz. Max supported freq is %zu Hz\n", + spi->max_speed_hz, TI_TSC2046_MAX_CLK_FREQ); + return -EINVAL; + } + + dcfg = device_get_match_data(dev); + if (!dcfg) + return -EINVAL; + + spi->bits_per_word = 8; + spi->mode &= ~SPI_MODE_X_MASK; + spi->mode |= SPI_MODE_0; + ret = spi_setup(spi); + if (ret < 0) + return dev_err_probe(dev, ret, "Error in SPI setup\n"); + + indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); + if (!indio_dev) + return -ENOMEM; + + priv = iio_priv(indio_dev); + priv->dcfg = dcfg; + + priv->spi = spi; + + indio_dev->name = TI_TSC2046_NAME; + indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_TRIGGERED; + indio_dev->channels = dcfg->channels; + indio_dev->num_channels = dcfg->num_channels; + indio_dev->info = &tsc2046_adc_info; + + tsc2046_adc_parse_fwnode(priv); + + ret = tsc2046_adc_setup_spi_msg(priv); + if (ret) + return ret; + + mutex_init(&priv->slock); + + ret = devm_request_irq(dev, spi->irq, &tsc2046_adc_irq, + IRQF_NO_AUTOEN, indio_dev->name, indio_dev); + if (ret) + return ret; + + trig = devm_iio_trigger_alloc(dev, "touchscreen-%s", indio_dev->name); + if (!trig) + return -ENOMEM; + + priv->trig = trig; + iio_trigger_set_drvdata(trig, indio_dev); + trig->ops = &tsc2046_adc_trigger_ops; + + spin_lock_init(&priv->trig_lock); + hrtimer_init(&priv->trig_timer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL_SOFT); + priv->trig_timer.function = tsc2046_adc_trig_more; + + ret = devm_iio_trigger_register(dev, trig); + if (ret) { + dev_err(dev, "failed to register trigger\n"); + return ret; + } + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, + &tsc2046_adc_trigger_handler, NULL); + if (ret) { + dev_err(dev, "Failed to setup triggered buffer\n"); + return ret; + } + + /* set default trigger */ + indio_dev->trig = iio_trigger_get(priv->trig); + + return devm_iio_device_register(dev, indio_dev); +} + +static const struct of_device_id ads7950_of_table[] = { + { .compatible = "ti,tsc2046e-adc", .data = &tsc2046_adc_dcfg_tsc2046e }, + { } +}; +MODULE_DEVICE_TABLE(of, ads7950_of_table); + +static struct spi_driver tsc2046_adc_driver = { + .driver = { + .name = "tsc2046", + .of_match_table = ads7950_of_table, + }, + .probe = tsc2046_adc_probe, +}; +module_spi_driver(tsc2046_adc_driver); + +MODULE_AUTHOR("Oleksij Rempel <kernel@pengutronix.de>"); +MODULE_DESCRIPTION("TI TSC2046 ADC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c index 1d794cf3e3f1..fd57fc43e8e5 100644 --- a/drivers/iio/adc/vf610_adc.c +++ b/drivers/iio/adc/vf610_adc.c @@ -167,7 +167,11 @@ struct vf610_adc { u32 sample_freq_avail[5]; struct completion completion; - u16 buffer[8]; + /* Ensure the timestamp is naturally aligned */ + struct { + u16 chan; + s64 timestamp __aligned(8); + } scan; }; static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 }; @@ -579,9 +583,9 @@ static irqreturn_t vf610_adc_isr(int irq, void *dev_id) if (coco & VF610_ADC_HS_COCO0) { info->value = vf610_adc_read_data(info); if (iio_buffer_enabled(indio_dev)) { - info->buffer[0] = info->value; + info->scan.chan = info->value; iio_push_to_buffers_with_timestamp(indio_dev, - info->buffer, + &info->scan, iio_get_time_ns(indio_dev)); iio_trigger_notify_done(indio_dev->trig); } else diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c index 6914c1900ed0..198d2916266d 100644 --- a/drivers/iio/adc/xilinx-xadc-core.c +++ b/drivers/iio/adc/xilinx-xadc-core.c @@ -743,7 +743,7 @@ static struct iio_trigger *xadc_alloc_trigger(struct iio_dev *indio_dev, int ret; trig = devm_iio_trigger_alloc(dev, "%s%d-%s", indio_dev->name, - indio_dev->id, name); + iio_device_id(indio_dev), name); if (trig == NULL) return ERR_PTR(-ENOMEM); diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c index e42ea2b1707d..774eb3044edd 100644 --- a/drivers/iio/afe/iio-rescale.c +++ b/drivers/iio/afe/iio-rescale.c @@ -29,6 +29,7 @@ struct rescale { struct iio_channel *source; struct iio_chan_spec chan; struct iio_chan_spec_ext_info *ext_info; + bool chan_processed; s32 numerator; s32 denominator; }; @@ -43,10 +44,27 @@ static int rescale_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - return iio_read_channel_raw(rescale->source, val); + if (rescale->chan_processed) + /* + * When only processed channels are supported, we + * read the processed data and scale it by 1/1 + * augmented with whatever the rescaler has calculated. + */ + return iio_read_channel_processed(rescale->source, val); + else + return iio_read_channel_raw(rescale->source, val); case IIO_CHAN_INFO_SCALE: - ret = iio_read_channel_scale(rescale->source, val, val2); + if (rescale->chan_processed) { + /* + * Processed channels are scaled 1-to-1 + */ + *val = 1; + *val2 = 1; + ret = IIO_VAL_FRACTIONAL; + } else { + ret = iio_read_channel_scale(rescale->source, val, val2); + } switch (ret) { case IIO_VAL_FRACTIONAL: *val *= rescale->numerator; @@ -130,16 +148,27 @@ static int rescale_configure_channel(struct device *dev, chan->ext_info = rescale->ext_info; chan->type = rescale->cfg->type; - if (!iio_channel_has_info(schan, IIO_CHAN_INFO_RAW) || - !iio_channel_has_info(schan, IIO_CHAN_INFO_SCALE)) { - dev_err(dev, "source channel does not support raw/scale\n"); + if (iio_channel_has_info(schan, IIO_CHAN_INFO_RAW) || + iio_channel_has_info(schan, IIO_CHAN_INFO_SCALE)) { + dev_info(dev, "using raw+scale source channel\n"); + } else if (iio_channel_has_info(schan, IIO_CHAN_INFO_PROCESSED)) { + dev_info(dev, "using processed channel\n"); + rescale->chan_processed = true; + } else { + dev_err(dev, "source channel is not supported\n"); return -EINVAL; } chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE); - if (iio_channel_has_available(schan, IIO_CHAN_INFO_RAW)) + /* + * Using .read_avail() is fringe to begin with and makes no sense + * whatsoever for processed channels, so we make sure that this cannot + * be called on a processed channel. + */ + if (iio_channel_has_available(schan, IIO_CHAN_INFO_RAW) && + !rescale->chan_processed) chan->info_mask_separate_available |= BIT(IIO_CHAN_INFO_RAW); return 0; diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c index d76179878ff9..1ac94c4e9792 100644 --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c @@ -228,9 +228,9 @@ static void iio_dmaengine_buffer_free(struct iio_buffer *buffer) iio_buffer_put(buffer); } -static void __devm_iio_dmaengine_buffer_free(struct device *dev, void *res) +static void __devm_iio_dmaengine_buffer_free(void *buffer) { - iio_dmaengine_buffer_free(*(struct iio_buffer **)res); + iio_dmaengine_buffer_free(buffer); } /** @@ -247,21 +247,17 @@ static void __devm_iio_dmaengine_buffer_free(struct device *dev, void *res) static struct iio_buffer *devm_iio_dmaengine_buffer_alloc(struct device *dev, const char *channel) { - struct iio_buffer **bufferp, *buffer; - - bufferp = devres_alloc(__devm_iio_dmaengine_buffer_free, - sizeof(*bufferp), GFP_KERNEL); - if (!bufferp) - return ERR_PTR(-ENOMEM); + struct iio_buffer *buffer; + int ret; buffer = iio_dmaengine_buffer_alloc(dev, channel); - if (IS_ERR(buffer)) { - devres_free(bufferp); + if (IS_ERR(buffer)) return buffer; - } - *bufferp = buffer; - devres_add(dev, bufferp); + ret = devm_add_action_or_reset(dev, __devm_iio_dmaengine_buffer_free, + buffer); + if (ret) + return ERR_PTR(ret); return buffer; } diff --git a/drivers/iio/buffer/industrialio-hw-consumer.c b/drivers/iio/buffer/industrialio-hw-consumer.c index f2d27788f666..87d9aabd20c7 100644 --- a/drivers/iio/buffer/industrialio-hw-consumer.c +++ b/drivers/iio/buffer/industrialio-hw-consumer.c @@ -137,9 +137,9 @@ void iio_hw_consumer_free(struct iio_hw_consumer *hwc) } EXPORT_SYMBOL_GPL(iio_hw_consumer_free); -static void devm_iio_hw_consumer_release(struct device *dev, void *res) +static void devm_iio_hw_consumer_release(void *iio_hwc) { - iio_hw_consumer_free(*(struct iio_hw_consumer **)res); + iio_hw_consumer_free(iio_hwc); } /** @@ -153,20 +153,17 @@ static void devm_iio_hw_consumer_release(struct device *dev, void *res) */ struct iio_hw_consumer *devm_iio_hw_consumer_alloc(struct device *dev) { - struct iio_hw_consumer **ptr, *iio_hwc; - - ptr = devres_alloc(devm_iio_hw_consumer_release, sizeof(*ptr), - GFP_KERNEL); - if (!ptr) - return NULL; + struct iio_hw_consumer *iio_hwc; + int ret; iio_hwc = iio_hw_consumer_alloc(dev); - if (IS_ERR(iio_hwc)) { - devres_free(ptr); - } else { - *ptr = iio_hwc; - devres_add(dev, ptr); - } + if (IS_ERR(iio_hwc)) + return iio_hwc; + + ret = devm_add_action_or_reset(dev, devm_iio_hw_consumer_release, + iio_hwc); + if (ret) + return ERR_PTR(ret); return iio_hwc; } diff --git a/drivers/iio/buffer/industrialio-triggered-buffer.c b/drivers/iio/buffer/industrialio-triggered-buffer.c index b2b1b7d27af4..f77c4538141e 100644 --- a/drivers/iio/buffer/industrialio-triggered-buffer.c +++ b/drivers/iio/buffer/industrialio-triggered-buffer.c @@ -56,7 +56,7 @@ int iio_triggered_buffer_setup_ext(struct iio_dev *indio_dev, indio_dev, "%s_consumer%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (indio_dev->pollfunc == NULL) { ret = -ENOMEM; goto error_kfifo_free; @@ -96,9 +96,9 @@ void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev) } EXPORT_SYMBOL(iio_triggered_buffer_cleanup); -static void devm_iio_triggered_buffer_clean(struct device *dev, void *res) +static void devm_iio_triggered_buffer_clean(void *indio_dev) { - iio_triggered_buffer_cleanup(*(struct iio_dev **)res); + iio_triggered_buffer_cleanup(indio_dev); } int devm_iio_triggered_buffer_setup_ext(struct device *dev, @@ -108,24 +108,15 @@ int devm_iio_triggered_buffer_setup_ext(struct device *dev, const struct iio_buffer_setup_ops *ops, const struct attribute **buffer_attrs) { - struct iio_dev **ptr; int ret; - ptr = devres_alloc(devm_iio_triggered_buffer_clean, sizeof(*ptr), - GFP_KERNEL); - if (!ptr) - return -ENOMEM; - - *ptr = indio_dev; - ret = iio_triggered_buffer_setup_ext(indio_dev, h, thread, ops, buffer_attrs); - if (!ret) - devres_add(dev, ptr); - else - devres_free(ptr); + if (ret) + return ret; - return ret; + return devm_add_action_or_reset(dev, devm_iio_triggered_buffer_clean, + indio_dev); } EXPORT_SYMBOL_GPL(devm_iio_triggered_buffer_setup_ext); diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig index 10bb431bc3ce..a4920646e9be 100644 --- a/drivers/iio/chemical/Kconfig +++ b/drivers/iio/chemical/Kconfig @@ -132,17 +132,32 @@ config SENSIRION_SGP30 module will be called sgp30. config SPS30 - tristate "SPS30 particulate matter sensor" - depends on I2C - select CRC8 + tristate select IIO_BUFFER select IIO_TRIGGERED_BUFFER + +config SPS30_I2C + tristate "SPS30 particulate matter sensor I2C driver" + depends on I2C + select SPS30 + select CRC8 help - Say Y here to build support for the Sensirion SPS30 particulate - matter sensor. + Say Y here to build support for the Sensirion SPS30 I2C interface + driver. + + To compile this driver as a module, choose M here: the module will + be called sps30_i2c. + +config SPS30_SERIAL + tristate "SPS30 particulate matter sensor serial driver" + depends on SERIAL_DEV_BUS + select SPS30 + help + Say Y here to build support for the Sensirion SPS30 serial interface + driver. To compile this driver as a module, choose M here: the module will - be called sps30. + be called sps30_serial. config VZ89X tristate "SGX Sensortech MiCS VZ89X VOC sensor" diff --git a/drivers/iio/chemical/Makefile b/drivers/iio/chemical/Makefile index fef63dd5bf92..4898690cc155 100644 --- a/drivers/iio/chemical/Makefile +++ b/drivers/iio/chemical/Makefile @@ -17,4 +17,6 @@ obj-$(CONFIG_SCD30_I2C) += scd30_i2c.o obj-$(CONFIG_SCD30_SERIAL) += scd30_serial.o obj-$(CONFIG_SENSIRION_SGP30) += sgp30.o obj-$(CONFIG_SPS30) += sps30.o +obj-$(CONFIG_SPS30_I2C) += sps30_i2c.o +obj-$(CONFIG_SPS30_SERIAL) += sps30_serial.o obj-$(CONFIG_VZ89X) += vz89x.o diff --git a/drivers/iio/chemical/atlas-sensor.c b/drivers/iio/chemical/atlas-sensor.c index 56ba6c82b501..9cb99585b6ff 100644 --- a/drivers/iio/chemical/atlas-sensor.c +++ b/drivers/iio/chemical/atlas-sensor.c @@ -91,8 +91,8 @@ struct atlas_data { struct regmap *regmap; struct irq_work work; unsigned int interrupt_enabled; - - __be32 buffer[6]; /* 96-bit data + 32-bit pad + 64-bit timestamp */ + /* 96-bit data + 32-bit pad + 64-bit timestamp */ + __be32 buffer[6] __aligned(8); }; static const struct regmap_config atlas_regmap_config = { @@ -410,11 +410,9 @@ static int atlas_buffer_postenable(struct iio_dev *indio_dev) struct atlas_data *data = iio_priv(indio_dev); int ret; - ret = pm_runtime_get_sync(&data->client->dev); - if (ret < 0) { - pm_runtime_put_noidle(&data->client->dev); + ret = pm_runtime_resume_and_get(&data->client->dev); + if (ret) return ret; - } return atlas_set_interrupt(data, true); } @@ -487,11 +485,9 @@ static int atlas_read_measurement(struct atlas_data *data, int reg, __be32 *val) int suspended = pm_runtime_suspended(dev); int ret; - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - pm_runtime_put_noidle(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret) return ret; - } if (suspended) msleep(data->chip->delay); @@ -640,7 +636,7 @@ static int atlas_probe(struct i2c_client *client, indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE; trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", - indio_dev->name, indio_dev->id); + indio_dev->name, iio_device_id(indio_dev)); if (!trig) return -ENOMEM; @@ -741,7 +737,6 @@ static int atlas_remove(struct i2c_client *client) pm_runtime_disable(&client->dev); pm_runtime_set_suspended(&client->dev); - pm_runtime_put_noidle(&client->dev); return atlas_set_powermode(data, 0); } diff --git a/drivers/iio/chemical/bme680_i2c.c b/drivers/iio/chemical/bme680_i2c.c index 29c0dfa4702b..74cf89c82c0a 100644 --- a/drivers/iio/chemical/bme680_i2c.c +++ b/drivers/iio/chemical/bme680_i2c.c @@ -11,7 +11,6 @@ * Note: SDO pin cannot be left floating otherwise I2C address * will be undefined. */ -#include <linux/acpi.h> #include <linux/i2c.h> #include <linux/module.h> #include <linux/regmap.h> @@ -42,12 +41,6 @@ static const struct i2c_device_id bme680_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, bme680_i2c_id); -static const struct acpi_device_id bme680_acpi_match[] = { - {"BME0680", 0}, - {}, -}; -MODULE_DEVICE_TABLE(acpi, bme680_acpi_match); - static const struct of_device_id bme680_of_i2c_match[] = { { .compatible = "bosch,bme680", }, {}, @@ -57,7 +50,6 @@ MODULE_DEVICE_TABLE(of, bme680_of_i2c_match); static struct i2c_driver bme680_i2c_driver = { .driver = { .name = "bme680_i2c", - .acpi_match_table = ACPI_PTR(bme680_acpi_match), .of_match_table = bme680_of_i2c_match, }, .probe = bme680_i2c_probe, diff --git a/drivers/iio/chemical/bme680_spi.c b/drivers/iio/chemical/bme680_spi.c index 6f56ad48cc40..cc579a7ac5ce 100644 --- a/drivers/iio/chemical/bme680_spi.c +++ b/drivers/iio/chemical/bme680_spi.c @@ -4,7 +4,6 @@ * * Copyright (C) 2018 Himanshu Jha <himanshujha199640@gmail.com> */ -#include <linux/acpi.h> #include <linux/module.h> #include <linux/of.h> #include <linux/regmap.h> @@ -145,12 +144,6 @@ static const struct spi_device_id bme680_spi_id[] = { }; MODULE_DEVICE_TABLE(spi, bme680_spi_id); -static const struct acpi_device_id bme680_acpi_match[] = { - {"BME0680", 0}, - {}, -}; -MODULE_DEVICE_TABLE(acpi, bme680_acpi_match); - static const struct of_device_id bme680_of_spi_match[] = { { .compatible = "bosch,bme680", }, {}, @@ -160,7 +153,6 @@ MODULE_DEVICE_TABLE(of, bme680_of_spi_match); static struct spi_driver bme680_spi_driver = { .driver = { .name = "bme680_spi", - .acpi_match_table = ACPI_PTR(bme680_acpi_match), .of_match_table = bme680_of_spi_match, }, .probe = bme680_spi_probe, diff --git a/drivers/iio/chemical/ccs811.c b/drivers/iio/chemical/ccs811.c index 886e96496dbf..847194fa1e46 100644 --- a/drivers/iio/chemical/ccs811.c +++ b/drivers/iio/chemical/ccs811.c @@ -491,7 +491,7 @@ static int ccs811_probe(struct i2c_client *client, data->drdy_trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!data->drdy_trig) { ret = -ENOMEM; goto err_poweroff; diff --git a/drivers/iio/chemical/scd30_core.c b/drivers/iio/chemical/scd30_core.c index d89f117dd0ef..9fe6bbe9ee04 100644 --- a/drivers/iio/chemical/scd30_core.c +++ b/drivers/iio/chemical/scd30_core.c @@ -640,7 +640,8 @@ static int scd30_setup_trigger(struct iio_dev *indio_dev) struct iio_trigger *trig; int ret; - trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, indio_dev->id); + trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, + iio_device_id(indio_dev)); if (!trig) { dev_err(dev, "failed to allocate trigger\n"); return -ENOMEM; diff --git a/drivers/iio/chemical/sgp30.c b/drivers/iio/chemical/sgp30.c index 1029c457be15..2343d444604d 100644 --- a/drivers/iio/chemical/sgp30.c +++ b/drivers/iio/chemical/sgp30.c @@ -425,7 +425,7 @@ static int sgp_check_compat(struct sgp_data *data, product = SGP_VERS_PRODUCT(data); if (product != product_id) { - dev_err(dev, "sensor reports a different product: 0x%04hx\n", + dev_err(dev, "sensor reports a different product: 0x%04x\n", product); return -ENODEV; } diff --git a/drivers/iio/chemical/sps30.c b/drivers/iio/chemical/sps30.c index 2ea9a5c4d846..d51314505115 100644 --- a/drivers/iio/chemical/sps30.c +++ b/drivers/iio/chemical/sps30.c @@ -3,11 +3,8 @@ * Sensirion SPS30 particulate matter sensor driver * * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com> - * - * I2C slave address: 0x69 */ -#include <asm/unaligned.h> #include <linux/crc8.h> #include <linux/delay.h> #include <linux/i2c.h> @@ -19,27 +16,14 @@ #include <linux/kernel.h> #include <linux/module.h> -#define SPS30_CRC8_POLYNOMIAL 0x31 -/* max number of bytes needed to store PM measurements or serial string */ -#define SPS30_MAX_READ_SIZE 48 +#include "sps30.h" + /* sensor measures reliably up to 3000 ug / m3 */ #define SPS30_MAX_PM 3000 /* minimum and maximum self cleaning periods in seconds */ #define SPS30_AUTO_CLEANING_PERIOD_MIN 0 #define SPS30_AUTO_CLEANING_PERIOD_MAX 604800 -/* SPS30 commands */ -#define SPS30_START_MEAS 0x0010 -#define SPS30_STOP_MEAS 0x0104 -#define SPS30_RESET 0xd304 -#define SPS30_READ_DATA_READY_FLAG 0x0202 -#define SPS30_READ_DATA 0x0300 -#define SPS30_READ_SERIAL 0xd033 -#define SPS30_START_FAN_CLEANING 0x5607 -#define SPS30_AUTO_CLEANING_PERIOD 0x8004 -/* not a sensor command per se, used only to distinguish write from read */ -#define SPS30_READ_AUTO_CLEANING_PERIOD 0x8005 - enum { PM1, PM2P5, @@ -52,114 +36,9 @@ enum { MEASURING, }; -struct sps30_state { - struct i2c_client *client; - /* - * Guards against concurrent access to sensor registers. - * Must be held whenever sequence of commands is to be executed. - */ - struct mutex lock; - int state; -}; - -DECLARE_CRC8_TABLE(sps30_crc8_table); - -static int sps30_write_then_read(struct sps30_state *state, u8 *txbuf, - int txsize, u8 *rxbuf, int rxsize) -{ - int ret; - - /* - * Sensor does not support repeated start so instead of - * sending two i2c messages in a row we just send one by one. - */ - ret = i2c_master_send(state->client, txbuf, txsize); - if (ret != txsize) - return ret < 0 ? ret : -EIO; - - if (!rxbuf) - return 0; - - ret = i2c_master_recv(state->client, rxbuf, rxsize); - if (ret != rxsize) - return ret < 0 ? ret : -EIO; - - return 0; -} - -static int sps30_do_cmd(struct sps30_state *state, u16 cmd, u8 *data, int size) -{ - /* - * Internally sensor stores measurements in a following manner: - * - * PM1: upper two bytes, crc8, lower two bytes, crc8 - * PM2P5: upper two bytes, crc8, lower two bytes, crc8 - * PM4: upper two bytes, crc8, lower two bytes, crc8 - * PM10: upper two bytes, crc8, lower two bytes, crc8 - * - * What follows next are number concentration measurements and - * typical particle size measurement which we omit. - */ - u8 buf[SPS30_MAX_READ_SIZE] = { cmd >> 8, cmd }; - int i, ret = 0; - - switch (cmd) { - case SPS30_START_MEAS: - buf[2] = 0x03; - buf[3] = 0x00; - buf[4] = crc8(sps30_crc8_table, &buf[2], 2, CRC8_INIT_VALUE); - ret = sps30_write_then_read(state, buf, 5, NULL, 0); - break; - case SPS30_STOP_MEAS: - case SPS30_RESET: - case SPS30_START_FAN_CLEANING: - ret = sps30_write_then_read(state, buf, 2, NULL, 0); - break; - case SPS30_READ_AUTO_CLEANING_PERIOD: - buf[0] = SPS30_AUTO_CLEANING_PERIOD >> 8; - buf[1] = (u8)(SPS30_AUTO_CLEANING_PERIOD & 0xff); - fallthrough; - case SPS30_READ_DATA_READY_FLAG: - case SPS30_READ_DATA: - case SPS30_READ_SERIAL: - /* every two data bytes are checksummed */ - size += size / 2; - ret = sps30_write_then_read(state, buf, 2, buf, size); - break; - case SPS30_AUTO_CLEANING_PERIOD: - buf[2] = data[0]; - buf[3] = data[1]; - buf[4] = crc8(sps30_crc8_table, &buf[2], 2, CRC8_INIT_VALUE); - buf[5] = data[2]; - buf[6] = data[3]; - buf[7] = crc8(sps30_crc8_table, &buf[5], 2, CRC8_INIT_VALUE); - ret = sps30_write_then_read(state, buf, 8, NULL, 0); - break; - } - - if (ret) - return ret; - - /* validate received data and strip off crc bytes */ - for (i = 0; i < size; i += 3) { - u8 crc = crc8(sps30_crc8_table, &buf[i], 2, CRC8_INIT_VALUE); - - if (crc != buf[i + 2]) { - dev_err(&state->client->dev, - "data integrity check failed\n"); - return -EIO; - } - - *data++ = buf[i]; - *data++ = buf[i + 1]; - } - - return 0; -} - -static s32 sps30_float_to_int_clamped(const u8 *fp) +static s32 sps30_float_to_int_clamped(__be32 *fp) { - int val = get_unaligned_be32(fp); + int val = be32_to_cpup(fp); int mantissa = val & GENMASK(22, 0); /* this is fine since passed float is always non-negative */ int exp = val >> 23; @@ -188,38 +67,35 @@ static s32 sps30_float_to_int_clamped(const u8 *fp) static int sps30_do_meas(struct sps30_state *state, s32 *data, int size) { - int i, ret, tries = 5; - u8 tmp[16]; + int i, ret; if (state->state == RESET) { - ret = sps30_do_cmd(state, SPS30_START_MEAS, NULL, 0); + ret = state->ops->start_meas(state); if (ret) return ret; state->state = MEASURING; } - while (tries--) { - ret = sps30_do_cmd(state, SPS30_READ_DATA_READY_FLAG, tmp, 2); - if (ret) - return -EIO; + ret = state->ops->read_meas(state, (__be32 *)data, size); + if (ret) + return ret; - /* new measurements ready to be read */ - if (tmp[1] == 1) - break; + for (i = 0; i < size; i++) + data[i] = sps30_float_to_int_clamped((__be32 *)&data[i]); - msleep_interruptible(300); - } + return 0; +} - if (tries == -1) - return -ETIMEDOUT; +static int sps30_do_reset(struct sps30_state *state) +{ + int ret; - ret = sps30_do_cmd(state, SPS30_READ_DATA, tmp, sizeof(int) * size); + ret = state->ops->reset(state); if (ret) return ret; - for (i = 0; i < size; i++) - data[i] = sps30_float_to_int_clamped(&tmp[4 * i]); + state->state = RESET; return 0; } @@ -310,24 +186,6 @@ static int sps30_read_raw(struct iio_dev *indio_dev, return -EINVAL; } -static int sps30_do_cmd_reset(struct sps30_state *state) -{ - int ret; - - ret = sps30_do_cmd(state, SPS30_RESET, NULL, 0); - msleep(300); - /* - * Power-on-reset causes sensor to produce some glitch on i2c bus and - * some controllers end up in error state. Recover simply by placing - * some data on the bus, for example STOP_MEAS command, which - * is NOP in this case. - */ - sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0); - state->state = RESET; - - return ret; -} - static ssize_t start_cleaning_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) @@ -340,7 +198,7 @@ static ssize_t start_cleaning_store(struct device *dev, return -EINVAL; mutex_lock(&state->lock); - ret = sps30_do_cmd(state, SPS30_START_FAN_CLEANING, NULL, 0); + ret = state->ops->clean_fan(state); mutex_unlock(&state->lock); if (ret) return ret; @@ -349,31 +207,29 @@ static ssize_t start_cleaning_store(struct device *dev, } static ssize_t cleaning_period_show(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct sps30_state *state = iio_priv(indio_dev); - u8 tmp[4]; + __be32 val; int ret; mutex_lock(&state->lock); - ret = sps30_do_cmd(state, SPS30_READ_AUTO_CLEANING_PERIOD, tmp, 4); + ret = state->ops->read_cleaning_period(state, &val); mutex_unlock(&state->lock); if (ret) return ret; - return sprintf(buf, "%d\n", get_unaligned_be32(tmp)); + return sprintf(buf, "%d\n", be32_to_cpu(val)); } -static ssize_t cleaning_period_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t cleaning_period_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct sps30_state *state = iio_priv(indio_dev); int val, ret; - u8 tmp[4]; if (kstrtoint(buf, 0, &val)) return -EINVAL; @@ -382,10 +238,8 @@ static ssize_t cleaning_period_store(struct device *dev, (val > SPS30_AUTO_CLEANING_PERIOD_MAX)) return -EINVAL; - put_unaligned_be32(val, tmp); - mutex_lock(&state->lock); - ret = sps30_do_cmd(state, SPS30_AUTO_CLEANING_PERIOD, tmp, 0); + ret = state->ops->write_cleaning_period(state, cpu_to_be32(val)); if (ret) { mutex_unlock(&state->lock); return ret; @@ -397,7 +251,7 @@ static ssize_t cleaning_period_store(struct device *dev, * sensor requires reset in order to return up to date self cleaning * period */ - ret = sps30_do_cmd_reset(state); + ret = sps30_do_reset(state); if (ret) dev_warn(dev, "period changed but reads will return the old value\n"); @@ -411,9 +265,9 @@ static ssize_t cleaning_period_available_show(struct device *dev, struct device_attribute *attr, char *buf) { - return snprintf(buf, PAGE_SIZE, "[%d %d %d]\n", - SPS30_AUTO_CLEANING_PERIOD_MIN, 1, - SPS30_AUTO_CLEANING_PERIOD_MAX); + return sysfs_emit(buf, "[%d %d %d]\n", + SPS30_AUTO_CLEANING_PERIOD_MIN, 1, + SPS30_AUTO_CLEANING_PERIOD_MAX); } static IIO_DEVICE_ATTR_WO(start_cleaning, 0); @@ -460,90 +314,65 @@ static const struct iio_chan_spec sps30_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(4), }; -static void sps30_stop_meas(void *data) +static void sps30_devm_stop_meas(void *data) { struct sps30_state *state = data; - sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0); + if (state->state == MEASURING) + state->ops->stop_meas(state); } static const unsigned long sps30_scan_masks[] = { 0x0f, 0x00 }; -static int sps30_probe(struct i2c_client *client) +int sps30_probe(struct device *dev, const char *name, void *priv, const struct sps30_ops *ops) { struct iio_dev *indio_dev; struct sps30_state *state; - u8 buf[32]; int ret; - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) - return -EOPNOTSUPP; - - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*state)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*state)); if (!indio_dev) return -ENOMEM; + dev_set_drvdata(dev, indio_dev); + state = iio_priv(indio_dev); - i2c_set_clientdata(client, indio_dev); - state->client = client; - state->state = RESET; + state->dev = dev; + state->priv = priv; + state->ops = ops; + mutex_init(&state->lock); + indio_dev->info = &sps30_info; - indio_dev->name = client->name; + indio_dev->name = name; indio_dev->channels = sps30_channels; indio_dev->num_channels = ARRAY_SIZE(sps30_channels); indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->available_scan_masks = sps30_scan_masks; - mutex_init(&state->lock); - crc8_populate_msb(sps30_crc8_table, SPS30_CRC8_POLYNOMIAL); - - ret = sps30_do_cmd_reset(state); + ret = sps30_do_reset(state); if (ret) { - dev_err(&client->dev, "failed to reset device\n"); + dev_err(dev, "failed to reset device\n"); return ret; } - ret = sps30_do_cmd(state, SPS30_READ_SERIAL, buf, sizeof(buf)); + ret = state->ops->show_info(state); if (ret) { - dev_err(&client->dev, "failed to read serial number\n"); + dev_err(dev, "failed to read device info\n"); return ret; } - /* returned serial number is already NUL terminated */ - dev_info(&client->dev, "serial number: %s\n", buf); - ret = devm_add_action_or_reset(&client->dev, sps30_stop_meas, state); + ret = devm_add_action_or_reset(dev, sps30_devm_stop_meas, state); if (ret) return ret; - ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL, + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, sps30_trigger_handler, NULL); if (ret) return ret; - return devm_iio_device_register(&client->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } - -static const struct i2c_device_id sps30_id[] = { - { "sps30" }, - { } -}; -MODULE_DEVICE_TABLE(i2c, sps30_id); - -static const struct of_device_id sps30_of_match[] = { - { .compatible = "sensirion,sps30" }, - { } -}; -MODULE_DEVICE_TABLE(of, sps30_of_match); - -static struct i2c_driver sps30_driver = { - .driver = { - .name = "sps30", - .of_match_table = sps30_of_match, - }, - .id_table = sps30_id, - .probe_new = sps30_probe, -}; -module_i2c_driver(sps30_driver); +EXPORT_SYMBOL_GPL(sps30_probe); MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>"); MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor driver"); diff --git a/drivers/iio/chemical/sps30.h b/drivers/iio/chemical/sps30.h new file mode 100644 index 000000000000..a58ee43cf45d --- /dev/null +++ b/drivers/iio/chemical/sps30.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _SPS30_H +#define _SPS30_H + +#include <linux/types.h> + +struct sps30_state; +struct sps30_ops { + int (*start_meas)(struct sps30_state *state); + int (*stop_meas)(struct sps30_state *state); + int (*read_meas)(struct sps30_state *state, __be32 *meas, size_t num); + int (*reset)(struct sps30_state *state); + int (*clean_fan)(struct sps30_state *state); + int (*read_cleaning_period)(struct sps30_state *state, __be32 *period); + int (*write_cleaning_period)(struct sps30_state *state, __be32 period); + int (*show_info)(struct sps30_state *state); +}; + +struct sps30_state { + /* serialize access to the device */ + struct mutex lock; + struct device *dev; + int state; + /* + * priv pointer is solely for serdev driver private data. We keep it + * here because driver_data inside dev has been already used for iio and + * struct serdev_device doesn't have one. + */ + void *priv; + const struct sps30_ops *ops; +}; + +int sps30_probe(struct device *dev, const char *name, void *priv, const struct sps30_ops *ops); + +#endif diff --git a/drivers/iio/chemical/sps30_i2c.c b/drivers/iio/chemical/sps30_i2c.c new file mode 100644 index 000000000000..d33560ed7184 --- /dev/null +++ b/drivers/iio/chemical/sps30_i2c.c @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Sensirion SPS30 particulate matter sensor i2c driver + * + * Copyright (c) 2020 Tomasz Duszynski <tomasz.duszynski@octakon.com> + * + * I2C slave address: 0x69 + */ +#include <asm/unaligned.h> +#include <linux/crc8.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/i2c.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/types.h> + +#include "sps30.h" + +#define SPS30_I2C_CRC8_POLYNOMIAL 0x31 +/* max number of bytes needed to store PM measurements or serial string */ +#define SPS30_I2C_MAX_BUF_SIZE 48 + +DECLARE_CRC8_TABLE(sps30_i2c_crc8_table); + +#define SPS30_I2C_START_MEAS 0x0010 +#define SPS30_I2C_STOP_MEAS 0x0104 +#define SPS30_I2C_READ_MEAS 0x0300 +#define SPS30_I2C_MEAS_READY 0x0202 +#define SPS30_I2C_RESET 0xd304 +#define SPS30_I2C_CLEAN_FAN 0x5607 +#define SPS30_I2C_PERIOD 0x8004 +#define SPS30_I2C_READ_SERIAL 0xd033 +#define SPS30_I2C_READ_VERSION 0xd100 + +static int sps30_i2c_xfer(struct sps30_state *state, unsigned char *txbuf, size_t txsize, + unsigned char *rxbuf, size_t rxsize) +{ + struct i2c_client *client = to_i2c_client(state->dev); + int ret; + + /* + * Sensor does not support repeated start so instead of + * sending two i2c messages in a row we just send one by one. + */ + ret = i2c_master_send(client, txbuf, txsize); + if (ret < 0) + return ret; + if (ret != txsize) + return -EIO; + + if (!rxsize) + return 0; + + ret = i2c_master_recv(client, rxbuf, rxsize); + if (ret < 0) + return ret; + if (ret != rxsize) + return -EIO; + + return 0; +} + +static int sps30_i2c_command(struct sps30_state *state, u16 cmd, void *arg, size_t arg_size, + void *rsp, size_t rsp_size) +{ + /* + * Internally sensor stores measurements in a following manner: + * + * PM1: upper two bytes, crc8, lower two bytes, crc8 + * PM2P5: upper two bytes, crc8, lower two bytes, crc8 + * PM4: upper two bytes, crc8, lower two bytes, crc8 + * PM10: upper two bytes, crc8, lower two bytes, crc8 + * + * What follows next are number concentration measurements and + * typical particle size measurement which we omit. + */ + unsigned char buf[SPS30_I2C_MAX_BUF_SIZE]; + unsigned char *tmp; + unsigned char crc; + size_t i; + int ret; + + put_unaligned_be16(cmd, buf); + i = 2; + + if (rsp) { + /* each two bytes are followed by a crc8 */ + rsp_size += rsp_size / 2; + } else { + tmp = arg; + + while (arg_size) { + buf[i] = *tmp++; + buf[i + 1] = *tmp++; + buf[i + 2] = crc8(sps30_i2c_crc8_table, buf + i, 2, CRC8_INIT_VALUE); + arg_size -= 2; + i += 3; + } + } + + ret = sps30_i2c_xfer(state, buf, i, buf, rsp_size); + if (ret) + return ret; + + /* validate received data and strip off crc bytes */ + tmp = rsp; + for (i = 0; i < rsp_size; i += 3) { + crc = crc8(sps30_i2c_crc8_table, buf + i, 2, CRC8_INIT_VALUE); + if (crc != buf[i + 2]) { + dev_err(state->dev, "data integrity check failed\n"); + return -EIO; + } + + *tmp++ = buf[i]; + *tmp++ = buf[i + 1]; + } + + return 0; +} + +static int sps30_i2c_start_meas(struct sps30_state *state) +{ + /* request BE IEEE754 formatted data */ + unsigned char buf[] = { 0x03, 0x00 }; + + return sps30_i2c_command(state, SPS30_I2C_START_MEAS, buf, sizeof(buf), NULL, 0); +} + +static int sps30_i2c_stop_meas(struct sps30_state *state) +{ + return sps30_i2c_command(state, SPS30_I2C_STOP_MEAS, NULL, 0, NULL, 0); +} + +static int sps30_i2c_reset(struct sps30_state *state) +{ + int ret; + + ret = sps30_i2c_command(state, SPS30_I2C_RESET, NULL, 0, NULL, 0); + msleep(500); + /* + * Power-on-reset causes sensor to produce some glitch on i2c bus and + * some controllers end up in error state. Recover simply by placing + * some data on the bus, for example STOP_MEAS command, which + * is NOP in this case. + */ + sps30_i2c_stop_meas(state); + + return ret; +} + +static bool sps30_i2c_meas_ready(struct sps30_state *state) +{ + unsigned char buf[2]; + int ret; + + ret = sps30_i2c_command(state, SPS30_I2C_MEAS_READY, NULL, 0, buf, sizeof(buf)); + if (ret) + return false; + + return buf[1]; +} + +static int sps30_i2c_read_meas(struct sps30_state *state, __be32 *meas, size_t num) +{ + /* measurements are ready within a second */ + if (msleep_interruptible(1000)) + return -EINTR; + + if (!sps30_i2c_meas_ready(state)) + return -ETIMEDOUT; + + return sps30_i2c_command(state, SPS30_I2C_READ_MEAS, NULL, 0, meas, sizeof(num) * num); +} + +static int sps30_i2c_clean_fan(struct sps30_state *state) +{ + return sps30_i2c_command(state, SPS30_I2C_CLEAN_FAN, NULL, 0, NULL, 0); +} + +static int sps30_i2c_read_cleaning_period(struct sps30_state *state, __be32 *period) +{ + return sps30_i2c_command(state, SPS30_I2C_PERIOD, NULL, 0, period, sizeof(*period)); +} + +static int sps30_i2c_write_cleaning_period(struct sps30_state *state, __be32 period) +{ + return sps30_i2c_command(state, SPS30_I2C_PERIOD, &period, sizeof(period), NULL, 0); +} + +static int sps30_i2c_show_info(struct sps30_state *state) +{ + /* extra nul just in case */ + unsigned char buf[32 + 1] = { 0x00 }; + int ret; + + ret = sps30_i2c_command(state, SPS30_I2C_READ_SERIAL, NULL, 0, buf, sizeof(buf) - 1); + if (ret) + return ret; + + dev_info(state->dev, "serial number: %s\n", buf); + + ret = sps30_i2c_command(state, SPS30_I2C_READ_VERSION, NULL, 0, buf, 2); + if (ret) + return ret; + + dev_info(state->dev, "fw version: %u.%u\n", buf[0], buf[1]); + + return 0; +} + +static const struct sps30_ops sps30_i2c_ops = { + .start_meas = sps30_i2c_start_meas, + .stop_meas = sps30_i2c_stop_meas, + .read_meas = sps30_i2c_read_meas, + .reset = sps30_i2c_reset, + .clean_fan = sps30_i2c_clean_fan, + .read_cleaning_period = sps30_i2c_read_cleaning_period, + .write_cleaning_period = sps30_i2c_write_cleaning_period, + .show_info = sps30_i2c_show_info, +}; + +static int sps30_i2c_probe(struct i2c_client *client) +{ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -EOPNOTSUPP; + + crc8_populate_msb(sps30_i2c_crc8_table, SPS30_I2C_CRC8_POLYNOMIAL); + + return sps30_probe(&client->dev, client->name, NULL, &sps30_i2c_ops); +} + +static const struct i2c_device_id sps30_i2c_id[] = { + { "sps30" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, sps30_i2c_id); + +static const struct of_device_id sps30_i2c_of_match[] = { + { .compatible = "sensirion,sps30" }, + { } +}; +MODULE_DEVICE_TABLE(of, sps30_i2c_of_match); + +static struct i2c_driver sps30_i2c_driver = { + .driver = { + .name = KBUILD_MODNAME, + .of_match_table = sps30_i2c_of_match, + }, + .id_table = sps30_i2c_id, + .probe_new = sps30_i2c_probe, +}; +module_i2c_driver(sps30_i2c_driver); + +MODULE_AUTHOR("Tomasz Duszynski <tomasz.duszynski@octakon.com>"); +MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor i2c driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/chemical/sps30_serial.c b/drivers/iio/chemical/sps30_serial.c new file mode 100644 index 000000000000..3f311d50087c --- /dev/null +++ b/drivers/iio/chemical/sps30_serial.c @@ -0,0 +1,431 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Sensirion SPS30 particulate matter sensor serial driver + * + * Copyright (c) 2021 Tomasz Duszynski <tomasz.duszynski@octakon.com> + */ +#include <linux/completion.h> +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/iio/iio.h> +#include <linux/minmax.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/serdev.h> +#include <linux/types.h> + +#include "sps30.h" + +#define SPS30_SERIAL_DEV_NAME "sps30" + +#define SPS30_SERIAL_SOF_EOF 0x7e +#define SPS30_SERIAL_TIMEOUT msecs_to_jiffies(20) +#define SPS30_SERIAL_MAX_BUF_SIZE 263 +#define SPS30_SERIAL_ESCAPE_CHAR 0x7d + +#define SPS30_SERIAL_FRAME_MIN_SIZE 7 +#define SPS30_SERIAL_FRAME_ADR_OFFSET 1 +#define SPS30_SERIAL_FRAME_CMD_OFFSET 2 +#define SPS30_SERIAL_FRAME_MOSI_LEN_OFFSET 3 +#define SPS30_SERIAL_FRAME_MISO_STATE_OFFSET 3 +#define SPS30_SERIAL_FRAME_MISO_LEN_OFFSET 4 +#define SPS30_SERIAL_FRAME_MISO_DATA_OFFSET 5 + +#define SPS30_SERIAL_START_MEAS 0x00 +#define SPS30_SERIAL_STOP_MEAS 0x01 +#define SPS30_SERIAL_READ_MEAS 0x03 +#define SPS30_SERIAL_RESET 0xd3 +#define SPS30_SERIAL_CLEAN_FAN 0x56 +#define SPS30_SERIAL_PERIOD 0x80 +#define SPS30_SERIAL_DEV_INFO 0xd0 +#define SPS30_SERIAL_READ_VERSION 0xd1 + +struct sps30_serial_priv { + struct completion new_frame; + unsigned char buf[SPS30_SERIAL_MAX_BUF_SIZE]; + size_t num; + bool escaped; + bool done; +}; + +static int sps30_serial_xfer(struct sps30_state *state, const unsigned char *buf, size_t size) +{ + struct serdev_device *serdev = to_serdev_device(state->dev); + struct sps30_serial_priv *priv = state->priv; + int ret; + + priv->num = 0; + priv->escaped = false; + priv->done = false; + + ret = serdev_device_write(serdev, buf, size, SPS30_SERIAL_TIMEOUT); + if (ret < 0) + return ret; + if (ret != size) + return -EIO; + + ret = wait_for_completion_interruptible_timeout(&priv->new_frame, SPS30_SERIAL_TIMEOUT); + if (ret < 0) + return ret; + if (!ret) + return -ETIMEDOUT; + + return 0; +} + +static const struct { + unsigned char byte; + unsigned char byte2; +} sps30_serial_bytes[] = { + { 0x11, 0x31 }, + { 0x13, 0x33 }, + { 0x7e, 0x5e }, + { 0x7d, 0x5d }, +}; + +static int sps30_serial_put_byte(unsigned char *buf, unsigned char byte) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(sps30_serial_bytes); i++) { + if (sps30_serial_bytes[i].byte != byte) + continue; + + buf[0] = SPS30_SERIAL_ESCAPE_CHAR; + buf[1] = sps30_serial_bytes[i].byte2; + + return 2; + } + + buf[0] = byte; + + return 1; +} + +static char sps30_serial_get_byte(bool escaped, unsigned char byte2) +{ + int i; + + if (!escaped) + return byte2; + + for (i = 0; i < ARRAY_SIZE(sps30_serial_bytes); i++) { + if (sps30_serial_bytes[i].byte2 != byte2) + continue; + + return sps30_serial_bytes[i].byte; + } + + return 0; +} + +static unsigned char sps30_serial_calc_chksum(const unsigned char *buf, size_t num) +{ + unsigned int chksum = 0; + size_t i; + + for (i = 0; i < num; i++) + chksum += buf[i]; + + return ~chksum; +} + +static int sps30_serial_prep_frame(unsigned char *buf, unsigned char cmd, + const unsigned char *arg, size_t arg_size) +{ + unsigned char chksum; + int num = 0; + size_t i; + + buf[num++] = SPS30_SERIAL_SOF_EOF; + buf[num++] = 0; + num += sps30_serial_put_byte(buf + num, cmd); + num += sps30_serial_put_byte(buf + num, arg_size); + + for (i = 0; i < arg_size; i++) + num += sps30_serial_put_byte(buf + num, arg[i]); + + /* SOF isn't checksummed */ + chksum = sps30_serial_calc_chksum(buf + 1, num - 1); + num += sps30_serial_put_byte(buf + num, chksum); + buf[num++] = SPS30_SERIAL_SOF_EOF; + + return num; +} + +static bool sps30_serial_frame_valid(struct sps30_state *state, const unsigned char *buf) +{ + struct sps30_serial_priv *priv = state->priv; + unsigned char chksum; + + if ((priv->num < SPS30_SERIAL_FRAME_MIN_SIZE) || + (priv->num != SPS30_SERIAL_FRAME_MIN_SIZE + + priv->buf[SPS30_SERIAL_FRAME_MISO_LEN_OFFSET])) { + dev_err(state->dev, "frame has invalid number of bytes\n"); + return false; + } + + if ((priv->buf[SPS30_SERIAL_FRAME_ADR_OFFSET] != buf[SPS30_SERIAL_FRAME_ADR_OFFSET]) || + (priv->buf[SPS30_SERIAL_FRAME_CMD_OFFSET] != buf[SPS30_SERIAL_FRAME_CMD_OFFSET])) { + dev_err(state->dev, "frame has wrong ADR and CMD bytes\n"); + return false; + } + + if (priv->buf[SPS30_SERIAL_FRAME_MISO_STATE_OFFSET]) { + dev_err(state->dev, "frame with non-zero state received (0x%02x)\n", + priv->buf[SPS30_SERIAL_FRAME_MISO_STATE_OFFSET]); + return false; + } + + /* SOF, checksum and EOF are not checksummed */ + chksum = sps30_serial_calc_chksum(priv->buf + 1, priv->num - 3); + if (priv->buf[priv->num - 2] != chksum) { + dev_err(state->dev, "frame integrity check failed\n"); + return false; + } + + return true; +} + +static int sps30_serial_command(struct sps30_state *state, unsigned char cmd, + const void *arg, size_t arg_size, void *rsp, size_t rsp_size) +{ + struct sps30_serial_priv *priv = state->priv; + unsigned char buf[SPS30_SERIAL_MAX_BUF_SIZE]; + int ret, size; + + size = sps30_serial_prep_frame(buf, cmd, arg, arg_size); + ret = sps30_serial_xfer(state, buf, size); + if (ret) + return ret; + + if (!sps30_serial_frame_valid(state, buf)) + return -EIO; + + if (rsp) { + rsp_size = min_t(size_t, priv->buf[SPS30_SERIAL_FRAME_MISO_LEN_OFFSET], rsp_size); + memcpy(rsp, &priv->buf[SPS30_SERIAL_FRAME_MISO_DATA_OFFSET], rsp_size); + } + + return rsp_size; +} + +static int sps30_serial_receive_buf(struct serdev_device *serdev, + const unsigned char *buf, size_t size) +{ + struct iio_dev *indio_dev = dev_get_drvdata(&serdev->dev); + struct sps30_serial_priv *priv; + struct sps30_state *state; + unsigned char byte; + size_t i; + + if (!indio_dev) + return 0; + + state = iio_priv(indio_dev); + priv = state->priv; + + /* just in case device put some unexpected data on the bus */ + if (priv->done) + return size; + + /* wait for the start of frame */ + if (!priv->num && size && buf[0] != SPS30_SERIAL_SOF_EOF) + return 1; + + if (priv->num + size >= ARRAY_SIZE(priv->buf)) + size = ARRAY_SIZE(priv->buf) - priv->num; + + for (i = 0; i < size; i++) { + byte = buf[i]; + /* remove stuffed bytes on-the-fly */ + if (byte == SPS30_SERIAL_ESCAPE_CHAR) { + priv->escaped = true; + continue; + } + + byte = sps30_serial_get_byte(priv->escaped, byte); + if (priv->escaped && !byte) + dev_warn(state->dev, "unrecognized escaped char (0x%02x)\n", byte); + + priv->buf[priv->num++] = byte; + + /* EOF received */ + if (!priv->escaped && byte == SPS30_SERIAL_SOF_EOF) { + if (priv->num < SPS30_SERIAL_FRAME_MIN_SIZE) + continue; + + priv->done = true; + complete(&priv->new_frame); + i++; + break; + } + + priv->escaped = false; + } + + return i; +} + +static const struct serdev_device_ops sps30_serial_device_ops = { + .receive_buf = sps30_serial_receive_buf, + .write_wakeup = serdev_device_write_wakeup, +}; + +static int sps30_serial_start_meas(struct sps30_state *state) +{ + /* request BE IEEE754 formatted data */ + unsigned char buf[] = { 0x01, 0x03 }; + + return sps30_serial_command(state, SPS30_SERIAL_START_MEAS, buf, sizeof(buf), NULL, 0); +} + +static int sps30_serial_stop_meas(struct sps30_state *state) +{ + return sps30_serial_command(state, SPS30_SERIAL_STOP_MEAS, NULL, 0, NULL, 0); +} + +static int sps30_serial_reset(struct sps30_state *state) +{ + int ret; + + ret = sps30_serial_command(state, SPS30_SERIAL_RESET, NULL, 0, NULL, 0); + msleep(500); + + return ret; +} + +static int sps30_serial_read_meas(struct sps30_state *state, __be32 *meas, size_t num) +{ + int ret; + + /* measurements are ready within a second */ + if (msleep_interruptible(1000)) + return -EINTR; + + ret = sps30_serial_command(state, SPS30_SERIAL_READ_MEAS, NULL, 0, meas, num * sizeof(num)); + if (ret < 0) + return ret; + /* if measurements aren't ready sensor returns empty frame */ + if (ret == SPS30_SERIAL_FRAME_MIN_SIZE) + return -ETIMEDOUT; + if (ret != num * sizeof(*meas)) + return -EIO; + + return 0; +} + +static int sps30_serial_clean_fan(struct sps30_state *state) +{ + return sps30_serial_command(state, SPS30_SERIAL_CLEAN_FAN, NULL, 0, NULL, 0); +} + +static int sps30_serial_read_cleaning_period(struct sps30_state *state, __be32 *period) +{ + unsigned char buf[] = { 0x00 }; + int ret; + + ret = sps30_serial_command(state, SPS30_SERIAL_PERIOD, buf, sizeof(buf), + period, sizeof(*period)); + if (ret < 0) + return ret; + if (ret != sizeof(*period)) + return -EIO; + + return 0; +} + +static int sps30_serial_write_cleaning_period(struct sps30_state *state, __be32 period) +{ + unsigned char buf[5] = { 0x00 }; + + memcpy(buf + 1, &period, sizeof(period)); + + return sps30_serial_command(state, SPS30_SERIAL_PERIOD, buf, sizeof(buf), NULL, 0); +} + +static int sps30_serial_show_info(struct sps30_state *state) +{ + /* + * tell device do return serial number and add extra nul byte just in case + * serial number isn't a valid string + */ + unsigned char buf[32 + 1] = { 0x03 }; + struct device *dev = state->dev; + int ret; + + ret = sps30_serial_command(state, SPS30_SERIAL_DEV_INFO, buf, 1, buf, sizeof(buf) - 1); + if (ret < 0) + return ret; + if (ret != sizeof(buf) - 1) + return -EIO; + + dev_info(dev, "serial number: %s\n", buf); + + ret = sps30_serial_command(state, SPS30_SERIAL_READ_VERSION, NULL, 0, buf, sizeof(buf) - 1); + if (ret < 0) + return ret; + if (ret < 2) + return -EIO; + + dev_info(dev, "fw version: %u.%u\n", buf[0], buf[1]); + + return 0; +} + +static const struct sps30_ops sps30_serial_ops = { + .start_meas = sps30_serial_start_meas, + .stop_meas = sps30_serial_stop_meas, + .read_meas = sps30_serial_read_meas, + .reset = sps30_serial_reset, + .clean_fan = sps30_serial_clean_fan, + .read_cleaning_period = sps30_serial_read_cleaning_period, + .write_cleaning_period = sps30_serial_write_cleaning_period, + .show_info = sps30_serial_show_info, +}; + +static int sps30_serial_probe(struct serdev_device *serdev) +{ + struct device *dev = &serdev->dev; + struct sps30_serial_priv *priv; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + init_completion(&priv->new_frame); + serdev_device_set_client_ops(serdev, &sps30_serial_device_ops); + + ret = devm_serdev_device_open(dev, serdev); + if (ret) + return ret; + + serdev_device_set_baudrate(serdev, 115200); + serdev_device_set_flow_control(serdev, false); + + ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE); + if (ret) + return ret; + + return sps30_probe(dev, SPS30_SERIAL_DEV_NAME, priv, &sps30_serial_ops); +} + +static const struct of_device_id sps30_serial_of_match[] = { + { .compatible = "sensirion,sps30" }, + { } +}; +MODULE_DEVICE_TABLE(of, sps30_serial_of_match); + +static struct serdev_device_driver sps30_serial_driver = { + .driver = { + .name = KBUILD_MODNAME, + .of_match_table = sps30_serial_of_match, + }, + .probe = sps30_serial_probe, +}; +module_serdev_device_driver(sps30_serial_driver); + +MODULE_AUTHOR("Tomasz Duszynski <tomasz.duszynski@octakon.com>"); +MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor serial driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c index cb52b4fd6bf7..043f199e7bc6 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c @@ -3,18 +3,12 @@ * HID Sensors Driver * Copyright (c) 2012, Intel Corporation. */ -#include <linux/device.h> -#include <linux/platform_device.h> #include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/irq.h> #include <linux/kernel.h> -#include <linux/slab.h> #include <linux/time.h> #include <linux/hid-sensor-hub.h> #include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> #define HZ_PER_MHZ 1000000L @@ -176,7 +170,7 @@ s32 hid_sensor_read_poll_value(struct hid_sensor_common *st) return value; } -EXPORT_SYMBOL(hid_sensor_read_poll_value); +EXPORT_SYMBOL_NS(hid_sensor_read_poll_value, IIO_HID_ATTRIBUTES); int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st, int *val1, int *val2) @@ -203,7 +197,7 @@ int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st, return IIO_VAL_INT_PLUS_MICRO; } -EXPORT_SYMBOL(hid_sensor_read_samp_freq_value); +EXPORT_SYMBOL_NS(hid_sensor_read_samp_freq_value, IIO_HID); int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st, int val1, int val2) @@ -238,7 +232,7 @@ int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st, return 0; } -EXPORT_SYMBOL(hid_sensor_write_samp_freq_value); +EXPORT_SYMBOL_NS(hid_sensor_write_samp_freq_value, IIO_HID); int hid_sensor_read_raw_hyst_value(struct hid_sensor_common *st, int *val1, int *val2) @@ -261,7 +255,7 @@ int hid_sensor_read_raw_hyst_value(struct hid_sensor_common *st, return IIO_VAL_INT_PLUS_MICRO; } -EXPORT_SYMBOL(hid_sensor_read_raw_hyst_value); +EXPORT_SYMBOL_NS(hid_sensor_read_raw_hyst_value, IIO_HID); int hid_sensor_read_raw_hyst_rel_value(struct hid_sensor_common *st, int *val1, int *val2) @@ -283,7 +277,7 @@ int hid_sensor_read_raw_hyst_rel_value(struct hid_sensor_common *st, int *val1, return IIO_VAL_INT_PLUS_MICRO; } -EXPORT_SYMBOL(hid_sensor_read_raw_hyst_rel_value); +EXPORT_SYMBOL_NS(hid_sensor_read_raw_hyst_rel_value, IIO_HID); int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st, @@ -315,7 +309,7 @@ int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st, return 0; } -EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value); +EXPORT_SYMBOL_NS(hid_sensor_write_raw_hyst_value, IIO_HID); int hid_sensor_write_raw_hyst_rel_value(struct hid_sensor_common *st, int val1, int val2) @@ -346,7 +340,7 @@ int hid_sensor_write_raw_hyst_rel_value(struct hid_sensor_common *st, return 0; } -EXPORT_SYMBOL(hid_sensor_write_raw_hyst_rel_value); +EXPORT_SYMBOL_NS(hid_sensor_write_raw_hyst_rel_value, IIO_HID); /* * This fuction applies the unit exponent to the scale. @@ -430,14 +424,14 @@ int hid_sensor_format_scale(u32 usage_id, return IIO_VAL_INT_PLUS_NANO; } -EXPORT_SYMBOL(hid_sensor_format_scale); +EXPORT_SYMBOL_NS(hid_sensor_format_scale, IIO_HID); int64_t hid_sensor_convert_timestamp(struct hid_sensor_common *st, int64_t raw_value) { return st->timestamp_ns_scale * raw_value; } -EXPORT_SYMBOL(hid_sensor_convert_timestamp); +EXPORT_SYMBOL_NS(hid_sensor_convert_timestamp, IIO_HID); static int hid_sensor_get_reporting_interval(struct hid_sensor_hub_device *hsdev, @@ -484,7 +478,7 @@ int hid_sensor_get_report_latency(struct hid_sensor_common *st) return value; } -EXPORT_SYMBOL(hid_sensor_get_report_latency); +EXPORT_SYMBOL_NS(hid_sensor_get_report_latency, IIO_HID_ATTRIBUTES); int hid_sensor_set_report_latency(struct hid_sensor_common *st, int latency_ms) { @@ -492,13 +486,13 @@ int hid_sensor_set_report_latency(struct hid_sensor_common *st, int latency_ms) st->report_latency.index, sizeof(latency_ms), &latency_ms); } -EXPORT_SYMBOL(hid_sensor_set_report_latency); +EXPORT_SYMBOL_NS(hid_sensor_set_report_latency, IIO_HID_ATTRIBUTES); bool hid_sensor_batch_mode_supported(struct hid_sensor_common *st) { return st->report_latency.index > 0 && st->report_latency.report_id > 0; } -EXPORT_SYMBOL(hid_sensor_batch_mode_supported); +EXPORT_SYMBOL_NS(hid_sensor_batch_mode_supported, IIO_HID_ATTRIBUTES); int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, u32 usage_id, @@ -590,7 +584,7 @@ int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, return 0; } -EXPORT_SYMBOL(hid_sensor_parse_common_attributes); +EXPORT_SYMBOL_NS(hid_sensor_parse_common_attributes, IIO_HID); MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); MODULE_DESCRIPTION("HID Sensor common attribute processing"); diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index 95ddccb44f1c..a4ec11a3b68a 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c @@ -6,16 +6,13 @@ #include <linux/device.h> #include <linux/platform_device.h> #include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/slab.h> #include <linux/delay.h> #include <linux/hid-sensor-hub.h> +#include <linux/workqueue.h> #include <linux/iio/iio.h> #include <linux/iio/trigger.h> #include <linux/iio/triggered_buffer.h> #include <linux/iio/trigger_consumer.h> -#include <linux/iio/buffer.h> #include <linux/iio/sysfs.h> #include "hid-sensor-trigger.h" @@ -150,7 +147,7 @@ static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state) return 0; } -EXPORT_SYMBOL(hid_sensor_power_state); +EXPORT_SYMBOL_NS(hid_sensor_power_state, IIO_HID); int hid_sensor_power_state(struct hid_sensor_common *st, bool state) { @@ -163,18 +160,15 @@ int hid_sensor_power_state(struct hid_sensor_common *st, bool state) if (state) { atomic_inc(&st->user_requested_state); - ret = pm_runtime_get_sync(&st->pdev->dev); + ret = pm_runtime_resume_and_get(&st->pdev->dev); } else { atomic_dec(&st->user_requested_state); pm_runtime_mark_last_busy(&st->pdev->dev); pm_runtime_use_autosuspend(&st->pdev->dev); ret = pm_runtime_put_autosuspend(&st->pdev->dev); } - if (ret < 0) { - if (state) - pm_runtime_put_noidle(&st->pdev->dev); + if (ret < 0) return ret; - } return 0; #else @@ -222,14 +216,13 @@ void hid_sensor_remove_trigger(struct iio_dev *indio_dev, pm_runtime_disable(&attrb->pdev->dev); pm_runtime_set_suspended(&attrb->pdev->dev); - pm_runtime_put_noidle(&attrb->pdev->dev); cancel_work_sync(&attrb->work); iio_trigger_unregister(attrb->trigger); iio_trigger_free(attrb->trigger); iio_triggered_buffer_cleanup(indio_dev); } -EXPORT_SYMBOL(hid_sensor_remove_trigger); +EXPORT_SYMBOL_NS(hid_sensor_remove_trigger, IIO_HID); static const struct iio_trigger_ops hid_sensor_trigger_ops = { .set_trigger_state = &hid_sensor_data_rdy_trigger_set_state, @@ -256,7 +249,7 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, } trig = iio_trigger_alloc(indio_dev->dev.parent, - "%s-dev%d", name, indio_dev->id); + "%s-dev%d", name, iio_device_id(indio_dev)); if (trig == NULL) { dev_err(&indio_dev->dev, "Trigger Allocate Failed\n"); ret = -ENOMEM; @@ -295,7 +288,7 @@ error_triggered_buffer_cleanup: iio_triggered_buffer_cleanup(indio_dev); return ret; } -EXPORT_SYMBOL(hid_sensor_setup_trigger); +EXPORT_SYMBOL_NS(hid_sensor_setup_trigger, IIO_HID); static int __maybe_unused hid_sensor_suspend(struct device *dev) { @@ -325,8 +318,9 @@ const struct dev_pm_ops hid_sensor_pm_ops = { SET_RUNTIME_PM_OPS(hid_sensor_suspend, hid_sensor_runtime_resume, NULL) }; -EXPORT_SYMBOL(hid_sensor_pm_ops); +EXPORT_SYMBOL_NS(hid_sensor_pm_ops, IIO_HID); MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); MODULE_DESCRIPTION("HID Sensor trigger processing"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(IIO_HID_ATTRIBUTES); diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h index bb45cc89e551..f94fca4f1edf 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h @@ -9,6 +9,9 @@ #include <linux/pm.h> #include <linux/pm_runtime.h> +struct hid_sensor_common; +struct iio_dev; + extern const struct dev_pm_ops hid_sensor_pm_ops; int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, diff --git a/drivers/iio/common/scmi_sensors/Makefile b/drivers/iio/common/scmi_sensors/Makefile index f13140a2575a..645e0fce1a73 100644 --- a/drivers/iio/common/scmi_sensors/Makefile +++ b/drivers/iio/common/scmi_sensors/Makefile @@ -1,4 +1,4 @@ -# SPDX - License - Identifier : GPL - 2.0 - only +# SPDX-License-Identifier: GPL-2.0-only # # Makefile for the IIO over SCMI # diff --git a/drivers/iio/common/scmi_sensors/scmi_iio.c b/drivers/iio/common/scmi_sensors/scmi_iio.c index 141e8aa6911e..7cf2bf282cef 100644 --- a/drivers/iio/common/scmi_sensors/scmi_iio.c +++ b/drivers/iio/common/scmi_sensors/scmi_iio.c @@ -525,7 +525,6 @@ scmi_alloc_iiodev(struct scmi_device *sdev, return ERR_PTR(-ENOMEM); iiodev->modes = INDIO_DIRECT_MODE; - iiodev->dev.parent = dev; sensor = iio_priv(iiodev); sensor->sensor_ops = ops; sensor->ph = ph; diff --git a/drivers/iio/dac/ad5766.c b/drivers/iio/dac/ad5766.c index 79837a4b3a41..3104ec32dfac 100644 --- a/drivers/iio/dac/ad5766.c +++ b/drivers/iio/dac/ad5766.c @@ -597,8 +597,6 @@ static int ad5766_probe(struct spi_device *spi) indio_dev->channels = st->chip_info->channels; indio_dev->num_channels = st->chip_info->num_channels; indio_dev->info = &ad5766_info; - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/stm32-dac.c b/drivers/iio/dac/stm32-dac.c index a5b0a52bf86e..dd2e306824e7 100644 --- a/drivers/iio/dac/stm32-dac.c +++ b/drivers/iio/dac/stm32-dac.c @@ -69,9 +69,8 @@ static int stm32_dac_set_enable_state(struct iio_dev *indio_dev, int ch, } if (enable) { - ret = pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); if (ret < 0) { - pm_runtime_put_noidle(dev); mutex_unlock(&dac->lock); return ret; } diff --git a/drivers/iio/dummy/Kconfig b/drivers/iio/dummy/Kconfig index 5c5c2f8c55f3..1f46cb9e51b7 100644 --- a/drivers/iio/dummy/Kconfig +++ b/drivers/iio/dummy/Kconfig @@ -34,6 +34,7 @@ config IIO_SIMPLE_DUMMY_BUFFER select IIO_BUFFER select IIO_TRIGGER select IIO_KFIFO_BUF + select IIO_TRIGGERED_BUFFER help Add buffered data capture to the simple dummy driver. diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index 1462a6a5bc6d..3d9eba716b69 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -563,8 +563,10 @@ static int adf4350_probe(struct spi_device *spi) st->lock_detect_gpiod = devm_gpiod_get_optional(&spi->dev, NULL, GPIOD_IN); - if (IS_ERR(st->lock_detect_gpiod)) - return PTR_ERR(st->lock_detect_gpiod); + if (IS_ERR(st->lock_detect_gpiod)) { + ret = PTR_ERR(st->lock_detect_gpiod); + goto error_disable_reg; + } if (pdata->power_up_frequency) { ret = adf4350_set_freq(st, pdata->power_up_frequency); diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c index a11ae9db0d11..36879f01e28c 100644 --- a/drivers/iio/gyro/adis16136.c +++ b/drivers/iio/gyro/adis16136.c @@ -6,19 +6,14 @@ * Author: Lars-Peter Clausen <lars@metafoo.de> */ -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/mutex.h> #include <linux/device.h> #include <linux/kernel.h> #include <linux/spi/spi.h> -#include <linux/slab.h> #include <linux/sysfs.h> #include <linux/module.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> -#include <linux/iio/buffer.h> #include <linux/iio/imu/adis.h> #include <linux/debugfs.h> @@ -223,13 +218,12 @@ static ssize_t adis16136_read_frequency(struct device *dev, { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct adis16136 *adis16136 = iio_priv(indio_dev); - struct mutex *slock = &adis16136->adis.state_lock; unsigned int freq; int ret; - mutex_lock(slock); + adis_dev_lock(&adis16136->adis); ret = __adis16136_get_freq(adis16136, &freq); - mutex_unlock(slock); + adis_dev_unlock(&adis16136->adis); if (ret) return ret; @@ -254,11 +248,10 @@ static const unsigned adis16136_3db_divisors[] = { static int adis16136_set_filter(struct iio_dev *indio_dev, int val) { struct adis16136 *adis16136 = iio_priv(indio_dev); - struct mutex *slock = &adis16136->adis.state_lock; unsigned int freq; int i, ret; - mutex_lock(slock); + adis_dev_lock(&adis16136->adis); ret = __adis16136_get_freq(adis16136, &freq); if (ret) goto out_unlock; @@ -270,7 +263,7 @@ static int adis16136_set_filter(struct iio_dev *indio_dev, int val) ret = __adis_write_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, i); out_unlock: - mutex_unlock(slock); + adis_dev_unlock(&adis16136->adis); return ret; } @@ -278,12 +271,11 @@ out_unlock: static int adis16136_get_filter(struct iio_dev *indio_dev, int *val) { struct adis16136 *adis16136 = iio_priv(indio_dev); - struct mutex *slock = &adis16136->adis.state_lock; unsigned int freq; uint16_t val16; int ret; - mutex_lock(slock); + adis_dev_lock(&adis16136->adis); ret = __adis_read_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, &val16); @@ -297,7 +289,7 @@ static int adis16136_get_filter(struct iio_dev *indio_dev, int *val) *val = freq / adis16136_3db_divisors[val16 & 0x07]; err_unlock: - mutex_unlock(slock); + adis_dev_unlock(&adis16136->adis); return ret ? ret : IIO_VAL_INT; } diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c index e7c9a3e31c45..66b6b7bd5e1b 100644 --- a/drivers/iio/gyro/adis16260.c +++ b/drivers/iio/gyro/adis16260.c @@ -5,17 +5,12 @@ * Copyright 2010 Analog Devices Inc. */ -#include <linux/interrupt.h> -#include <linux/mutex.h> #include <linux/device.h> #include <linux/kernel.h> #include <linux/spi/spi.h> -#include <linux/sysfs.h> #include <linux/module.h> #include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> -#include <linux/iio/buffer.h> #include <linux/iio/imu/adis.h> #define ADIS16260_STARTUP_DELAY 220 /* ms */ @@ -293,7 +288,7 @@ static int adis16260_write_raw(struct iio_dev *indio_dev, addr = adis16260_addresses[chan->scan_index][1]; return adis_write_reg_16(adis, addr, val); case IIO_CHAN_INFO_SAMP_FREQ: - mutex_lock(&adis->state_lock); + adis_dev_lock(adis); if (spi_get_device_id(adis->spi)->driver_data) t = 256 / val; else @@ -310,7 +305,7 @@ static int adis16260_write_raw(struct iio_dev *indio_dev, adis->spi->max_speed_hz = ADIS16260_SPI_FAST; ret = __adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t); - mutex_unlock(&adis->state_lock); + adis_dev_unlock(adis); return ret; } return -EINVAL; diff --git a/drivers/iio/gyro/adxrs290.c b/drivers/iio/gyro/adxrs290.c index cec5e1f17c22..3e0734ddafe3 100644 --- a/drivers/iio/gyro/adxrs290.c +++ b/drivers/iio/gyro/adxrs290.c @@ -589,7 +589,7 @@ static int adxrs290_probe_trigger(struct iio_dev *indio_dev) st->dready_trig = devm_iio_trigger_alloc(&st->spi->dev, "%s-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!st->dready_trig) return -ENOMEM; diff --git a/drivers/iio/gyro/bmg160_core.c b/drivers/iio/gyro/bmg160_core.c index b11ebd9bb7a4..17b939a367ad 100644 --- a/drivers/iio/gyro/bmg160_core.c +++ b/drivers/iio/gyro/bmg160_core.c @@ -98,7 +98,11 @@ struct bmg160_data { struct iio_trigger *motion_trig; struct iio_mount_matrix orientation; struct mutex mutex; - s16 buffer[8]; + /* Ensure naturally aligned timestamp */ + struct { + s16 chans[3]; + s64 timestamp __aligned(8); + } scan; u32 dps_range; int ev_enable_state; int slope_thres; @@ -882,12 +886,12 @@ static irqreturn_t bmg160_trigger_handler(int irq, void *p) mutex_lock(&data->mutex); ret = regmap_bulk_read(data->regmap, BMG160_REG_XOUT_L, - data->buffer, AXIS_MAX * 2); + data->scan.chans, AXIS_MAX * 2); mutex_unlock(&data->mutex); if (ret < 0) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, pf->timestamp); err: iio_trigger_notify_done(indio_dev->trig); @@ -1102,8 +1106,7 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq, if (ret) return ret; - ret = iio_read_mount_matrix(dev, "mount-matrix", - &data->orientation); + ret = iio_read_mount_matrix(dev, &data->orientation); if (ret) return ret; @@ -1137,14 +1140,14 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq, data->dready_trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!data->dready_trig) return -ENOMEM; data->motion_trig = devm_iio_trigger_alloc(dev, "%s-any-motion-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!data->motion_trig) return -ENOMEM; diff --git a/drivers/iio/gyro/fxas21002c_core.c b/drivers/iio/gyro/fxas21002c_core.c index 645461c70454..410e5e9f2672 100644 --- a/drivers/iio/gyro/fxas21002c_core.c +++ b/drivers/iio/gyro/fxas21002c_core.c @@ -366,14 +366,7 @@ out_unlock: static int fxas21002c_pm_get(struct fxas21002c_data *data) { - struct device *dev = regmap_get_device(data->regmap); - int ret; - - ret = pm_runtime_get_sync(dev); - if (ret < 0) - pm_runtime_put_noidle(dev); - - return ret; + return pm_runtime_resume_and_get(regmap_get_device(data->regmap)); } static int fxas21002c_pm_put(struct fxas21002c_data *data) @@ -854,7 +847,7 @@ static int fxas21002c_trigger_probe(struct fxas21002c_data *data) data->dready_trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!data->dready_trig) return -ENOMEM; @@ -1004,7 +997,6 @@ int fxas21002c_core_probe(struct device *dev, struct regmap *regmap, int irq, pm_disable: pm_runtime_disable(dev); pm_runtime_set_suspended(dev); - pm_runtime_put_noidle(dev); return ret; } @@ -1018,7 +1010,6 @@ void fxas21002c_core_remove(struct device *dev) pm_runtime_disable(dev); pm_runtime_set_suspended(dev); - pm_runtime_put_noidle(dev); } EXPORT_SYMBOL_GPL(fxas21002c_core_remove); diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c index dad26ee4fd1f..bc63c2a34c5e 100644 --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c @@ -6,13 +6,10 @@ #include <linux/device.h> #include <linux/platform_device.h> #include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/irq.h> +#include <linux/mod_devicetable.h> #include <linux/slab.h> -#include <linux/delay.h> #include <linux/hid-sensor-hub.h> #include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> #include <linux/iio/buffer.h> #include "../common/hid-sensors/hid-sensor-trigger.h" @@ -400,3 +397,4 @@ module_platform_driver(hid_gyro_3d_platform_driver); MODULE_DESCRIPTION("HID Sensor Gyroscope 3D"); MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(IIO_HID); diff --git a/drivers/iio/gyro/itg3200_buffer.c b/drivers/iio/gyro/itg3200_buffer.c index af0aaa146f0c..04dd6a7969ea 100644 --- a/drivers/iio/gyro/itg3200_buffer.c +++ b/drivers/iio/gyro/itg3200_buffer.c @@ -114,7 +114,7 @@ int itg3200_probe_trigger(struct iio_dev *indio_dev) struct itg3200 *st = iio_priv(indio_dev); st->trig = iio_trigger_alloc(&st->i2c->dev, "%s-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!st->trig) return -ENOMEM; diff --git a/drivers/iio/gyro/itg3200_core.c b/drivers/iio/gyro/itg3200_core.c index e9804664db73..a7f1bbb5f289 100644 --- a/drivers/iio/gyro/itg3200_core.c +++ b/drivers/iio/gyro/itg3200_core.c @@ -308,8 +308,7 @@ static int itg3200_probe(struct i2c_client *client, st = iio_priv(indio_dev); - ret = iio_read_mount_matrix(&client->dev, "mount-matrix", - &st->orientation); + ret = iio_read_mount_matrix(&client->dev, &st->orientation); if (ret) return ret; diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c index f17a93519535..3225de1f023b 100644 --- a/drivers/iio/gyro/mpu3050-core.c +++ b/drivers/iio/gyro/mpu3050-core.c @@ -1058,7 +1058,7 @@ static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq) mpu3050->trig = devm_iio_trigger_alloc(&indio_dev->dev, "%s-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!mpu3050->trig) return -ENOMEM; @@ -1164,7 +1164,7 @@ int mpu3050_common_probe(struct device *dev, mpu3050->divisor = 99; /* Read the mounting matrix, if present */ - ret = iio_read_mount_matrix(dev, "mount-matrix", &mpu3050->orientation); + ret = iio_read_mount_matrix(dev, &mpu3050->orientation); if (ret) return ret; diff --git a/drivers/iio/gyro/st_gyro.h b/drivers/iio/gyro/st_gyro.h index fd9171cc3aba..6537f5cb8320 100644 --- a/drivers/iio/gyro/st_gyro.h +++ b/drivers/iio/gyro/st_gyro.h @@ -24,18 +24,6 @@ #define LSM330_GYRO_DEV_NAME "lsm330_gyro" #define LSM9DS0_GYRO_DEV_NAME "lsm9ds0_gyro" -/** - * struct st_sensors_platform_data - gyro platform data - * @drdy_int_pin: DRDY on gyros is available only on INT2 pin. - */ -static __maybe_unused const struct st_sensors_platform_data gyro_pdata = { - .drdy_int_pin = 2, -}; - -const struct st_sensor_settings *st_gyro_get_settings(const char *name); -int st_gyro_common_probe(struct iio_dev *indio_dev); -void st_gyro_common_remove(struct iio_dev *indio_dev); - #ifdef CONFIG_IIO_BUFFER int st_gyro_allocate_ring(struct iio_dev *indio_dev); void st_gyro_deallocate_ring(struct iio_dev *indio_dev); diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index c8aa051995d3..b86ee4d940d9 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c @@ -37,19 +37,36 @@ #define ST_GYRO_FS_AVL_500DPS 500 #define ST_GYRO_FS_AVL_2000DPS 2000 +static const struct iio_mount_matrix * +st_gyro_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct st_sensor_data *gdata = iio_priv(indio_dev); + + return &gdata->mount_matrix; +} + +static const struct iio_chan_spec_ext_info st_gyro_mount_matrix_ext_info[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_gyro_get_mount_matrix), + { } +}; + static const struct iio_chan_spec st_gyro_16bit_channels[] = { - ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL, + ST_SENSORS_LSM_CHANNELS_EXT(IIO_ANGL_VEL, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16, - ST_GYRO_DEFAULT_OUT_X_L_ADDR), - ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL, + ST_GYRO_DEFAULT_OUT_X_L_ADDR, + st_gyro_mount_matrix_ext_info), + ST_SENSORS_LSM_CHANNELS_EXT(IIO_ANGL_VEL, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16, - ST_GYRO_DEFAULT_OUT_Y_L_ADDR), - ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL, + ST_GYRO_DEFAULT_OUT_Y_L_ADDR, + st_gyro_mount_matrix_ext_info), + ST_SENSORS_LSM_CHANNELS_EXT(IIO_ANGL_VEL, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16, - ST_GYRO_DEFAULT_OUT_Z_L_ADDR), + ST_GYRO_DEFAULT_OUT_Z_L_ADDR, + st_gyro_mount_matrix_ext_info), IIO_CHAN_SOFT_TIMESTAMP(3) }; @@ -357,6 +374,11 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { }, }; +/* DRDY on gyros is available only on INT2 pin */ +static const struct st_sensors_platform_data gyro_pdata = { + .drdy_int_pin = 2, +}; + static int st_gyro_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask) @@ -466,18 +488,18 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &gyro_info; - err = st_sensors_power_enable(indio_dev); - if (err) - return err; - err = st_sensors_verify_id(indio_dev); if (err < 0) - goto st_gyro_power_off; + return err; gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS; indio_dev->channels = gdata->sensor_settings->ch; indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; + err = iio_read_mount_matrix(gdata->dev, &gdata->mount_matrix); + if (err) + return err; + gdata->current_fullscale = &gdata->sensor_settings->fs.fs_avl[0]; gdata->odr = gdata->sensor_settings->odr.odr_avl[0].hz; @@ -485,11 +507,11 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) err = st_sensors_init_sensor(indio_dev, pdata); if (err < 0) - goto st_gyro_power_off; + return err; err = st_gyro_allocate_ring(indio_dev); if (err < 0) - goto st_gyro_power_off; + return err; if (gdata->irq > 0) { err = st_sensors_allocate_trigger(indio_dev, @@ -512,9 +534,6 @@ st_gyro_device_register_error: st_sensors_deallocate_trigger(indio_dev); st_gyro_probe_trigger_error: st_gyro_deallocate_ring(indio_dev); -st_gyro_power_off: - st_sensors_power_disable(indio_dev); - return err; } EXPORT_SYMBOL(st_gyro_common_probe); @@ -523,8 +542,6 @@ void st_gyro_common_remove(struct iio_dev *indio_dev) { struct st_sensor_data *gdata = iio_priv(indio_dev); - st_sensors_power_disable(indio_dev); - iio_device_unregister(indio_dev); if (gdata->irq > 0) st_sensors_deallocate_trigger(indio_dev); diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c index 8190966e6ff0..a25cc0379e16 100644 --- a/drivers/iio/gyro/st_gyro_i2c.c +++ b/drivers/iio/gyro/st_gyro_i2c.c @@ -86,16 +86,29 @@ static int st_gyro_i2c_probe(struct i2c_client *client, if (err < 0) return err; + err = st_sensors_power_enable(indio_dev); + if (err) + return err; + err = st_gyro_common_probe(indio_dev); if (err < 0) - return err; + goto st_gyro_power_off; return 0; + +st_gyro_power_off: + st_sensors_power_disable(indio_dev); + + return err; } static int st_gyro_i2c_remove(struct i2c_client *client) { - st_gyro_common_remove(i2c_get_clientdata(client)); + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + st_sensors_power_disable(indio_dev); + + st_gyro_common_remove(indio_dev); return 0; } diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c index efb862763ca3..18d6a2aeda45 100644 --- a/drivers/iio/gyro/st_gyro_spi.c +++ b/drivers/iio/gyro/st_gyro_spi.c @@ -90,16 +90,29 @@ static int st_gyro_spi_probe(struct spi_device *spi) if (err < 0) return err; + err = st_sensors_power_enable(indio_dev); + if (err) + return err; + err = st_gyro_common_probe(indio_dev); if (err < 0) - return err; + goto st_gyro_power_off; return 0; + +st_gyro_power_off: + st_sensors_power_disable(indio_dev); + + return err; } static int st_gyro_spi_remove(struct spi_device *spi) { - st_gyro_common_remove(spi_get_drvdata(spi)); + struct iio_dev *indio_dev = spi_get_drvdata(spi); + + st_sensors_power_disable(indio_dev); + + st_gyro_common_remove(indio_dev); return 0; } diff --git a/drivers/iio/health/afe4403.c b/drivers/iio/health/afe4403.c index 1fa8d51d5080..d4921385aaf7 100644 --- a/drivers/iio/health/afe4403.c +++ b/drivers/iio/health/afe4403.c @@ -521,7 +521,7 @@ static int afe4403_probe(struct spi_device *spi) afe->trig = devm_iio_trigger_alloc(afe->dev, "%s-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!afe->trig) { dev_err(afe->dev, "Unable to allocate IIO trigger\n"); ret = -ENOMEM; diff --git a/drivers/iio/health/afe4404.c b/drivers/iio/health/afe4404.c index e1476bf79fe2..d8a27dfe074a 100644 --- a/drivers/iio/health/afe4404.c +++ b/drivers/iio/health/afe4404.c @@ -528,7 +528,7 @@ static int afe4404_probe(struct i2c_client *client, afe->trig = devm_iio_trigger_alloc(afe->dev, "%s-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!afe->trig) { dev_err(afe->dev, "Unable to allocate IIO trigger\n"); ret = -ENOMEM; diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c index 23bc9c784ef4..4a39f1019347 100644 --- a/drivers/iio/humidity/am2315.c +++ b/drivers/iio/humidity/am2315.c @@ -7,7 +7,6 @@ * 7-bit I2C address: 0x5C. */ -#include <linux/acpi.h> #include <linux/delay.h> #include <linux/i2c.h> #include <linux/kernel.h> @@ -33,7 +32,11 @@ struct am2315_data { struct i2c_client *client; struct mutex lock; - s16 buffer[8]; /* 2x16-bit channels + 2x16 padding + 4x16 timestamp */ + /* Ensure timestamp is naturally aligned */ + struct { + s16 chans[2]; + s64 timestamp __aligned(8); + } scan; }; struct am2315_sensor_data { @@ -167,20 +170,20 @@ static irqreturn_t am2315_trigger_handler(int irq, void *p) mutex_lock(&data->lock); if (*(indio_dev->active_scan_mask) == AM2315_ALL_CHANNEL_MASK) { - data->buffer[0] = sensor_data.hum_data; - data->buffer[1] = sensor_data.temp_data; + data->scan.chans[0] = sensor_data.hum_data; + data->scan.chans[1] = sensor_data.temp_data; } else { i = 0; for_each_set_bit(bit, indio_dev->active_scan_mask, indio_dev->masklength) { - data->buffer[i] = (bit ? sensor_data.temp_data : - sensor_data.hum_data); + data->scan.chans[i] = (bit ? sensor_data.temp_data : + sensor_data.hum_data); i++; } } mutex_unlock(&data->lock); - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, pf->timestamp); err: iio_trigger_notify_done(indio_dev->trig); @@ -256,17 +259,9 @@ static const struct i2c_device_id am2315_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, am2315_i2c_id); -static const struct acpi_device_id am2315_acpi_id[] = { - {"AOS2315", 0}, - {} -}; - -MODULE_DEVICE_TABLE(acpi, am2315_acpi_id); - static struct i2c_driver am2315_driver = { .driver = { .name = "am2315", - .acpi_match_table = ACPI_PTR(am2315_acpi_id), }, .probe = am2315_probe, .id_table = am2315_i2c_id, diff --git a/drivers/iio/humidity/hdc2010.c b/drivers/iio/humidity/hdc2010.c index 83f5b9f60780..1381df46187c 100644 --- a/drivers/iio/humidity/hdc2010.c +++ b/drivers/iio/humidity/hdc2010.c @@ -272,7 +272,6 @@ static int hdc2010_probe(struct i2c_client *client, data->client = client; mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; /* * As DEVICE ID register does not differentiate between * HDC2010 and HDC2080, we have the name hardcoded diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c index 74383abc0d44..fa0fe404a70a 100644 --- a/drivers/iio/humidity/hid-sensor-humidity.c +++ b/drivers/iio/humidity/hid-sensor-humidity.c @@ -8,6 +8,7 @@ #include <linux/iio/buffer.h> #include <linux/iio/iio.h> #include <linux/module.h> +#include <linux/mod_devicetable.h> #include <linux/platform_device.h> #include "hid-sensor-trigger.h" @@ -295,3 +296,4 @@ module_platform_driver(hid_humidity_platform_driver); MODULE_DESCRIPTION("HID Environmental humidity sensor"); MODULE_AUTHOR("Song Hongyan <hongyan.song@intel.com>"); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS(IIO_HID); diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index f02883b08480..001ca2c3ff95 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig @@ -94,6 +94,7 @@ config KMX61 source "drivers/iio/imu/inv_icm42600/Kconfig" source "drivers/iio/imu/inv_mpu6050/Kconfig" source "drivers/iio/imu/st_lsm6dsx/Kconfig" +source "drivers/iio/imu/st_lsm9ds0/Kconfig" endmenu diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile index 13e9ff442b11..c82748096c77 100644 --- a/drivers/iio/imu/Makefile +++ b/drivers/iio/imu/Makefile @@ -26,3 +26,4 @@ obj-y += inv_mpu6050/ obj-$(CONFIG_KMX61) += kmx61.o obj-y += st_lsm6dsx/ +obj-y += st_lsm9ds0/ diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 319b64b2fd88..a5b421f42287 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -12,14 +12,10 @@ #include <linux/device.h> #include <linux/kernel.h> #include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> #include <linux/module.h> #include <asm/unaligned.h> #include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> -#include <linux/iio/buffer.h> #include <linux/iio/imu/adis.h> #define ADIS_MSC_CTRL_DATA_RDY_EN BIT(2) diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c index 768aa493a1a6..b12917a7cb60 100644 --- a/drivers/iio/imu/adis16400.c +++ b/drivers/iio/imu/adis16400.c @@ -10,22 +10,15 @@ * Copyright (c) 2011 Analog Devices Inc. */ -#include <linux/interrupt.h> #include <linux/irq.h> -#include <linux/delay.h> -#include <linux/mutex.h> #include <linux/device.h> #include <linux/kernel.h> #include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/list.h> #include <linux/module.h> #include <linux/debugfs.h> #include <linux/bitops.h> #include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> #include <linux/iio/buffer.h> #include <linux/iio/trigger_consumer.h> #include <linux/iio/imu/adis.h> @@ -641,28 +634,13 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p) struct iio_dev *indio_dev = pf->indio_dev; struct adis16400_state *st = iio_priv(indio_dev); struct adis *adis = &st->adis; - u32 old_speed_hz = st->adis.spi->max_speed_hz; void *buffer; int ret; - if (!adis->buffer) - return -ENOMEM; - - if (!(st->variant->flags & ADIS16400_NO_BURST) && - st->adis.spi->max_speed_hz > ADIS16400_SPI_BURST) { - st->adis.spi->max_speed_hz = ADIS16400_SPI_BURST; - spi_setup(st->adis.spi); - } - ret = spi_sync(adis->spi, &adis->msg); if (ret) dev_err(&adis->spi->dev, "Failed to read data: %d\n", ret); - if (!(st->variant->flags & ADIS16400_NO_BURST)) { - st->adis.spi->max_speed_hz = old_speed_hz; - spi_setup(st->adis.spi); - } - if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) buffer = adis->buffer + sizeof(u16); else @@ -968,7 +946,8 @@ static const char * const adis16400_status_error_msgs[] = { BIT(ADIS16400_DIAG_STAT_POWER_LOW), \ .timeouts = (_timeouts), \ .burst_reg_cmd = ADIS16400_GLOB_CMD, \ - .burst_len = (_burst_len) \ + .burst_len = (_burst_len), \ + .burst_max_speed_hz = ADIS16400_SPI_BURST \ } static const struct adis_timeout adis16300_timeouts = { @@ -1178,8 +1157,6 @@ static int adis16400_probe(struct spi_device *spi) return -ENOMEM; st = iio_priv(indio_dev); - /* this is only used for removal purposes */ - spi_set_drvdata(spi, indio_dev); /* setup the industrialio driver allocated elements */ st->variant = &adis16400_chips[spi_get_device_id(spi)->driver_data]; diff --git a/drivers/iio/imu/adis16460.c b/drivers/iio/imu/adis16460.c index 73bf45e859b8..a6f9fba3e03f 100644 --- a/drivers/iio/imu/adis16460.c +++ b/drivers/iio/imu/adis16460.c @@ -5,7 +5,6 @@ * Copyright 2019 Analog Devices Inc. */ -#include <linux/delay.h> #include <linux/module.h> #include <linux/spi/spi.h> @@ -388,8 +387,6 @@ static int adis16460_probe(struct spi_device *spi) if (indio_dev == NULL) return -ENOMEM; - spi_set_drvdata(spi, indio_dev); - st = iio_priv(indio_dev); st->chip_info = &adis16460_chip_info; diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c index 1de62fc79e0f..eb48102f9424 100644 --- a/drivers/iio/imu/adis16475.c +++ b/drivers/iio/imu/adis16475.c @@ -14,7 +14,6 @@ #include <linux/iio/buffer.h> #include <linux/iio/iio.h> #include <linux/iio/imu/adis.h> -#include <linux/iio/sysfs.h> #include <linux/iio/trigger_consumer.h> #include <linux/irq.h> #include <linux/lcm.h> @@ -645,7 +644,8 @@ static int adis16475_enable_irq(struct adis *adis, bool enable) .timeouts = (_timeouts), \ .burst_reg_cmd = ADIS16475_REG_GLOB_CMD, \ .burst_len = ADIS16475_BURST_MAX_DATA, \ - .burst_max_len = ADIS16475_BURST32_MAX_DATA \ + .burst_max_len = ADIS16475_BURST32_MAX_DATA, \ + .burst_max_speed_hz = ADIS16475_BURST_MAX_SPEED \ } static const struct adis16475_sync adis16475_sync_mode[] = { @@ -1062,15 +1062,11 @@ static irqreturn_t adis16475_trigger_handler(int irq, void *p) bool valid; /* offset until the first element after gyro and accel */ const u8 offset = st->burst32 ? 13 : 7; - const u32 cached_spi_speed_hz = adis->spi->max_speed_hz; - - adis->spi->max_speed_hz = ADIS16475_BURST_MAX_SPEED; ret = spi_sync(adis->spi, &adis->msg); if (ret) - return ret; + goto check_burst32; - adis->spi->max_speed_hz = cached_spi_speed_hz; buffer = adis->buffer; crc = be16_to_cpu(buffer[offset + 2]); @@ -1332,7 +1328,6 @@ static int adis16475_probe(struct spi_device *spi) return -ENOMEM; st = iio_priv(indio_dev); - spi_set_drvdata(spi, indio_dev); st->info = device_get_match_data(&spi->dev); if (!st->info) diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c index f81b86690b76..a869a6e52a16 100644 --- a/drivers/iio/imu/adis16480.c +++ b/drivers/iio/imu/adis16480.c @@ -9,21 +9,19 @@ #include <linux/bitfield.h> #include <linux/of_irq.h> #include <linux/interrupt.h> -#include <linux/delay.h> #include <linux/math.h> -#include <linux/mutex.h> #include <linux/device.h> #include <linux/kernel.h> #include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> #include <linux/module.h> #include <linux/lcm.h> +#include <linux/swab.h> +#include <linux/crc32.h> #include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> #include <linux/iio/buffer.h> #include <linux/iio/imu/adis.h> +#include <linux/iio/trigger_consumer.h> #include <linux/debugfs.h> @@ -103,6 +101,12 @@ * Available only for ADIS1649x devices */ #define ADIS16495_REG_SYNC_SCALE ADIS16480_REG(0x03, 0x10) +#define ADIS16495_REG_BURST_CMD ADIS16480_REG(0x00, 0x7C) +#define ADIS16495_BURST_ID 0xA5A5 +/* total number of segments in burst */ +#define ADIS16495_BURST_MAX_DATA 20 +/* spi max speed in burst mode */ +#define ADIS16495_BURST_MAX_SPEED 6000000 #define ADIS16480_REG_SERIAL_NUM ADIS16480_REG(0x04, 0x20) @@ -163,6 +167,8 @@ struct adis16480 { struct clk *ext_clk; enum adis16480_clock_mode clk_mode; unsigned int clk_freq; + /* Alignment needed for the timestamp */ + __be16 data[ADIS16495_BURST_MAX_DATA] __aligned(8); }; static const char * const adis16480_int_pin_names[4] = { @@ -863,7 +869,7 @@ static const char * const adis16480_status_error_msgs[] = { static int adis16480_enable_irq(struct adis *adis, bool enable); -#define ADIS16480_DATA(_prod_id, _timeouts) \ +#define ADIS16480_DATA(_prod_id, _timeouts, _burst_len) \ { \ .diag_stat_reg = ADIS16480_REG_DIAG_STS, \ .glob_cmd_reg = ADIS16480_REG_GLOB_CMD, \ @@ -887,6 +893,9 @@ static int adis16480_enable_irq(struct adis *adis, bool enable); BIT(ADIS16480_DIAG_STAT_BARO_FAIL), \ .enable_irq = adis16480_enable_irq, \ .timeouts = (_timeouts), \ + .burst_reg_cmd = ADIS16495_REG_BURST_CMD, \ + .burst_len = (_burst_len), \ + .burst_max_speed_hz = ADIS16495_BURST_MAX_SPEED \ } static const struct adis_timeout adis16485_timeouts = { @@ -931,7 +940,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .int_clk = 2460000, .max_dec_rate = 2048, .filter_freqs = adis16480_def_filter_freqs, - .adis_data = ADIS16480_DATA(16375, &adis16485_timeouts), + .adis_data = ADIS16480_DATA(16375, &adis16485_timeouts, 0), }, [ADIS16480] = { .channels = adis16480_channels, @@ -944,7 +953,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .int_clk = 2460000, .max_dec_rate = 2048, .filter_freqs = adis16480_def_filter_freqs, - .adis_data = ADIS16480_DATA(16480, &adis16480_timeouts), + .adis_data = ADIS16480_DATA(16480, &adis16480_timeouts, 0), }, [ADIS16485] = { .channels = adis16485_channels, @@ -957,7 +966,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .int_clk = 2460000, .max_dec_rate = 2048, .filter_freqs = adis16480_def_filter_freqs, - .adis_data = ADIS16480_DATA(16485, &adis16485_timeouts), + .adis_data = ADIS16480_DATA(16485, &adis16485_timeouts, 0), }, [ADIS16488] = { .channels = adis16480_channels, @@ -970,7 +979,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .int_clk = 2460000, .max_dec_rate = 2048, .filter_freqs = adis16480_def_filter_freqs, - .adis_data = ADIS16480_DATA(16488, &adis16485_timeouts), + .adis_data = ADIS16480_DATA(16488, &adis16485_timeouts, 0), }, [ADIS16490] = { .channels = adis16485_channels, @@ -984,7 +993,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, - .adis_data = ADIS16480_DATA(16490, &adis16495_timeouts), + .adis_data = ADIS16480_DATA(16490, &adis16495_timeouts, 0), }, [ADIS16495_1] = { .channels = adis16485_channels, @@ -998,7 +1007,9 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, - .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts), + /* 20 elements of 16bits */ + .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts, + ADIS16495_BURST_MAX_DATA * 2), }, [ADIS16495_2] = { .channels = adis16485_channels, @@ -1012,7 +1023,9 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, - .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts), + /* 20 elements of 16bits */ + .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts, + ADIS16495_BURST_MAX_DATA * 2), }, [ADIS16495_3] = { .channels = adis16485_channels, @@ -1026,7 +1039,9 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, - .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts), + /* 20 elements of 16bits */ + .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts, + ADIS16495_BURST_MAX_DATA * 2), }, [ADIS16497_1] = { .channels = adis16485_channels, @@ -1040,7 +1055,9 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, - .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts), + /* 20 elements of 16bits */ + .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts, + ADIS16495_BURST_MAX_DATA * 2), }, [ADIS16497_2] = { .channels = adis16485_channels, @@ -1054,7 +1071,9 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, - .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts), + /* 20 elements of 16bits */ + .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts, + ADIS16495_BURST_MAX_DATA * 2), }, [ADIS16497_3] = { .channels = adis16485_channels, @@ -1068,10 +1087,118 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, - .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts), + /* 20 elements of 16bits */ + .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts, + ADIS16495_BURST_MAX_DATA * 2), }, }; +static bool adis16480_validate_crc(const u16 *buf, const u8 n_elem, const u32 crc) +{ + u32 crc_calc; + u16 crc_buf[15]; + int j; + + for (j = 0; j < n_elem; j++) + crc_buf[j] = swab16(buf[j]); + + crc_calc = crc32(~0, crc_buf, n_elem * 2); + crc_calc ^= ~0; + + return (crc == crc_calc); +} + +static irqreturn_t adis16480_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct adis16480 *st = iio_priv(indio_dev); + struct adis *adis = &st->adis; + int ret, bit, offset, i = 0; + __be16 *buffer; + u32 crc; + bool valid; + + adis_dev_lock(adis); + if (adis->current_page != 0) { + adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); + adis->tx[1] = 0; + ret = spi_write(adis->spi, adis->tx, 2); + if (ret) { + dev_err(&adis->spi->dev, "Failed to change device page: %d\n", ret); + adis_dev_unlock(adis); + goto irq_done; + } + + adis->current_page = 0; + } + + ret = spi_sync(adis->spi, &adis->msg); + if (ret) { + dev_err(&adis->spi->dev, "Failed to read data: %d\n", ret); + adis_dev_unlock(adis); + goto irq_done; + } + + adis_dev_unlock(adis); + + /* + * After making the burst request, the response can have one or two + * 16-bit responses containing the BURST_ID depending on the sclk. If + * clk > 3.6MHz, then we will have two BURST_ID in a row. If clk < 3MHZ, + * we have only one. To manage that variation, we use the transition from the + * BURST_ID to the SYS_E_FLAG register, which will not be equal to 0xA5A5. If + * we not find this variation in the first 4 segments, then the data should + * not be valid. + */ + buffer = adis->buffer; + for (offset = 0; offset < 4; offset++) { + u16 curr = be16_to_cpu(buffer[offset]); + u16 next = be16_to_cpu(buffer[offset + 1]); + + if (curr == ADIS16495_BURST_ID && next != ADIS16495_BURST_ID) { + offset++; + break; + } + } + + if (offset == 4) { + dev_err(&adis->spi->dev, "Invalid burst data\n"); + goto irq_done; + } + + crc = be16_to_cpu(buffer[offset + 16]) << 16 | be16_to_cpu(buffer[offset + 15]); + valid = adis16480_validate_crc((u16 *)&buffer[offset], 15, crc); + if (!valid) { + dev_err(&adis->spi->dev, "Invalid crc\n"); + goto irq_done; + } + + for_each_set_bit(bit, indio_dev->active_scan_mask, indio_dev->masklength) { + /* + * When burst mode is used, temperature is the first data + * channel in the sequence, but the temperature scan index + * is 10. + */ + switch (bit) { + case ADIS16480_SCAN_TEMP: + st->data[i++] = buffer[offset + 1]; + break; + case ADIS16480_SCAN_GYRO_X ... ADIS16480_SCAN_ACCEL_Z: + /* The lower register data is sequenced first */ + st->data[i++] = buffer[2 * bit + offset + 3]; + st->data[i++] = buffer[2 * bit + offset + 2]; + break; + } + } + + iio_push_to_buffers_with_timestamp(indio_dev, st->data, pf->timestamp); +irq_done: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + static const struct iio_info adis16480_info = { .read_raw = &adis16480_read_raw, .write_raw = &adis16480_write_raw, @@ -1279,8 +1406,6 @@ static int adis16480_probe(struct spi_device *spi) if (indio_dev == NULL) return -ENOMEM; - spi_set_drvdata(spi, indio_dev); - st = iio_priv(indio_dev); st->chip_info = &adis16480_chip_info[id->driver_data]; @@ -1341,7 +1466,8 @@ static int adis16480_probe(struct spi_device *spi) st->clk_freq = st->chip_info->int_clk; } - ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL); + ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, + adis16480_trigger_handler); if (ret) return ret; diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c index ac354321f63a..351c303c8a8c 100644 --- a/drivers/iio/imu/adis_buffer.c +++ b/drivers/iio/imu/adis_buffer.c @@ -51,9 +51,13 @@ static int adis_update_scan_mode_burst(struct iio_dev *indio_dev, adis->xfer[0].tx_buf = tx; adis->xfer[0].bits_per_word = 8; adis->xfer[0].len = 2; + if (adis->data->burst_max_speed_hz) + adis->xfer[0].speed_hz = adis->data->burst_max_speed_hz; adis->xfer[1].rx_buf = adis->buffer; adis->xfer[1].bits_per_word = 8; adis->xfer[1].len = burst_length; + if (adis->data->burst_max_speed_hz) + adis->xfer[1].speed_hz = adis->data->burst_max_speed_hz; spi_message_init(&adis->msg); spi_message_add_tail(&adis->xfer[0], &adis->msg); @@ -129,31 +133,34 @@ static irqreturn_t adis_trigger_handler(int irq, void *p) struct adis *adis = iio_device_get_drvdata(indio_dev); int ret; - if (!adis->buffer) - return -ENOMEM; - if (adis->data->has_paging) { mutex_lock(&adis->state_lock); if (adis->current_page != 0) { adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); adis->tx[1] = 0; - spi_write(adis->spi, adis->tx, 2); + ret = spi_write(adis->spi, adis->tx, 2); + if (ret) { + dev_err(&adis->spi->dev, "Failed to change device page: %d\n", ret); + mutex_unlock(&adis->state_lock); + goto irq_done; + } + + adis->current_page = 0; } } ret = spi_sync(adis->spi, &adis->msg); - if (ret) - dev_err(&adis->spi->dev, "Failed to read data: %d", ret); - - - if (adis->data->has_paging) { - adis->current_page = 0; + if (adis->data->has_paging) mutex_unlock(&adis->state_lock); + if (ret) { + dev_err(&adis->spi->dev, "Failed to read data: %d", ret); + goto irq_done; } iio_push_to_buffers_with_timestamp(indio_dev, adis->buffer, pf->timestamp); +irq_done: iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c index fa5540fabacc..48eedc29b28a 100644 --- a/drivers/iio/imu/adis_trigger.c +++ b/drivers/iio/imu/adis_trigger.c @@ -62,7 +62,8 @@ int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) int ret; adis->trig = devm_iio_trigger_alloc(&adis->spi->dev, "%s-dev%d", - indio_dev->name, indio_dev->id); + indio_dev->name, + iio_device_id(indio_dev)); if (!adis->trig) return -ENOMEM; diff --git a/drivers/iio/imu/bmi160/bmi160_core.c b/drivers/iio/imu/bmi160/bmi160_core.c index 290b5ef83f77..824b5124a5f5 100644 --- a/drivers/iio/imu/bmi160/bmi160_core.c +++ b/drivers/iio/imu/bmi160/bmi160_core.c @@ -785,7 +785,8 @@ int bmi160_probe_trigger(struct iio_dev *indio_dev, int irq, u32 irq_type) int ret; data->trig = devm_iio_trigger_alloc(&indio_dev->dev, "%s-dev%d", - indio_dev->name, indio_dev->id); + indio_dev->name, + iio_device_id(indio_dev)); if (data->trig == NULL) return -ENOMEM; @@ -851,8 +852,7 @@ int bmi160_core_probe(struct device *dev, struct regmap *regmap, return ret; } - ret = iio_read_mount_matrix(dev, "mount-matrix", - &data->orientation); + ret = iio_read_mount_matrix(dev, &data->orientation); if (ret) return ret; diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c index 8bd77185ccb7..86858da9cc38 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c @@ -592,7 +592,7 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, st->chip = chip; st->map = regmap; - ret = iio_read_mount_matrix(dev, "mount-matrix", &st->orientation); + ret = iio_read_mount_matrix(dev, &st->orientation); if (ret) { dev_err(dev, "failed to retrieve mounting matrix %d\n", ret); return ret; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 6244a07048df..8a7a920e6200 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -570,11 +570,9 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev, freq_hz = INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider); period_us = 1000000 / freq_hz; - result = pm_runtime_get_sync(pdev); - if (result < 0) { - pm_runtime_put_noidle(pdev); + result = pm_runtime_resume_and_get(pdev); + if (result) return result; - } switch (chan->type) { case IIO_ANGL_VEL: @@ -812,11 +810,9 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev, return result; mutex_lock(&st->lock); - result = pm_runtime_get_sync(pdev); - if (result < 0) { - pm_runtime_put_noidle(pdev); + result = pm_runtime_resume_and_get(pdev); + if (result) goto error_write_raw_unlock; - } switch (mask) { case IIO_CHAN_INFO_SCALE: @@ -930,11 +926,9 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr, result = 0; goto fifo_rate_fail_unlock; } - result = pm_runtime_get_sync(pdev); - if (result < 0) { - pm_runtime_put_noidle(pdev); + result = pm_runtime_resume_and_get(pdev); + if (result) goto fifo_rate_fail_unlock; - } result = regmap_write(st->map, st->reg->sample_rate_div, d); if (result) @@ -1314,8 +1308,7 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st) for (i = 0; i < INV_NUM_PARTS; ++i) { if (regval == hw_info[i].whoami) { dev_warn(regmap_get_device(st->map), - "whoami mismatch got %#02x (%s)" - "expected %#02hhx (%s)\n", + "whoami mismatch got 0x%02x (%s) expected 0x%02x (%s)\n", regval, hw_info[i].name, st->hw->whoami, st->hw->name); break; @@ -1323,7 +1316,7 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st) } if (i >= INV_NUM_PARTS) { dev_err(regmap_get_device(st->map), - "invalid whoami %#02x expected %#02hhx (%s)\n", + "invalid whoami 0x%02x expected 0x%02x (%s)\n", regval, st->hw->whoami, st->hw->name); return -ENODEV; } @@ -1422,7 +1415,6 @@ static void inv_mpu_pm_disable(void *data) { struct device *dev = data; - pm_runtime_put_sync_suspend(dev); pm_runtime_disable(dev); } @@ -1455,8 +1447,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, pdata = dev_get_platdata(dev); if (!pdata) { - result = iio_read_mount_matrix(dev, "mount-matrix", - &st->orientation); + result = iio_read_mount_matrix(dev, &st->orientation); if (result) { dev_err(dev, "Failed to retrieve mounting matrix %d\n", result); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c index de8ed1446d60..2d0e8cdd4848 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c @@ -173,11 +173,9 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable) if (enable) { scan = inv_scan_query(indio_dev); - result = pm_runtime_get_sync(pdev); - if (result < 0) { - pm_runtime_put_noidle(pdev); + result = pm_runtime_resume_and_get(pdev); + if (result) return result; - } /* * In case autosuspend didn't trigger, turn off first not * required sensors. @@ -238,7 +236,7 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type) st->trig = devm_iio_trigger_alloc(&indio_dev->dev, "%s-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!st->trig) return -ENOMEM; diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index fc5a60fcfec0..1dabfd615dab 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -750,7 +750,7 @@ static int kmx61_set_power_state(struct kmx61_data *data, bool on, u8 device) } if (on) { - ret = pm_runtime_get_sync(&data->client->dev); + ret = pm_runtime_resume_and_get(&data->client->dev); } else { pm_runtime_mark_last_busy(&data->client->dev); ret = pm_runtime_put_autosuspend(&data->client->dev); @@ -759,8 +759,6 @@ static int kmx61_set_power_state(struct kmx61_data *data, bool on, u8 device) dev_err(&data->client->dev, "Failed: kmx61_set_power_state for %d, ret %d\n", on, ret); - if (on) - pm_runtime_put_noidle(&data->client->dev); return ret; } @@ -1264,7 +1262,7 @@ static struct iio_trigger *kmx61_trigger_setup(struct kmx61_data *data, "%s-%s-dev%d", indio_dev->name, tag, - indio_dev->id); + iio_device_id(indio_dev)); if (!trig) return ERR_PTR(-ENOMEM); @@ -1426,7 +1424,6 @@ static int kmx61_remove(struct i2c_client *client) pm_runtime_disable(&client->dev); pm_runtime_set_suspended(&client->dev); - pm_runtime_put_noidle(&client->dev); if (client->irq > 0) { iio_triggered_buffer_cleanup(data->acc_indio_dev); diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 7cedaab096a7..db45f1fc0b81 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -15,19 +15,19 @@ * * Supported sensors: * - LSM6DS3: - * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 + * - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 416 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 * - FIFO size: 8KB * * - LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC/LSM6DS3TR-C: - * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 + * - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 416 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 * - FIFO size: 4KB * * - LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR/ISM330DHCX/LSM6DST/LSM6DSOP: - * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416, + * - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 416, * 833 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 @@ -2256,7 +2256,7 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, return err; } - err = iio_read_mount_matrix(hw->dev, "mount-matrix", &hw->orientation); + err = iio_read_mount_matrix(hw->dev, &hw->orientation); if (err) return err; diff --git a/drivers/iio/imu/st_lsm9ds0/Kconfig b/drivers/iio/imu/st_lsm9ds0/Kconfig new file mode 100644 index 000000000000..53b7017014f8 --- /dev/null +++ b/drivers/iio/imu/st_lsm9ds0/Kconfig @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config IIO_ST_LSM9DS0 + tristate "STMicroelectronics LSM9DS0 IMU driver" + depends on (I2C || SPI_MASTER) && SYSFS + depends on !SENSORS_LIS3_I2C + depends on !SENSORS_LIS3_SPI + select IIO_ST_LSM9DS0_I2C if I2C + select IIO_ST_LSM9DS0_SPI if SPI_MASTER + select IIO_ST_ACCEL_3AXIS + select IIO_ST_MAGN_3AXIS + + help + Say yes here to build support for STMicroelectronics LSM9DS0 IMU + sensor. Supported devices: accelerometer/magnetometer of lsm9ds0. + + To compile this driver as a module, choose M here: the module + will be called st_lsm9ds0. + +config IIO_ST_LSM9DS0_I2C + tristate + depends on IIO_ST_LSM9DS0 + select REGMAP_I2C + +config IIO_ST_LSM9DS0_SPI + tristate + depends on IIO_ST_LSM9DS0 + select REGMAP_SPI diff --git a/drivers/iio/imu/st_lsm9ds0/Makefile b/drivers/iio/imu/st_lsm9ds0/Makefile new file mode 100644 index 000000000000..488af523f648 --- /dev/null +++ b/drivers/iio/imu/st_lsm9ds0/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_IIO_ST_LSM9DS0) += st_lsm9ds0.o +st_lsm9ds0-y := st_lsm9ds0_core.o +obj-$(CONFIG_IIO_ST_LSM9DS0_I2C) += st_lsm9ds0_i2c.o +obj-$(CONFIG_IIO_ST_LSM9DS0_SPI) += st_lsm9ds0_spi.o diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0.h b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0.h new file mode 100644 index 000000000000..146393afd9a7 --- /dev/null +++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +// STMicroelectronics LSM9DS0 IMU driver + +#ifndef ST_LSM9DS0_H +#define ST_LSM9DS0_H + +struct iio_dev; +struct regulator; + +struct st_lsm9ds0 { + struct device *dev; + const char *name; + int irq; + struct iio_dev *accel; + struct iio_dev *magn; + struct regulator *vdd; + struct regulator *vdd_io; +}; + +int st_lsm9ds0_probe(struct st_lsm9ds0 *lsm9ds0, struct regmap *regmap); +int st_lsm9ds0_remove(struct st_lsm9ds0 *lsm9ds0); + +#endif /* ST_LSM9DS0_H */ diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c new file mode 100644 index 000000000000..8204f7303fd7 --- /dev/null +++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * STMicroelectronics LSM9DS0 IMU driver + * + * Copyright (C) 2021, Intel Corporation + * + * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> + */ + +#include <linux/device.h> +#include <linux/err.h> +#include <linux/module.h> +#include <linux/regulator/consumer.h> + +#include <linux/iio/common/st_sensors.h> +#include <linux/iio/iio.h> + +#include "st_lsm9ds0.h" + +static int st_lsm9ds0_power_enable(struct device *dev, struct st_lsm9ds0 *lsm9ds0) +{ + int ret; + + /* Regulators not mandatory, but if requested we should enable them. */ + lsm9ds0->vdd = devm_regulator_get(dev, "vdd"); + if (IS_ERR(lsm9ds0->vdd)) { + dev_err(dev, "unable to get Vdd supply\n"); + return PTR_ERR(lsm9ds0->vdd); + } + ret = regulator_enable(lsm9ds0->vdd); + if (ret) { + dev_warn(dev, "Failed to enable specified Vdd supply\n"); + return ret; + } + + lsm9ds0->vdd_io = devm_regulator_get(dev, "vddio"); + if (IS_ERR(lsm9ds0->vdd_io)) { + dev_err(dev, "unable to get Vdd_IO supply\n"); + regulator_disable(lsm9ds0->vdd); + return PTR_ERR(lsm9ds0->vdd_io); + } + ret = regulator_enable(lsm9ds0->vdd_io); + if (ret) { + dev_warn(dev, "Failed to enable specified Vdd_IO supply\n"); + regulator_disable(lsm9ds0->vdd); + return ret; + } + + return 0; +} + +static void st_lsm9ds0_power_disable(void *data) +{ + struct st_lsm9ds0 *lsm9ds0 = data; + + regulator_disable(lsm9ds0->vdd_io); + regulator_disable(lsm9ds0->vdd); +} + +static int devm_st_lsm9ds0_power_enable(struct st_lsm9ds0 *lsm9ds0) +{ + struct device *dev = lsm9ds0->dev; + int ret; + + ret = st_lsm9ds0_power_enable(dev, lsm9ds0); + if (ret) + return ret; + + return devm_add_action_or_reset(dev, st_lsm9ds0_power_disable, lsm9ds0); +} + +static int st_lsm9ds0_probe_accel(struct st_lsm9ds0 *lsm9ds0, struct regmap *regmap) +{ + const struct st_sensor_settings *settings; + struct device *dev = lsm9ds0->dev; + struct st_sensor_data *data; + + settings = st_accel_get_settings(lsm9ds0->name); + if (!settings) { + dev_err(dev, "device name %s not recognized.\n", lsm9ds0->name); + return -ENODEV; + } + + lsm9ds0->accel = devm_iio_device_alloc(dev, sizeof(*data)); + if (!lsm9ds0->accel) + return -ENOMEM; + + lsm9ds0->accel->name = lsm9ds0->name; + + data = iio_priv(lsm9ds0->accel); + data->sensor_settings = (struct st_sensor_settings *)settings; + data->dev = dev; + data->irq = lsm9ds0->irq; + data->regmap = regmap; + data->vdd = lsm9ds0->vdd; + data->vdd_io = lsm9ds0->vdd_io; + + return st_accel_common_probe(lsm9ds0->accel); +} + +static int st_lsm9ds0_probe_magn(struct st_lsm9ds0 *lsm9ds0, struct regmap *regmap) +{ + const struct st_sensor_settings *settings; + struct device *dev = lsm9ds0->dev; + struct st_sensor_data *data; + + settings = st_magn_get_settings(lsm9ds0->name); + if (!settings) { + dev_err(dev, "device name %s not recognized.\n", lsm9ds0->name); + return -ENODEV; + } + + lsm9ds0->magn = devm_iio_device_alloc(dev, sizeof(*data)); + if (!lsm9ds0->magn) + return -ENOMEM; + + lsm9ds0->magn->name = lsm9ds0->name; + + data = iio_priv(lsm9ds0->magn); + data->sensor_settings = (struct st_sensor_settings *)settings; + data->dev = dev; + data->irq = lsm9ds0->irq; + data->regmap = regmap; + data->vdd = lsm9ds0->vdd; + data->vdd_io = lsm9ds0->vdd_io; + + return st_magn_common_probe(lsm9ds0->magn); +} + +int st_lsm9ds0_probe(struct st_lsm9ds0 *lsm9ds0, struct regmap *regmap) +{ + int ret; + + ret = devm_st_lsm9ds0_power_enable(lsm9ds0); + if (ret) + return ret; + + /* Setup accelerometer device */ + ret = st_lsm9ds0_probe_accel(lsm9ds0, regmap); + if (ret) + return ret; + + /* Setup magnetometer device */ + ret = st_lsm9ds0_probe_magn(lsm9ds0, regmap); + if (ret) + st_accel_common_remove(lsm9ds0->accel); + + return ret; +} +EXPORT_SYMBOL_GPL(st_lsm9ds0_probe); + +int st_lsm9ds0_remove(struct st_lsm9ds0 *lsm9ds0) +{ + st_magn_common_remove(lsm9ds0->magn); + st_accel_common_remove(lsm9ds0->accel); + + return 0; +} +EXPORT_SYMBOL_GPL(st_lsm9ds0_remove); + +MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); +MODULE_DESCRIPTION("STMicroelectronics LSM9DS0 IMU core driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c new file mode 100644 index 000000000000..50a36ab53bc3 --- /dev/null +++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * STMicroelectronics LSM9DS0 IMU driver + * + * Copyright (C) 2021, Intel Corporation + * + * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> + */ + +#include <linux/i2c.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> + +#include <linux/iio/common/st_sensors_i2c.h> + +#include "st_lsm9ds0.h" + +static const struct of_device_id st_lsm9ds0_of_match[] = { + { + .compatible = "st,lsm9ds0-imu", + .data = LSM9DS0_IMU_DEV_NAME, + }, + {} +}; +MODULE_DEVICE_TABLE(of, st_lsm9ds0_of_match); + +static const struct i2c_device_id st_lsm9ds0_id_table[] = { + { LSM9DS0_IMU_DEV_NAME }, + {} +}; +MODULE_DEVICE_TABLE(i2c, st_lsm9ds0_id_table); + +static const struct regmap_config st_lsm9ds0_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .read_flag_mask = 0x80, +}; + +static int st_lsm9ds0_i2c_probe(struct i2c_client *client) +{ + const struct regmap_config *config = &st_lsm9ds0_regmap_config; + struct device *dev = &client->dev; + struct st_lsm9ds0 *lsm9ds0; + struct regmap *regmap; + + st_sensors_dev_name_probe(dev, client->name, sizeof(client->name)); + + lsm9ds0 = devm_kzalloc(dev, sizeof(*lsm9ds0), GFP_KERNEL); + if (!lsm9ds0) + return -ENOMEM; + + lsm9ds0->dev = dev; + lsm9ds0->name = client->name; + lsm9ds0->irq = client->irq; + + regmap = devm_regmap_init_i2c(client, config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + i2c_set_clientdata(client, lsm9ds0); + + return st_lsm9ds0_probe(lsm9ds0, regmap); +} + +static int st_lsm9ds0_i2c_remove(struct i2c_client *client) +{ + return st_lsm9ds0_remove(i2c_get_clientdata(client)); +} + +static struct i2c_driver st_lsm9ds0_driver = { + .driver = { + .name = "st-lsm9ds0-i2c", + .of_match_table = st_lsm9ds0_of_match, + }, + .probe_new = st_lsm9ds0_i2c_probe, + .remove = st_lsm9ds0_i2c_remove, + .id_table = st_lsm9ds0_id_table, +}; +module_i2c_driver(st_lsm9ds0_driver); + +MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); +MODULE_DESCRIPTION("STMicroelectronics LSM9DS0 IMU I2C driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c new file mode 100644 index 000000000000..272c88990dd0 --- /dev/null +++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * STMicroelectronics LSM9DS0 IMU driver + * + * Copyright (C) 2021, Intel Corporation + * + * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/spi/spi.h> + +#include <linux/iio/common/st_sensors_spi.h> + +#include "st_lsm9ds0.h" + +static const struct of_device_id st_lsm9ds0_of_match[] = { + { + .compatible = "st,lsm9ds0-imu", + .data = LSM9DS0_IMU_DEV_NAME, + }, + {} +}; +MODULE_DEVICE_TABLE(of, st_lsm9ds0_of_match); + +static const struct spi_device_id st_lsm9ds0_id_table[] = { + { LSM9DS0_IMU_DEV_NAME }, + {} +}; +MODULE_DEVICE_TABLE(spi, st_lsm9ds0_id_table); + +static const struct regmap_config st_lsm9ds0_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .read_flag_mask = 0xc0, +}; + +static int st_lsm9ds0_spi_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct st_lsm9ds0 *lsm9ds0; + struct regmap *regmap; + + st_sensors_dev_name_probe(dev, spi->modalias, sizeof(spi->modalias)); + + lsm9ds0 = devm_kzalloc(dev, sizeof(*lsm9ds0), GFP_KERNEL); + if (!lsm9ds0) + return -ENOMEM; + + lsm9ds0->dev = dev; + lsm9ds0->name = spi->modalias; + lsm9ds0->irq = spi->irq; + + regmap = devm_regmap_init_spi(spi, &st_lsm9ds0_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + spi_set_drvdata(spi, lsm9ds0); + + return st_lsm9ds0_probe(lsm9ds0, regmap); +} + +static int st_lsm9ds0_spi_remove(struct spi_device *spi) +{ + return st_lsm9ds0_remove(spi_get_drvdata(spi)); +} + +static struct spi_driver st_lsm9ds0_driver = { + .driver = { + .name = "st-lsm9ds0-spi", + .of_match_table = st_lsm9ds0_of_match, + }, + .probe = st_lsm9ds0_spi_probe, + .remove = st_lsm9ds0_spi_remove, + .id_table = st_lsm9ds0_id_table, +}; +module_spi_driver(st_lsm9ds0_driver); + +MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); +MODULE_DESCRIPTION("STMicroelectronics LSM9DS0 IMU SPI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 9a8e16c7e9af..fdd623407b96 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -601,8 +601,10 @@ static unsigned int iio_storage_bytes_for_si(struct iio_dev *indio_dev, static unsigned int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); + return iio_storage_bytes_for_si(indio_dev, - indio_dev->scan_index_timestamp); + iio_dev_opaque->scan_index_timestamp); } static int iio_compute_scan_bytes(struct iio_dev *indio_dev, @@ -924,7 +926,6 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev, if (ret) goto error_clear_mux_table; out_loc += length; - in_loc += length; } buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL); if (buffer->demux_bounce == NULL) { @@ -1148,12 +1149,13 @@ int iio_update_buffers(struct iio_dev *indio_dev, struct iio_buffer *insert_buffer, struct iio_buffer *remove_buffer) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); int ret; if (insert_buffer == remove_buffer) return 0; - mutex_lock(&indio_dev->info_exist_lock); + mutex_lock(&iio_dev_opaque->info_exist_lock); mutex_lock(&indio_dev->mlock); if (insert_buffer && iio_buffer_is_active(insert_buffer)) @@ -1176,7 +1178,7 @@ int iio_update_buffers(struct iio_dev *indio_dev, out_unlock: mutex_unlock(&indio_dev->mlock); - mutex_unlock(&indio_dev->info_exist_lock); + mutex_unlock(&iio_dev_opaque->info_exist_lock); return ret; } @@ -1469,6 +1471,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer, struct iio_dev *indio_dev, int index) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); struct iio_dev_attr *p; struct attribute **attr; int ret, i, attrn, scan_el_attrcount, buffer_attrcount; @@ -1495,7 +1498,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer, goto error_cleanup_dynamic; scan_el_attrcount += ret; if (channels[i].type == IIO_TIMESTAMP) - indio_dev->scan_index_timestamp = + iio_dev_opaque->scan_index_timestamp = channels[i].scan_index; } if (indio_dev->masklength && buffer->scan_mask == NULL) { diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 59efb36db2c7..6d2175eb7af2 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -169,6 +169,20 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_THERMOCOUPLE_TYPE] = "thermocouple_type", [IIO_CHAN_INFO_CALIBAMBIENT] = "calibambient", }; +/** + * iio_device_id() - query the unique ID for the device + * @indio_dev: Device structure whose ID is being queried + * + * The IIO device ID is a unique index used for example for the naming + * of the character device /dev/iio\:device[ID] + */ +int iio_device_id(struct iio_dev *indio_dev) +{ + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); + + return iio_dev_opaque->id; +} +EXPORT_SYMBOL_GPL(iio_device_id); /** * iio_sysfs_match_string_with_gaps - matches given string in an array with gaps @@ -257,7 +271,7 @@ int iio_device_set_clock(struct iio_dev *indio_dev, clockid_t clock_id) mutex_unlock(&indio_dev->mlock); return -EBUSY; } - indio_dev->clock_id = clock_id; + iio_dev_opaque->clock_id = clock_id; mutex_unlock(&indio_dev->mlock); return 0; @@ -265,6 +279,18 @@ int iio_device_set_clock(struct iio_dev *indio_dev, clockid_t clock_id) EXPORT_SYMBOL(iio_device_set_clock); /** + * iio_device_get_clock() - Retrieve current timestamping clock for the device + * @indio_dev: IIO device structure containing the device + */ +clockid_t iio_device_get_clock(const struct iio_dev *indio_dev) +{ + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); + + return iio_dev_opaque->clock_id; +} +EXPORT_SYMBOL(iio_device_get_clock); + +/** * iio_get_time_ns() - utility function to get a time stamp for events etc * @indio_dev: device */ @@ -591,7 +617,6 @@ EXPORT_SYMBOL_GPL(iio_show_mount_matrix); * iio_read_mount_matrix() - retrieve iio device mounting matrix from * device "mount-matrix" property * @dev: device the mounting matrix property is assigned to - * @propname: device specific mounting matrix property name * @matrix: where to store retrieved matrix * * If device is assigned no mounting matrix property, a default 3x3 identity @@ -599,14 +624,12 @@ EXPORT_SYMBOL_GPL(iio_show_mount_matrix); * * Return: 0 if success, or a negative error code on failure. */ -int iio_read_mount_matrix(struct device *dev, const char *propname, - struct iio_mount_matrix *matrix) +int iio_read_mount_matrix(struct device *dev, struct iio_mount_matrix *matrix) { size_t len = ARRAY_SIZE(iio_mount_idmatrix.rotation); int err; - err = device_property_read_string_array(dev, propname, - matrix->rotation, len); + err = device_property_read_string_array(dev, "mount-matrix", matrix->rotation, len); if (err == len) return 0; @@ -1588,7 +1611,7 @@ static void iio_dev_release(struct device *device) iio_device_detach_buffers(indio_dev); - ida_simple_remove(&iio_ida, indio_dev->id); + ida_simple_remove(&iio_ida, iio_dev_opaque->id); kfree(iio_dev_opaque); } @@ -1628,17 +1651,17 @@ struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv) device_initialize(&indio_dev->dev); iio_device_set_drvdata(indio_dev, (void *)indio_dev); mutex_init(&indio_dev->mlock); - mutex_init(&indio_dev->info_exist_lock); + mutex_init(&iio_dev_opaque->info_exist_lock); INIT_LIST_HEAD(&iio_dev_opaque->channel_attr_list); - indio_dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); - if (indio_dev->id < 0) { + iio_dev_opaque->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); + if (iio_dev_opaque->id < 0) { /* cannot use a dev_err as the name isn't available */ pr_err("failed to get device id\n"); kfree(iio_dev_opaque); return NULL; } - dev_set_name(&indio_dev->dev, "iio:device%d", indio_dev->id); + dev_set_name(&indio_dev->dev, "iio:device%d", iio_dev_opaque->id); INIT_LIST_HEAD(&iio_dev_opaque->buffer_list); INIT_LIST_HEAD(&iio_dev_opaque->ioctl_handlers); @@ -1657,9 +1680,9 @@ void iio_device_free(struct iio_dev *dev) } EXPORT_SYMBOL(iio_device_free); -static void devm_iio_device_release(struct device *dev, void *res) +static void devm_iio_device_release(void *iio_dev) { - iio_device_free(*(struct iio_dev **)res); + iio_device_free(iio_dev); } /** @@ -1675,20 +1698,17 @@ static void devm_iio_device_release(struct device *dev, void *res) */ struct iio_dev *devm_iio_device_alloc(struct device *parent, int sizeof_priv) { - struct iio_dev **ptr, *iio_dev; + struct iio_dev *iio_dev; + int ret; - ptr = devres_alloc(devm_iio_device_release, sizeof(*ptr), - GFP_KERNEL); - if (!ptr) + iio_dev = iio_device_alloc(parent, sizeof_priv); + if (!iio_dev) return NULL; - iio_dev = iio_device_alloc(parent, sizeof_priv); - if (iio_dev) { - *ptr = iio_dev; - devres_add(parent, ptr); - } else { - devres_free(ptr); - } + ret = devm_add_action_or_reset(parent, devm_iio_device_release, + iio_dev); + if (ret) + return NULL; return iio_dev; } @@ -1704,11 +1724,12 @@ EXPORT_SYMBOL_GPL(devm_iio_device_alloc); **/ static int iio_chrdev_open(struct inode *inode, struct file *filp) { - struct iio_dev *indio_dev = container_of(inode->i_cdev, - struct iio_dev, chrdev); + struct iio_dev_opaque *iio_dev_opaque = + container_of(inode->i_cdev, struct iio_dev_opaque, chrdev); + struct iio_dev *indio_dev = &iio_dev_opaque->indio_dev; struct iio_dev_buffer_pair *ib; - if (test_and_set_bit(IIO_BUSY_BIT_POS, &indio_dev->flags)) + if (test_and_set_bit(IIO_BUSY_BIT_POS, &iio_dev_opaque->flags)) return -EBUSY; iio_device_get(indio_dev); @@ -1716,7 +1737,7 @@ static int iio_chrdev_open(struct inode *inode, struct file *filp) ib = kmalloc(sizeof(*ib), GFP_KERNEL); if (!ib) { iio_device_put(indio_dev); - clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags); + clear_bit(IIO_BUSY_BIT_POS, &iio_dev_opaque->flags); return -ENOMEM; } @@ -1738,10 +1759,11 @@ static int iio_chrdev_open(struct inode *inode, struct file *filp) static int iio_chrdev_release(struct inode *inode, struct file *filp) { struct iio_dev_buffer_pair *ib = filp->private_data; - struct iio_dev *indio_dev = container_of(inode->i_cdev, - struct iio_dev, chrdev); + struct iio_dev_opaque *iio_dev_opaque = + container_of(inode->i_cdev, struct iio_dev_opaque, chrdev); + struct iio_dev *indio_dev = &iio_dev_opaque->indio_dev; kfree(ib); - clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags); + clear_bit(IIO_BUSY_BIT_POS, &iio_dev_opaque->flags); iio_device_put(indio_dev); return 0; @@ -1768,7 +1790,7 @@ static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) struct iio_ioctl_handler *h; int ret = -ENODEV; - mutex_lock(&indio_dev->info_exist_lock); + mutex_lock(&iio_dev_opaque->info_exist_lock); /** * The NULL check here is required to prevent crashing when a device @@ -1788,7 +1810,7 @@ static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ret = -ENODEV; out_unlock: - mutex_unlock(&indio_dev->info_exist_lock); + mutex_unlock(&iio_dev_opaque->info_exist_lock); return ret; } @@ -1847,7 +1869,7 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod) if (!indio_dev->info) return -EINVAL; - indio_dev->driver_module = this_mod; + iio_dev_opaque->driver_module = this_mod; /* If the calling driver did not initialize of_node, do it here */ if (!indio_dev->dev.of_node && indio_dev->dev.parent) indio_dev->dev.of_node = indio_dev->dev.parent->of_node; @@ -1889,19 +1911,19 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod) indio_dev->setup_ops = &noop_ring_setup_ops; if (iio_dev_opaque->attached_buffers_cnt) - cdev_init(&indio_dev->chrdev, &iio_buffer_fileops); + cdev_init(&iio_dev_opaque->chrdev, &iio_buffer_fileops); else if (iio_dev_opaque->event_interface) - cdev_init(&indio_dev->chrdev, &iio_event_fileops); + cdev_init(&iio_dev_opaque->chrdev, &iio_event_fileops); if (iio_dev_opaque->attached_buffers_cnt || iio_dev_opaque->event_interface) { - indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id); - indio_dev->chrdev.owner = this_mod; + indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), iio_dev_opaque->id); + iio_dev_opaque->chrdev.owner = this_mod; } /* assign device groups now; they should be all registered now */ indio_dev->dev.groups = iio_dev_opaque->groups; - ret = cdev_device_add(&indio_dev->chrdev, &indio_dev->dev); + ret = cdev_device_add(&iio_dev_opaque->chrdev, &indio_dev->dev); if (ret < 0) goto error_unreg_eventset; @@ -1925,9 +1947,11 @@ EXPORT_SYMBOL(__iio_device_register); **/ void iio_device_unregister(struct iio_dev *indio_dev) { - cdev_device_del(&indio_dev->chrdev, &indio_dev->dev); + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); - mutex_lock(&indio_dev->info_exist_lock); + cdev_device_del(&iio_dev_opaque->chrdev, &indio_dev->dev); + + mutex_lock(&iio_dev_opaque->info_exist_lock); iio_device_unregister_debugfs(indio_dev); @@ -1938,35 +1962,27 @@ void iio_device_unregister(struct iio_dev *indio_dev) iio_device_wakeup_eventset(indio_dev); iio_buffer_wakeup_poll(indio_dev); - mutex_unlock(&indio_dev->info_exist_lock); + mutex_unlock(&iio_dev_opaque->info_exist_lock); iio_buffers_free_sysfs_and_mask(indio_dev); } EXPORT_SYMBOL(iio_device_unregister); -static void devm_iio_device_unreg(struct device *dev, void *res) +static void devm_iio_device_unreg(void *indio_dev) { - iio_device_unregister(*(struct iio_dev **)res); + iio_device_unregister(indio_dev); } int __devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev, struct module *this_mod) { - struct iio_dev **ptr; int ret; - ptr = devres_alloc(devm_iio_device_unreg, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return -ENOMEM; - - *ptr = indio_dev; ret = __iio_device_register(indio_dev, this_mod); - if (!ret) - devres_add(dev, ptr); - else - devres_free(ptr); + if (ret) + return ret; - return ret; + return devm_add_action_or_reset(dev, devm_iio_device_unreg, indio_dev); } EXPORT_SYMBOL_GPL(__devm_iio_device_register); diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index b2c94abbb487..b23caa2f2aa1 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -13,6 +13,7 @@ #include <linux/slab.h> #include <linux/iio/iio.h> +#include <linux/iio/iio-opaque.h> #include <linux/iio/trigger.h> #include "iio_core.h" #include "iio_core_trigger.h" @@ -116,14 +117,17 @@ EXPORT_SYMBOL(iio_trigger_unregister); int iio_trigger_set_immutable(struct iio_dev *indio_dev, struct iio_trigger *trig) { + struct iio_dev_opaque *iio_dev_opaque; + if (!indio_dev || !trig) return -EINVAL; + iio_dev_opaque = to_iio_dev_opaque(indio_dev); mutex_lock(&indio_dev->mlock); - WARN_ON(indio_dev->trig_readonly); + WARN_ON(iio_dev_opaque->trig_readonly); indio_dev->trig = iio_trigger_get(trig); - indio_dev->trig_readonly = true; + iio_dev_opaque->trig_readonly = true; mutex_unlock(&indio_dev->mlock); return 0; @@ -240,12 +244,13 @@ static void iio_trigger_put_irq(struct iio_trigger *trig, int irq) int iio_trigger_attach_poll_func(struct iio_trigger *trig, struct iio_poll_func *pf) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(pf->indio_dev); bool notinuse = bitmap_empty(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER); int ret = 0; /* Prevent the module from being removed whilst attached to a trigger */ - __module_get(pf->indio_dev->driver_module); + __module_get(iio_dev_opaque->driver_module); /* Get irq number */ pf->irq = iio_trigger_get_irq(trig); @@ -284,13 +289,14 @@ out_free_irq: out_put_irq: iio_trigger_put_irq(trig, pf->irq); out_put_module: - module_put(pf->indio_dev->driver_module); + module_put(iio_dev_opaque->driver_module); return ret; } int iio_trigger_detach_poll_func(struct iio_trigger *trig, struct iio_poll_func *pf) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(pf->indio_dev); bool no_other_users = bitmap_weight(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER) == 1; int ret = 0; @@ -304,7 +310,7 @@ int iio_trigger_detach_poll_func(struct iio_trigger *trig, trig->attached_own_device = false; iio_trigger_put_irq(trig, pf->irq); free_irq(pf->irq, pf); - module_put(pf->indio_dev->driver_module); + module_put(iio_dev_opaque->driver_module); return ret; } @@ -399,6 +405,7 @@ static ssize_t iio_trigger_write_current(struct device *dev, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); struct iio_trigger *oldtrig = indio_dev->trig; struct iio_trigger *trig; int ret; @@ -408,7 +415,7 @@ static ssize_t iio_trigger_write_current(struct device *dev, mutex_unlock(&indio_dev->mlock); return -EBUSY; } - if (indio_dev->trig_readonly) { + if (iio_dev_opaque->trig_readonly) { mutex_unlock(&indio_dev->mlock); return -EPERM; } @@ -634,9 +641,9 @@ struct iio_trigger *devm_iio_trigger_alloc(struct device *parent, const char *fm } EXPORT_SYMBOL_GPL(devm_iio_trigger_alloc); -static void devm_iio_trigger_unreg(struct device *dev, void *res) +static void devm_iio_trigger_unreg(void *trigger_info) { - iio_trigger_unregister(*(struct iio_trigger **)res); + iio_trigger_unregister(trigger_info); } /** @@ -657,21 +664,13 @@ int __devm_iio_trigger_register(struct device *dev, struct iio_trigger *trig_info, struct module *this_mod) { - struct iio_trigger **ptr; int ret; - ptr = devres_alloc(devm_iio_trigger_unreg, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return -ENOMEM; - - *ptr = trig_info; ret = __iio_trigger_register(trig_info, this_mod); - if (!ret) - devres_add(dev, ptr); - else - devres_free(ptr); + if (ret) + return ret; - return ret; + return devm_add_action_or_reset(dev, devm_iio_trigger_unreg, trig_info); } EXPORT_SYMBOL_GPL(__devm_iio_trigger_register); diff --git a/drivers/iio/industrialio-triggered-event.c b/drivers/iio/industrialio-triggered-event.c index 53da9ab17a62..4bedc65c9fe3 100644 --- a/drivers/iio/industrialio-triggered-event.c +++ b/drivers/iio/industrialio-triggered-event.c @@ -37,7 +37,7 @@ int iio_triggered_event_setup(struct iio_dev *indio_dev, indio_dev, "%s_consumer%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (indio_dev->pollfunc_event == NULL) return -ENOMEM; diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 9c22697b7e83..391a3380a1d1 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -10,6 +10,7 @@ #include <linux/of.h> #include <linux/iio/iio.h> +#include <linux/iio/iio-opaque.h> #include "iio_core.h" #include <linux/iio/machine.h> #include <linux/iio/driver.h> @@ -359,30 +360,24 @@ void iio_channel_release(struct iio_channel *channel) } EXPORT_SYMBOL_GPL(iio_channel_release); -static void devm_iio_channel_free(struct device *dev, void *res) +static void devm_iio_channel_free(void *iio_channel) { - struct iio_channel *channel = *(struct iio_channel **)res; - - iio_channel_release(channel); + iio_channel_release(iio_channel); } struct iio_channel *devm_iio_channel_get(struct device *dev, const char *channel_name) { - struct iio_channel **ptr, *channel; - - ptr = devres_alloc(devm_iio_channel_free, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); + struct iio_channel *channel; + int ret; channel = iio_channel_get(dev, channel_name); - if (IS_ERR(channel)) { - devres_free(ptr); + if (IS_ERR(channel)) return channel; - } - *ptr = channel; - devres_add(dev, ptr); + ret = devm_add_action_or_reset(dev, devm_iio_channel_free, channel); + if (ret) + return ERR_PTR(ret); return channel; } @@ -392,20 +387,16 @@ struct iio_channel *devm_of_iio_channel_get_by_name(struct device *dev, struct device_node *np, const char *channel_name) { - struct iio_channel **ptr, *channel; - - ptr = devres_alloc(devm_iio_channel_free, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); + struct iio_channel *channel; + int ret; channel = of_iio_channel_get_by_name(np, channel_name); - if (IS_ERR(channel)) { - devres_free(ptr); + if (IS_ERR(channel)) return channel; - } - *ptr = channel; - devres_add(dev, ptr); + ret = devm_add_action_or_reset(dev, devm_iio_channel_free, channel); + if (ret) + return ERR_PTR(ret); return channel; } @@ -496,29 +487,24 @@ void iio_channel_release_all(struct iio_channel *channels) } EXPORT_SYMBOL_GPL(iio_channel_release_all); -static void devm_iio_channel_free_all(struct device *dev, void *res) +static void devm_iio_channel_free_all(void *iio_channels) { - struct iio_channel *channels = *(struct iio_channel **)res; - - iio_channel_release_all(channels); + iio_channel_release_all(iio_channels); } struct iio_channel *devm_iio_channel_get_all(struct device *dev) { - struct iio_channel **ptr, *channels; - - ptr = devres_alloc(devm_iio_channel_free_all, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); + struct iio_channel *channels; + int ret; channels = iio_channel_get_all(dev); - if (IS_ERR(channels)) { - devres_free(ptr); + if (IS_ERR(channels)) return channels; - } - *ptr = channels; - devres_add(dev, ptr); + ret = devm_add_action_or_reset(dev, devm_iio_channel_free_all, + channels); + if (ret) + return ERR_PTR(ret); return channels; } @@ -553,9 +539,10 @@ static int iio_channel_read(struct iio_channel *chan, int *val, int *val2, int iio_read_channel_raw(struct iio_channel *chan, int *val) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); int ret; - mutex_lock(&chan->indio_dev->info_exist_lock); + mutex_lock(&iio_dev_opaque->info_exist_lock); if (chan->indio_dev->info == NULL) { ret = -ENODEV; goto err_unlock; @@ -563,7 +550,7 @@ int iio_read_channel_raw(struct iio_channel *chan, int *val) ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW); err_unlock: - mutex_unlock(&chan->indio_dev->info_exist_lock); + mutex_unlock(&iio_dev_opaque->info_exist_lock); return ret; } @@ -571,9 +558,10 @@ EXPORT_SYMBOL_GPL(iio_read_channel_raw); int iio_read_channel_average_raw(struct iio_channel *chan, int *val) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); int ret; - mutex_lock(&chan->indio_dev->info_exist_lock); + mutex_lock(&iio_dev_opaque->info_exist_lock); if (chan->indio_dev->info == NULL) { ret = -ENODEV; goto err_unlock; @@ -581,7 +569,7 @@ int iio_read_channel_average_raw(struct iio_channel *chan, int *val) ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_AVERAGE_RAW); err_unlock: - mutex_unlock(&chan->indio_dev->info_exist_lock); + mutex_unlock(&iio_dev_opaque->info_exist_lock); return ret; } @@ -646,9 +634,10 @@ static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan, int iio_convert_raw_to_processed(struct iio_channel *chan, int raw, int *processed, unsigned int scale) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); int ret; - mutex_lock(&chan->indio_dev->info_exist_lock); + mutex_lock(&iio_dev_opaque->info_exist_lock); if (chan->indio_dev->info == NULL) { ret = -ENODEV; goto err_unlock; @@ -657,7 +646,7 @@ int iio_convert_raw_to_processed(struct iio_channel *chan, int raw, ret = iio_convert_raw_to_processed_unlocked(chan, raw, processed, scale); err_unlock: - mutex_unlock(&chan->indio_dev->info_exist_lock); + mutex_unlock(&iio_dev_opaque->info_exist_lock); return ret; } @@ -666,9 +655,10 @@ EXPORT_SYMBOL_GPL(iio_convert_raw_to_processed); int iio_read_channel_attribute(struct iio_channel *chan, int *val, int *val2, enum iio_chan_info_enum attribute) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); int ret; - mutex_lock(&chan->indio_dev->info_exist_lock); + mutex_lock(&iio_dev_opaque->info_exist_lock); if (chan->indio_dev->info == NULL) { ret = -ENODEV; goto err_unlock; @@ -676,7 +666,7 @@ int iio_read_channel_attribute(struct iio_channel *chan, int *val, int *val2, ret = iio_channel_read(chan, val, val2, attribute); err_unlock: - mutex_unlock(&chan->indio_dev->info_exist_lock); + mutex_unlock(&iio_dev_opaque->info_exist_lock); return ret; } @@ -691,9 +681,10 @@ EXPORT_SYMBOL_GPL(iio_read_channel_offset); int iio_read_channel_processed_scale(struct iio_channel *chan, int *val, unsigned int scale) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); int ret; - mutex_lock(&chan->indio_dev->info_exist_lock); + mutex_lock(&iio_dev_opaque->info_exist_lock); if (chan->indio_dev->info == NULL) { ret = -ENODEV; goto err_unlock; @@ -714,7 +705,7 @@ int iio_read_channel_processed_scale(struct iio_channel *chan, int *val, } err_unlock: - mutex_unlock(&chan->indio_dev->info_exist_lock); + mutex_unlock(&iio_dev_opaque->info_exist_lock); return ret; } @@ -748,9 +739,10 @@ int iio_read_avail_channel_attribute(struct iio_channel *chan, const int **vals, int *type, int *length, enum iio_chan_info_enum attribute) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); int ret; - mutex_lock(&chan->indio_dev->info_exist_lock); + mutex_lock(&iio_dev_opaque->info_exist_lock); if (!chan->indio_dev->info) { ret = -ENODEV; goto err_unlock; @@ -758,7 +750,7 @@ int iio_read_avail_channel_attribute(struct iio_channel *chan, ret = iio_channel_read_avail(chan, vals, type, length, attribute); err_unlock: - mutex_unlock(&chan->indio_dev->info_exist_lock); + mutex_unlock(&iio_dev_opaque->info_exist_lock); return ret; } @@ -830,10 +822,11 @@ static int iio_channel_read_max(struct iio_channel *chan, int iio_read_max_channel_raw(struct iio_channel *chan, int *val) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); int ret; int type; - mutex_lock(&chan->indio_dev->info_exist_lock); + mutex_lock(&iio_dev_opaque->info_exist_lock); if (!chan->indio_dev->info) { ret = -ENODEV; goto err_unlock; @@ -841,7 +834,7 @@ int iio_read_max_channel_raw(struct iio_channel *chan, int *val) ret = iio_channel_read_max(chan, val, NULL, &type, IIO_CHAN_INFO_RAW); err_unlock: - mutex_unlock(&chan->indio_dev->info_exist_lock); + mutex_unlock(&iio_dev_opaque->info_exist_lock); return ret; } @@ -849,10 +842,11 @@ EXPORT_SYMBOL_GPL(iio_read_max_channel_raw); int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); int ret = 0; /* Need to verify underlying driver has not gone away */ - mutex_lock(&chan->indio_dev->info_exist_lock); + mutex_lock(&iio_dev_opaque->info_exist_lock); if (chan->indio_dev->info == NULL) { ret = -ENODEV; goto err_unlock; @@ -860,7 +854,7 @@ int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type) *type = chan->channel->type; err_unlock: - mutex_unlock(&chan->indio_dev->info_exist_lock); + mutex_unlock(&iio_dev_opaque->info_exist_lock); return ret; } @@ -876,9 +870,10 @@ static int iio_channel_write(struct iio_channel *chan, int val, int val2, int iio_write_channel_attribute(struct iio_channel *chan, int val, int val2, enum iio_chan_info_enum attribute) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); int ret; - mutex_lock(&chan->indio_dev->info_exist_lock); + mutex_lock(&iio_dev_opaque->info_exist_lock); if (chan->indio_dev->info == NULL) { ret = -ENODEV; goto err_unlock; @@ -886,7 +881,7 @@ int iio_write_channel_attribute(struct iio_channel *chan, int val, int val2, ret = iio_channel_write(chan, val, val2, attribute); err_unlock: - mutex_unlock(&chan->indio_dev->info_exist_lock); + mutex_unlock(&iio_dev_opaque->info_exist_lock); return ret; } diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 917f9becf9c7..a62c7b4b8678 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -499,6 +499,17 @@ config TSL2583 Provides support for the TAOS tsl2580, tsl2581 and tsl2583 devices. Access ALS data via iio, sysfs. +config TSL2591 + tristate "TAOS TSL2591 ambient light sensor" + depends on I2C + help + Select Y here for support of the AMS/TAOS TSL2591 ambient light sensor, + featuring channels for combined visible + IR intensity and lux illuminance. + Access data via iio and sysfs. Supports iio_events. + + To compile this driver as a module, select M: the + module will be called tsl2591. + config TSL2772 tristate "TAOS TSL/TMD2x71 and TSL/TMD2x72 Family of light and proximity sensors" depends on I2C diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index ea376deaca54..d10912faf964 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_ST_UVIS25_SPI) += st_uvis25_spi.o obj-$(CONFIG_TCS3414) += tcs3414.o obj-$(CONFIG_TCS3472) += tcs3472.o obj-$(CONFIG_TSL2583) += tsl2583.o +obj-$(CONFIG_TSL2591) += tsl2591.o obj-$(CONFIG_TSL2772) += tsl2772.o obj-$(CONFIG_TSL4531) += tsl4531.o obj-$(CONFIG_US5182D) += us5182d.o diff --git a/drivers/iio/light/acpi-als.c b/drivers/iio/light/acpi-als.c index 0a6ab5761eec..e1ff6f524f4b 100644 --- a/drivers/iio/light/acpi-als.c +++ b/drivers/iio/light/acpi-als.c @@ -204,7 +204,8 @@ static int acpi_als_add(struct acpi_device *device) indio_dev->channels = acpi_als_channels; indio_dev->num_channels = ARRAY_SIZE(acpi_als_channels); - als->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, indio_dev->id); + als->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, + iio_device_id(indio_dev)); if (!als->trig) return -ENOMEM; diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c index 85c8a05b73cb..2ff252c75c03 100644 --- a/drivers/iio/light/hid-sensor-als.c +++ b/drivers/iio/light/hid-sensor-als.c @@ -6,13 +6,10 @@ #include <linux/device.h> #include <linux/platform_device.h> #include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/irq.h> +#include <linux/mod_devicetable.h> #include <linux/slab.h> -#include <linux/delay.h> #include <linux/hid-sensor-hub.h> #include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> #include <linux/iio/buffer.h> #include "../common/hid-sensors/hid-sensor-trigger.h" @@ -392,3 +389,4 @@ module_platform_driver(hid_als_platform_driver); MODULE_DESCRIPTION("HID Sensor ALS"); MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(IIO_HID); diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c index 17d167c3d595..1621530f5f61 100644 --- a/drivers/iio/light/hid-sensor-prox.c +++ b/drivers/iio/light/hid-sensor-prox.c @@ -6,13 +6,10 @@ #include <linux/device.h> #include <linux/platform_device.h> #include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/irq.h> +#include <linux/mod_devicetable.h> #include <linux/slab.h> -#include <linux/delay.h> #include <linux/hid-sensor-hub.h> #include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> #include <linux/iio/buffer.h> #include "../common/hid-sensors/hid-sensor-trigger.h" @@ -350,3 +347,4 @@ module_platform_driver(hid_prox_platform_driver); MODULE_DESCRIPTION("HID Sensor Proximity"); MODULE_AUTHOR("Archana Patni <archana.patni@intel.com>"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(IIO_HID); diff --git a/drivers/iio/light/isl29028.c b/drivers/iio/light/isl29028.c index 2f8b494f3e08..9de3262aa688 100644 --- a/drivers/iio/light/isl29028.c +++ b/drivers/iio/light/isl29028.c @@ -339,9 +339,7 @@ static int isl29028_set_pm_runtime_busy(struct isl29028_chip *chip, bool on) int ret; if (on) { - ret = pm_runtime_get_sync(dev); - if (ret < 0) - pm_runtime_put_noidle(dev); + ret = pm_runtime_resume_and_get(dev); } else { pm_runtime_mark_last_busy(dev); ret = pm_runtime_put_autosuspend(dev); @@ -647,7 +645,6 @@ static int isl29028_remove(struct i2c_client *client) pm_runtime_disable(&client->dev); pm_runtime_set_suspended(&client->dev); - pm_runtime_put_noidle(&client->dev); return isl29028_clear_configure_reg(chip); } diff --git a/drivers/iio/light/isl29125.c b/drivers/iio/light/isl29125.c index b93b85dbc3a6..ba53b50d711a 100644 --- a/drivers/iio/light/isl29125.c +++ b/drivers/iio/light/isl29125.c @@ -51,7 +51,11 @@ struct isl29125_data { struct i2c_client *client; u8 conf1; - u16 buffer[8]; /* 3x 16-bit, padding, 8 bytes timestamp */ + /* Ensure timestamp is naturally aligned */ + struct { + u16 chans[3]; + s64 timestamp __aligned(8); + } scan; }; #define ISL29125_CHANNEL(_color, _si) { \ @@ -184,10 +188,10 @@ static irqreturn_t isl29125_trigger_handler(int irq, void *p) if (ret < 0) goto done; - data->buffer[j++] = ret; + data->scan.chans[j++] = ret; } - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, iio_get_time_ns(indio_dev)); done: diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index b4323d2db0b1..1830221da48d 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -32,9 +32,12 @@ #define LTR501_PART_ID 0x86 #define LTR501_MANUFAC_ID 0x87 #define LTR501_ALS_DATA1 0x88 /* 16-bit, little endian */ +#define LTR501_ALS_DATA1_UPPER 0x89 /* upper 8 bits of LTR501_ALS_DATA1 */ #define LTR501_ALS_DATA0 0x8a /* 16-bit, little endian */ +#define LTR501_ALS_DATA0_UPPER 0x8b /* upper 8 bits of LTR501_ALS_DATA0 */ #define LTR501_ALS_PS_STATUS 0x8c #define LTR501_PS_DATA 0x8d /* 16-bit, little endian */ +#define LTR501_PS_DATA_UPPER 0x8e /* upper 8 bits of LTR501_PS_DATA */ #define LTR501_INTR 0x8f /* output mode, polarity, mode */ #define LTR501_PS_THRESH_UP 0x90 /* 11 bit, ps upper threshold */ #define LTR501_PS_THRESH_LOW 0x92 /* 11 bit, ps lower threshold */ @@ -149,7 +152,7 @@ struct ltr501_chip_info { struct ltr501_data { struct i2c_client *client; struct mutex lock_als, lock_ps; - struct ltr501_chip_info *chip_info; + const struct ltr501_chip_info *chip_info; u8 als_contr, ps_contr; int als_period, ps_period; /* period in micro seconds */ struct regmap *regmap; @@ -406,18 +409,19 @@ static int ltr501_read_als(const struct ltr501_data *data, __le16 buf[2]) static int ltr501_read_ps(const struct ltr501_data *data) { - int ret, status; + __le16 status; + int ret; ret = ltr501_drdy(data, LTR501_STATUS_PS_RDY); if (ret < 0) return ret; ret = regmap_bulk_read(data->regmap, LTR501_PS_DATA, - &status, 2); + &status, sizeof(status)); if (ret < 0) return ret; - return status; + return le16_to_cpu(status); } static int ltr501_read_intr_prst(const struct ltr501_data *data, @@ -735,7 +739,7 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, { struct ltr501_data *data = iio_priv(indio_dev); int i, ret, freq_val, freq_val2; - struct ltr501_chip_info *info = data->chip_info; + const struct ltr501_chip_info *info = data->chip_info; ret = iio_device_claim_direct_mode(indio_dev); if (ret) @@ -1082,7 +1086,7 @@ static ssize_t ltr501_show_proximity_scale_avail(struct device *dev, char *buf) { struct ltr501_data *data = iio_priv(dev_to_iio_dev(dev)); - struct ltr501_chip_info *info = data->chip_info; + const struct ltr501_chip_info *info = data->chip_info; ssize_t len = 0; int i; @@ -1104,7 +1108,7 @@ static ssize_t ltr501_show_intensity_scale_avail(struct device *dev, char *buf) { struct ltr501_data *data = iio_priv(dev_to_iio_dev(dev)); - struct ltr501_chip_info *info = data->chip_info; + const struct ltr501_chip_info *info = data->chip_info; ssize_t len = 0; int i; @@ -1184,7 +1188,7 @@ static const struct iio_info ltr301_info = { .write_event_config = <r501_write_event_config, }; -static struct ltr501_chip_info ltr501_chip_info_tbl[] = { +static const struct ltr501_chip_info ltr501_chip_info_tbl[] = { [ltr501] = { .partid = 0x08, .als_gain = ltr501_als_gain_tbl, @@ -1205,7 +1209,7 @@ static struct ltr501_chip_info ltr501_chip_info_tbl[] = { .als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl), .ps_gain = ltr559_ps_gain_tbl, .ps_gain_tbl_size = ARRAY_SIZE(ltr559_ps_gain_tbl), - .als_mode_active = BIT(1), + .als_mode_active = BIT(0), .als_gain_mask = BIT(2) | BIT(3) | BIT(4), .als_gain_shift = 2, .info = <r501_info, @@ -1354,9 +1358,12 @@ static bool ltr501_is_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { case LTR501_ALS_DATA1: + case LTR501_ALS_DATA1_UPPER: case LTR501_ALS_DATA0: + case LTR501_ALS_DATA0_UPPER: case LTR501_ALS_PS_STATUS: case LTR501_PS_DATA: + case LTR501_PS_DATA_UPPER: return true; default: return false; diff --git a/drivers/iio/light/pa12203001.c b/drivers/iio/light/pa12203001.c index bfade6577a38..a52b2c788540 100644 --- a/drivers/iio/light/pa12203001.c +++ b/drivers/iio/light/pa12203001.c @@ -186,9 +186,7 @@ static int pa12203001_set_power_state(struct pa12203001_data *data, bool on, } if (on) { - ret = pm_runtime_get_sync(&data->client->dev); - if (ret < 0) - pm_runtime_put_noidle(&data->client->dev); + ret = pm_runtime_resume_and_get(&data->client->dev); } else { pm_runtime_mark_last_busy(&data->client->dev); diff --git a/drivers/iio/light/rpr0521.c b/drivers/iio/light/rpr0521.c index 033578f444e4..c2dd8a3d4217 100644 --- a/drivers/iio/light/rpr0521.c +++ b/drivers/iio/light/rpr0521.c @@ -360,7 +360,7 @@ static int rpr0521_set_power_state(struct rpr0521_data *data, bool on, * both stay enabled until _suspend(). */ if (on) { - ret = pm_runtime_get_sync(&data->client->dev); + ret = pm_runtime_resume_and_get(&data->client->dev); } else { pm_runtime_mark_last_busy(&data->client->dev); ret = pm_runtime_put_autosuspend(&data->client->dev); @@ -369,9 +369,6 @@ static int rpr0521_set_power_state(struct rpr0521_data *data, bool on, dev_err(&data->client->dev, "Failed: rpr0521_set_power_state for %d, ret %d\n", on, ret); - if (on) - pm_runtime_put_noidle(&data->client->dev); - return ret; } @@ -985,7 +982,7 @@ static int rpr0521_probe(struct i2c_client *client, /* Trigger0 producer setup */ data->drdy_trigger0 = devm_iio_trigger_alloc( indio_dev->dev.parent, - "%s-dev%d", indio_dev->name, indio_dev->id); + "%s-dev%d", indio_dev->name, iio_device_id(indio_dev)); if (!data->drdy_trigger0) { ret = -ENOMEM; goto err_pm_disable; @@ -1038,7 +1035,6 @@ static int rpr0521_probe(struct i2c_client *client, err_pm_disable: pm_runtime_disable(&client->dev); pm_runtime_set_suspended(&client->dev); - pm_runtime_put_noidle(&client->dev); err_poweroff: rpr0521_poweroff(data); @@ -1053,7 +1049,6 @@ static int rpr0521_remove(struct i2c_client *client) pm_runtime_disable(&client->dev); pm_runtime_set_suspended(&client->dev); - pm_runtime_put_noidle(&client->dev); rpr0521_poweroff(iio_priv(indio_dev)); diff --git a/drivers/iio/light/si1133.c b/drivers/iio/light/si1133.c index c280b4195003..f8c9b2cc322e 100644 --- a/drivers/iio/light/si1133.c +++ b/drivers/iio/light/si1133.c @@ -352,22 +352,22 @@ static int si1133_parse_response_err(struct device *dev, u32 resp, u8 cmd) switch (resp) { case SI1133_ERR_OUTPUT_BUFFER_OVERFLOW: - dev_warn(dev, "Output buffer overflow: %#02hhx\n", cmd); + dev_warn(dev, "Output buffer overflow: 0x%02x\n", cmd); return -EOVERFLOW; case SI1133_ERR_SATURATION_ADC_OR_OVERFLOW_ACCUMULATION: - dev_warn(dev, "Saturation of the ADC or overflow of accumulation: %#02hhx\n", + dev_warn(dev, "Saturation of the ADC or overflow of accumulation: 0x%02x\n", cmd); return -EOVERFLOW; case SI1133_ERR_INVALID_LOCATION_CMD: dev_warn(dev, - "Parameter access to an invalid location: %#02hhx\n", + "Parameter access to an invalid location: 0x%02x\n", cmd); return -EINVAL; case SI1133_ERR_INVALID_CMD: - dev_warn(dev, "Invalid command %#02hhx\n", cmd); + dev_warn(dev, "Invalid command 0x%02x\n", cmd); return -EINVAL; default: - dev_warn(dev, "Unknown error %#02hhx\n", cmd); + dev_warn(dev, "Unknown error 0x%02x\n", cmd); return -EINVAL; } } @@ -400,7 +400,7 @@ static int si1133_command(struct si1133_data *data, u8 cmd) err = regmap_write(data->regmap, SI1133_REG_COMMAND, cmd); if (err) { - dev_warn(dev, "Failed to write command %#02hhx, ret=%d\n", cmd, + dev_warn(dev, "Failed to write command 0x%02x, ret=%d\n", cmd, err); goto out; } @@ -425,7 +425,7 @@ static int si1133_command(struct si1133_data *data, u8 cmd) SI1133_CMD_TIMEOUT_MS * 1000); if (err) { dev_warn(dev, - "Failed to read command %#02hhx, ret=%d\n", + "Failed to read command 0x%02x, ret=%d\n", cmd, err); goto out; } @@ -978,11 +978,11 @@ static int si1133_validate_ids(struct iio_dev *iio_dev) return err; dev_info(&iio_dev->dev, - "Device ID part %#02hhx rev %#02hhx mfr %#02hhx\n", + "Device ID part 0x%02x rev 0x%02x mfr 0x%02x\n", part_id, rev_id, mfr_id); if (part_id != SI1133_PART_ID) { dev_err(&iio_dev->dev, - "Part ID mismatch got %#02hhx, expected %#02x\n", + "Part ID mismatch got 0x%02x, expected 0x%02x\n", part_id, SI1133_PART_ID); return -ENODEV; } diff --git a/drivers/iio/light/si1145.c b/drivers/iio/light/si1145.c index 9b5c99823943..e2abad48b9f4 100644 --- a/drivers/iio/light/si1145.c +++ b/drivers/iio/light/si1145.c @@ -271,7 +271,7 @@ static int si1145_command(struct si1145_data *data, u8 cmd) if ((ret & ~SI1145_RSP_COUNTER_MASK) == 0) { if (ret == data->rsp_seq) { if (time_after(jiffies, stop_jiffies)) { - dev_warn(dev, "timeout on command %#02hhx\n", + dev_warn(dev, "timeout on command 0x%02x\n", cmd); ret = -ETIMEDOUT; break; @@ -291,12 +291,12 @@ static int si1145_command(struct si1145_data *data, u8 cmd) ret = -EIO; } else { if (ret == SI1145_RSP_INVALID_SETTING) { - dev_warn(dev, "INVALID_SETTING error on command %#02hhx\n", + dev_warn(dev, "INVALID_SETTING error on command 0x%02x\n", cmd); ret = -EINVAL; } else { /* All overflows are treated identically */ - dev_dbg(dev, "overflow, ret=%d, cmd=%#02hhx\n", + dev_dbg(dev, "overflow, ret=%d, cmd=0x%02x\n", ret, cmd); ret = -EOVERFLOW; } @@ -1243,7 +1243,7 @@ static int si1145_probe_trigger(struct iio_dev *indio_dev) int ret; trig = devm_iio_trigger_alloc(&client->dev, - "%s-dev%d", indio_dev->name, indio_dev->id); + "%s-dev%d", indio_dev->name, iio_device_id(indio_dev)); if (!trig) return -ENOMEM; @@ -1299,10 +1299,10 @@ static int si1145_probe(struct i2c_client *client, SI1145_REG_SEQ_ID); if (ret < 0) return ret; - dev_info(&client->dev, "device ID part %#02hhx rev %#02hhx seq %#02hhx\n", + dev_info(&client->dev, "device ID part 0x%02x rev 0x%02x seq 0x%02x\n", part_id, rev_id, seq_id); if (part_id != data->part_info->part) { - dev_err(&client->dev, "part ID mismatch got %#02hhx, expected %#02x\n", + dev_err(&client->dev, "part ID mismatch got 0x%02x, expected 0x%02x\n", part_id, data->part_info->part); return -ENODEV; } diff --git a/drivers/iio/light/tcs3414.c b/drivers/iio/light/tcs3414.c index 6fe5d46f80d4..0593abd600ec 100644 --- a/drivers/iio/light/tcs3414.c +++ b/drivers/iio/light/tcs3414.c @@ -53,7 +53,11 @@ struct tcs3414_data { u8 control; u8 gain; u8 timing; - u16 buffer[8]; /* 4x 16-bit + 8 bytes timestamp */ + /* Ensure timestamp is naturally aligned */ + struct { + u16 chans[4]; + s64 timestamp __aligned(8); + } scan; }; #define TCS3414_CHANNEL(_color, _si, _addr) { \ @@ -209,10 +213,10 @@ static irqreturn_t tcs3414_trigger_handler(int irq, void *p) if (ret < 0) goto done; - data->buffer[j++] = ret; + data->scan.chans[j++] = ret; } - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, iio_get_time_ns(indio_dev)); done: diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c index a0dc447aeb68..371c6a39a165 100644 --- a/drivers/iio/light/tcs3472.c +++ b/drivers/iio/light/tcs3472.c @@ -64,7 +64,11 @@ struct tcs3472_data { u8 control; u8 atime; u8 apers; - u16 buffer[8]; /* 4 16-bit channels + 64-bit timestamp */ + /* Ensure timestamp is naturally aligned */ + struct { + u16 chans[4]; + s64 timestamp __aligned(8); + } scan; }; static const struct iio_event_spec tcs3472_events[] = { @@ -386,10 +390,10 @@ static irqreturn_t tcs3472_trigger_handler(int irq, void *p) if (ret < 0) goto done; - data->buffer[j++] = ret; + data->scan.chans[j++] = ret; } - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, iio_get_time_ns(indio_dev)); done: @@ -531,7 +535,8 @@ static int tcs3472_probe(struct i2c_client *client, return 0; free_irq: - free_irq(client->irq, indio_dev); + if (client->irq) + free_irq(client->irq, indio_dev); buffer_cleanup: iio_triggered_buffer_cleanup(indio_dev); return ret; @@ -559,7 +564,8 @@ static int tcs3472_remove(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); iio_device_unregister(indio_dev); - free_irq(client->irq, indio_dev); + if (client->irq) + free_irq(client->irq, indio_dev); iio_triggered_buffer_cleanup(indio_dev); tcs3472_powerdown(iio_priv(indio_dev)); diff --git a/drivers/iio/light/tsl2583.c b/drivers/iio/light/tsl2583.c index c9d8f07a6fcd..7e101d5f72ee 100644 --- a/drivers/iio/light/tsl2583.c +++ b/drivers/iio/light/tsl2583.c @@ -644,9 +644,7 @@ static int tsl2583_set_pm_runtime_busy(struct tsl2583_chip *chip, bool on) int ret; if (on) { - ret = pm_runtime_get_sync(&chip->client->dev); - if (ret < 0) - pm_runtime_put_noidle(&chip->client->dev); + ret = pm_runtime_resume_and_get(&chip->client->dev); } else { pm_runtime_mark_last_busy(&chip->client->dev); ret = pm_runtime_put_autosuspend(&chip->client->dev); @@ -729,8 +727,10 @@ static int tsl2583_read_raw(struct iio_dev *indio_dev, read_done: mutex_unlock(&chip->als_mutex); - if (ret < 0) + if (ret < 0) { + tsl2583_set_pm_runtime_busy(chip, false); return ret; + } /* * Preserve the ret variable if the call to @@ -791,8 +791,10 @@ static int tsl2583_write_raw(struct iio_dev *indio_dev, mutex_unlock(&chip->als_mutex); - if (ret < 0) + if (ret < 0) { + tsl2583_set_pm_runtime_busy(chip, false); return ret; + } ret = tsl2583_set_pm_runtime_busy(chip, false); if (ret < 0) @@ -880,7 +882,6 @@ static int tsl2583_remove(struct i2c_client *client) pm_runtime_disable(&client->dev); pm_runtime_set_suspended(&client->dev); - pm_runtime_put_noidle(&client->dev); return tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_OFF); } diff --git a/drivers/iio/light/tsl2591.c b/drivers/iio/light/tsl2591.c new file mode 100644 index 000000000000..39e68d0c9d6a --- /dev/null +++ b/drivers/iio/light/tsl2591.c @@ -0,0 +1,1225 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2021 Joe Sandom <joe.g.sandom@gmail.com> + * + * Datasheet: https://ams.com/tsl25911#tab/documents + * + * Device driver for the TAOS TSL2591. This is a very-high sensitivity + * light-to-digital converter that transforms light intensity into a digital + * signal. + */ + +#include <linux/bitfield.h> +#include <linux/debugfs.h> +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/iopoll.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/pm_runtime.h> +#include <linux/sysfs.h> + +#include <asm/unaligned.h> + +#include <linux/iio/events.h> +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> + +/* ADC integration time, field value to time in ms */ +#define TSL2591_FVAL_TO_MSEC(x) (((x) + 1) * 100) +/* ADC integration time, field value to time in seconds */ +#define TSL2591_FVAL_TO_SEC(x) ((x) + 1) +/* ADC integration time, time in seconds to field value */ +#define TSL2591_SEC_TO_FVAL(x) ((x) - 1) + +/* TSL2591 register set */ +#define TSL2591_ENABLE 0x00 +#define TSL2591_CONTROL 0x01 +#define TSL2591_AILTL 0x04 +#define TSL2591_AILTH 0x05 +#define TSL2591_AIHTL 0x06 +#define TSL2591_AIHTH 0x07 +#define TSL2591_NP_AILTL 0x08 +#define TSL2591_NP_AILTH 0x09 +#define TSL2591_NP_AIHTL 0x0A +#define TSL2591_NP_AIHTH 0x0B +#define TSL2591_PERSIST 0x0C +#define TSL2591_PACKAGE_ID 0x11 +#define TSL2591_DEVICE_ID 0x12 +#define TSL2591_STATUS 0x13 +#define TSL2591_C0_DATAL 0x14 +#define TSL2591_C0_DATAH 0x15 +#define TSL2591_C1_DATAL 0x16 +#define TSL2591_C1_DATAH 0x17 + +/* TSL2591 command register definitions */ +#define TSL2591_CMD_NOP 0xA0 +#define TSL2591_CMD_SF_INTSET 0xE4 +#define TSL2591_CMD_SF_CALS_I 0xE5 +#define TSL2591_CMD_SF_CALS_NPI 0xE7 +#define TSL2591_CMD_SF_CNP_ALSI 0xEA + +/* TSL2591 enable register definitions */ +#define TSL2591_PWR_ON 0x01 +#define TSL2591_PWR_OFF 0x00 +#define TSL2591_ENABLE_ALS 0x02 +#define TSL2591_ENABLE_ALS_INT 0x10 +#define TSL2591_ENABLE_SLEEP_INT 0x40 +#define TSL2591_ENABLE_NP_INT 0x80 + +/* TSL2591 control register definitions */ +#define TSL2591_CTRL_ALS_INTEGRATION_100MS 0x00 +#define TSL2591_CTRL_ALS_INTEGRATION_200MS 0x01 +#define TSL2591_CTRL_ALS_INTEGRATION_300MS 0x02 +#define TSL2591_CTRL_ALS_INTEGRATION_400MS 0x03 +#define TSL2591_CTRL_ALS_INTEGRATION_500MS 0x04 +#define TSL2591_CTRL_ALS_INTEGRATION_600MS 0x05 +#define TSL2591_CTRL_ALS_LOW_GAIN 0x00 +#define TSL2591_CTRL_ALS_MED_GAIN 0x10 +#define TSL2591_CTRL_ALS_HIGH_GAIN 0x20 +#define TSL2591_CTRL_ALS_MAX_GAIN 0x30 +#define TSL2591_CTRL_SYS_RESET 0x80 + +/* TSL2591 persist register definitions */ +#define TSL2591_PRST_ALS_INT_CYCLE_0 0x00 +#define TSL2591_PRST_ALS_INT_CYCLE_ANY 0x01 +#define TSL2591_PRST_ALS_INT_CYCLE_2 0x02 +#define TSL2591_PRST_ALS_INT_CYCLE_3 0x03 +#define TSL2591_PRST_ALS_INT_CYCLE_5 0x04 +#define TSL2591_PRST_ALS_INT_CYCLE_10 0x05 +#define TSL2591_PRST_ALS_INT_CYCLE_15 0x06 +#define TSL2591_PRST_ALS_INT_CYCLE_20 0x07 +#define TSL2591_PRST_ALS_INT_CYCLE_25 0x08 +#define TSL2591_PRST_ALS_INT_CYCLE_30 0x09 +#define TSL2591_PRST_ALS_INT_CYCLE_35 0x0A +#define TSL2591_PRST_ALS_INT_CYCLE_40 0x0B +#define TSL2591_PRST_ALS_INT_CYCLE_45 0x0C +#define TSL2591_PRST_ALS_INT_CYCLE_50 0x0D +#define TSL2591_PRST_ALS_INT_CYCLE_55 0x0E +#define TSL2591_PRST_ALS_INT_CYCLE_60 0x0F +#define TSL2591_PRST_ALS_INT_CYCLE_MAX (BIT(4) - 1) + +/* TSL2591 PID register mask */ +#define TSL2591_PACKAGE_ID_MASK GENMASK(5, 4) + +/* TSL2591 ID register mask */ +#define TSL2591_DEVICE_ID_MASK GENMASK(7, 0) + +/* TSL2591 status register masks */ +#define TSL2591_STS_ALS_VALID_MASK BIT(0) +#define TSL2591_STS_ALS_INT_MASK BIT(4) +#define TSL2591_STS_NPERS_INT_MASK BIT(5) +#define TSL2591_STS_VAL_HIGH_MASK BIT(0) + +/* TSL2591 constant values */ +#define TSL2591_PACKAGE_ID_VAL 0x00 +#define TSL2591_DEVICE_ID_VAL 0x50 + +/* Power off suspend delay time MS */ +#define TSL2591_POWER_OFF_DELAY_MS 2000 + +/* TSL2591 default values */ +#define TSL2591_DEFAULT_ALS_INT_TIME TSL2591_CTRL_ALS_INTEGRATION_300MS +#define TSL2591_DEFAULT_ALS_GAIN TSL2591_CTRL_ALS_MED_GAIN +#define TSL2591_DEFAULT_ALS_PERSIST TSL2591_PRST_ALS_INT_CYCLE_ANY +#define TSL2591_DEFAULT_ALS_LOWER_THRESH 100 +#define TSL2591_DEFAULT_ALS_UPPER_THRESH 1500 + +/* TSL2591 number of data registers */ +#define TSL2591_NUM_DATA_REGISTERS 4 + +/* TSL2591 number of valid status reads on ADC complete */ +#define TSL2591_ALS_STS_VALID_COUNT 10 + +/* TSL2591 delay period between polls when checking for ALS valid flag */ +#define TSL2591_DELAY_PERIOD_US 10000 + +/* TSL2591 maximum values */ +#define TSL2591_MAX_ALS_INT_TIME_MS 600 +#define TSL2591_ALS_MAX_VALUE (BIT(16) - 1) + +/* + * LUX calculations; + * AGAIN values from Adafruit's TSL2591 Arduino library + * https://github.com/adafruit/Adafruit_TSL2591_Library + */ +#define TSL2591_CTRL_ALS_LOW_GAIN_MULTIPLIER 1 +#define TSL2591_CTRL_ALS_MED_GAIN_MULTIPLIER 25 +#define TSL2591_CTRL_ALS_HIGH_GAIN_MULTIPLIER 428 +#define TSL2591_CTRL_ALS_MAX_GAIN_MULTIPLIER 9876 +#define TSL2591_LUX_COEFFICIENT 408 + +struct tsl2591_als_settings { + u16 als_lower_thresh; + u16 als_upper_thresh; + u8 als_int_time; + u8 als_persist; + u8 als_gain; +}; + +struct tsl2591_chip { + struct tsl2591_als_settings als_settings; + struct i2c_client *client; + /* + * Keep als_settings in sync with hardware state + * and ensure multiple readers are serialized. + */ + struct mutex als_mutex; + bool events_enabled; +}; + +/* + * Period table is ALS persist cycle x integration time setting + * Integration times: 100ms, 200ms, 300ms, 400ms, 500ms, 600ms + * ALS cycles: 1, 2, 3, 5, 10, 20, 25, 30, 35, 40, 45, 50, 55, 60 + */ +static const char * const tsl2591_als_period_list[] = { + "0.1 0.2 0.3 0.5 1.0 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0", + "0.2 0.4 0.6 1.0 2.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0", + "0.3 0.6 0.9 1.5 3.0 6.0 7.5 9.0 10.5 12.0 13.5 15.0 16.5 18.0", + "0.4 0.8 1.2 2.0 4.0 8.0 10.0 12.0 14.0 16.0 18.0 20.0 22.0 24.0", + "0.5 1.0 1.5 2.5 5.0 10.0 12.5 15.0 17.5 20.0 22.5 25.0 27.5 30.0", + "0.6 1.2 1.8 3.0 6.0 12.0 15.0 18.0 21.0 24.0 27.0 30.0 33.0 36.0", +}; + +static const int tsl2591_int_time_available[] = { + 1, 2, 3, 4, 5, 6, +}; + +static const int tsl2591_calibscale_available[] = { + 1, 25, 428, 9876, +}; + +static int tsl2591_set_als_lower_threshold(struct tsl2591_chip *chip, + u16 als_lower_threshold); +static int tsl2591_set_als_upper_threshold(struct tsl2591_chip *chip, + u16 als_upper_threshold); + +static int tsl2591_gain_to_multiplier(const u8 als_gain) +{ + switch (als_gain) { + case TSL2591_CTRL_ALS_LOW_GAIN: + return TSL2591_CTRL_ALS_LOW_GAIN_MULTIPLIER; + case TSL2591_CTRL_ALS_MED_GAIN: + return TSL2591_CTRL_ALS_MED_GAIN_MULTIPLIER; + case TSL2591_CTRL_ALS_HIGH_GAIN: + return TSL2591_CTRL_ALS_HIGH_GAIN_MULTIPLIER; + case TSL2591_CTRL_ALS_MAX_GAIN: + return TSL2591_CTRL_ALS_MAX_GAIN_MULTIPLIER; + default: + return -EINVAL; + } +} + +static int tsl2591_multiplier_to_gain(const u32 multiplier) +{ + switch (multiplier) { + case TSL2591_CTRL_ALS_LOW_GAIN_MULTIPLIER: + return TSL2591_CTRL_ALS_LOW_GAIN; + case TSL2591_CTRL_ALS_MED_GAIN_MULTIPLIER: + return TSL2591_CTRL_ALS_MED_GAIN; + case TSL2591_CTRL_ALS_HIGH_GAIN_MULTIPLIER: + return TSL2591_CTRL_ALS_HIGH_GAIN; + case TSL2591_CTRL_ALS_MAX_GAIN_MULTIPLIER: + return TSL2591_CTRL_ALS_MAX_GAIN; + default: + return -EINVAL; + } +} + +static int tsl2591_persist_cycle_to_lit(const u8 als_persist) +{ + switch (als_persist) { + case TSL2591_PRST_ALS_INT_CYCLE_ANY: + return 1; + case TSL2591_PRST_ALS_INT_CYCLE_2: + return 2; + case TSL2591_PRST_ALS_INT_CYCLE_3: + return 3; + case TSL2591_PRST_ALS_INT_CYCLE_5: + return 5; + case TSL2591_PRST_ALS_INT_CYCLE_10: + return 10; + case TSL2591_PRST_ALS_INT_CYCLE_15: + return 15; + case TSL2591_PRST_ALS_INT_CYCLE_20: + return 20; + case TSL2591_PRST_ALS_INT_CYCLE_25: + return 25; + case TSL2591_PRST_ALS_INT_CYCLE_30: + return 30; + case TSL2591_PRST_ALS_INT_CYCLE_35: + return 35; + case TSL2591_PRST_ALS_INT_CYCLE_40: + return 40; + case TSL2591_PRST_ALS_INT_CYCLE_45: + return 45; + case TSL2591_PRST_ALS_INT_CYCLE_50: + return 50; + case TSL2591_PRST_ALS_INT_CYCLE_55: + return 55; + case TSL2591_PRST_ALS_INT_CYCLE_60: + return 60; + default: + return -EINVAL; + } +} + +static int tsl2591_persist_lit_to_cycle(const u8 als_persist) +{ + switch (als_persist) { + case 1: + return TSL2591_PRST_ALS_INT_CYCLE_ANY; + case 2: + return TSL2591_PRST_ALS_INT_CYCLE_2; + case 3: + return TSL2591_PRST_ALS_INT_CYCLE_3; + case 5: + return TSL2591_PRST_ALS_INT_CYCLE_5; + case 10: + return TSL2591_PRST_ALS_INT_CYCLE_10; + case 15: + return TSL2591_PRST_ALS_INT_CYCLE_15; + case 20: + return TSL2591_PRST_ALS_INT_CYCLE_20; + case 25: + return TSL2591_PRST_ALS_INT_CYCLE_25; + case 30: + return TSL2591_PRST_ALS_INT_CYCLE_30; + case 35: + return TSL2591_PRST_ALS_INT_CYCLE_35; + case 40: + return TSL2591_PRST_ALS_INT_CYCLE_40; + case 45: + return TSL2591_PRST_ALS_INT_CYCLE_45; + case 50: + return TSL2591_PRST_ALS_INT_CYCLE_50; + case 55: + return TSL2591_PRST_ALS_INT_CYCLE_55; + case 60: + return TSL2591_PRST_ALS_INT_CYCLE_60; + default: + return -EINVAL; + } +} + +static int tsl2591_compatible_int_time(struct tsl2591_chip *chip, + const u32 als_integration_time) +{ + switch (als_integration_time) { + case TSL2591_CTRL_ALS_INTEGRATION_100MS: + case TSL2591_CTRL_ALS_INTEGRATION_200MS: + case TSL2591_CTRL_ALS_INTEGRATION_300MS: + case TSL2591_CTRL_ALS_INTEGRATION_400MS: + case TSL2591_CTRL_ALS_INTEGRATION_500MS: + case TSL2591_CTRL_ALS_INTEGRATION_600MS: + return 0; + default: + return -EINVAL; + } +} + +static int tsl2591_als_time_to_fval(const u32 als_integration_time) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(tsl2591_int_time_available); i++) { + if (als_integration_time == tsl2591_int_time_available[i]) + return TSL2591_SEC_TO_FVAL(als_integration_time); + } + + return -EINVAL; +} + +static int tsl2591_compatible_gain(struct tsl2591_chip *chip, const u8 als_gain) +{ + switch (als_gain) { + case TSL2591_CTRL_ALS_LOW_GAIN: + case TSL2591_CTRL_ALS_MED_GAIN: + case TSL2591_CTRL_ALS_HIGH_GAIN: + case TSL2591_CTRL_ALS_MAX_GAIN: + return 0; + default: + return -EINVAL; + } +} + +static int tsl2591_compatible_als_persist_cycle(struct tsl2591_chip *chip, + const u32 als_persist) +{ + switch (als_persist) { + case TSL2591_PRST_ALS_INT_CYCLE_ANY: + case TSL2591_PRST_ALS_INT_CYCLE_2: + case TSL2591_PRST_ALS_INT_CYCLE_3: + case TSL2591_PRST_ALS_INT_CYCLE_5: + case TSL2591_PRST_ALS_INT_CYCLE_10: + case TSL2591_PRST_ALS_INT_CYCLE_15: + case TSL2591_PRST_ALS_INT_CYCLE_20: + case TSL2591_PRST_ALS_INT_CYCLE_25: + case TSL2591_PRST_ALS_INT_CYCLE_30: + case TSL2591_PRST_ALS_INT_CYCLE_35: + case TSL2591_PRST_ALS_INT_CYCLE_40: + case TSL2591_PRST_ALS_INT_CYCLE_45: + case TSL2591_PRST_ALS_INT_CYCLE_50: + case TSL2591_PRST_ALS_INT_CYCLE_55: + case TSL2591_PRST_ALS_INT_CYCLE_60: + return 0; + default: + return -EINVAL; + } +} + +static int tsl2591_check_als_valid(struct i2c_client *client) +{ + int ret; + + ret = i2c_smbus_read_byte_data(client, TSL2591_CMD_NOP | TSL2591_STATUS); + if (ret < 0) { + dev_err(&client->dev, "Failed to read register\n"); + return -EINVAL; + } + + return FIELD_GET(TSL2591_STS_ALS_VALID_MASK, ret); +} + +static int tsl2591_wait_adc_complete(struct tsl2591_chip *chip) +{ + struct tsl2591_als_settings settings = chip->als_settings; + struct i2c_client *client = chip->client; + int delay; + int val; + int ret; + + delay = TSL2591_FVAL_TO_MSEC(settings.als_int_time); + if (!delay) + return -EINVAL; + + /* + * Sleep for ALS integration time to allow enough time or an ADC read + * cycle to complete. Check status after delay for ALS valid. + */ + msleep(delay); + + /* Check for status ALS valid flag for up to 100ms */ + ret = readx_poll_timeout(tsl2591_check_als_valid, client, + val, val == TSL2591_STS_VAL_HIGH_MASK, + TSL2591_DELAY_PERIOD_US, + TSL2591_DELAY_PERIOD_US * TSL2591_ALS_STS_VALID_COUNT); + if (ret) + dev_err(&client->dev, "Timed out waiting for valid ALS data\n"); + + return ret; +} + +/* + * tsl2591_read_channel_data - Reads raw channel data and calculates lux + * + * Formula for lux calculation; + * Derived from Adafruit's TSL2591 library + * Link: https://github.com/adafruit/Adafruit_TSL2591_Library + * Counts Per Lux (CPL) = (ATIME_ms * AGAIN) / LUX DF + * lux = ((C0DATA - C1DATA) * (1 - (C1DATA / C0DATA))) / CPL + * + * Scale values to get more representative value of lux i.e. + * lux = ((C0DATA - C1DATA) * (1000 - ((C1DATA * 1000) / C0DATA))) / CPL + * + * Channel 0 = IR + Visible + * Channel 1 = IR only + */ +static int tsl2591_read_channel_data(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2) +{ + struct tsl2591_chip *chip = iio_priv(indio_dev); + struct tsl2591_als_settings *settings = &chip->als_settings; + struct i2c_client *client = chip->client; + u8 als_data[TSL2591_NUM_DATA_REGISTERS]; + int counts_per_lux, int_time_fval, gain_multi, lux; + u16 als_ch0, als_ch1; + int ret; + + ret = tsl2591_wait_adc_complete(chip); + if (ret < 0) { + dev_err(&client->dev, "No data available. Err: %d\n", ret); + return ret; + } + + ret = i2c_smbus_read_i2c_block_data(client, + TSL2591_CMD_NOP | TSL2591_C0_DATAL, + sizeof(als_data), als_data); + if (ret < 0) { + dev_err(&client->dev, "Failed to read data bytes"); + return ret; + } + + als_ch0 = get_unaligned_le16(&als_data[0]); + als_ch1 = get_unaligned_le16(&als_data[2]); + + switch (chan->type) { + case IIO_INTENSITY: + if (chan->channel2 == IIO_MOD_LIGHT_BOTH) + *val = als_ch0; + else if (chan->channel2 == IIO_MOD_LIGHT_IR) + *val = als_ch1; + else + return -EINVAL; + break; + case IIO_LIGHT: + gain_multi = tsl2591_gain_to_multiplier(settings->als_gain); + if (gain_multi < 0) { + dev_err(&client->dev, "Invalid multiplier"); + return gain_multi; + } + + int_time_fval = TSL2591_FVAL_TO_MSEC(settings->als_int_time); + /* Calculate counts per lux value */ + counts_per_lux = (int_time_fval * gain_multi) / TSL2591_LUX_COEFFICIENT; + + dev_dbg(&client->dev, "Counts Per Lux: %d\n", counts_per_lux); + + /* Calculate lux value */ + lux = ((als_ch0 - als_ch1) * + (1000 - ((als_ch1 * 1000) / als_ch0))) / counts_per_lux; + + dev_dbg(&client->dev, "Raw lux calculation: %d\n", lux); + + /* Divide by 1000 to get real lux value before scaling */ + *val = lux / 1000; + + /* Get the decimal part of lux reading */ + *val2 = (lux - (*val * 1000)) * 1000; + + break; + default: + return -EINVAL; + } + + return 0; +} + +static int tsl2591_set_als_gain_int_time(struct tsl2591_chip *chip) +{ + struct tsl2591_als_settings als_settings = chip->als_settings; + struct i2c_client *client = chip->client; + int ret; + + ret = i2c_smbus_write_byte_data(client, + TSL2591_CMD_NOP | TSL2591_CONTROL, + als_settings.als_int_time | als_settings.als_gain); + if (ret) + dev_err(&client->dev, "Failed to set als gain & int time\n"); + + return ret; +} + +static int tsl2591_set_als_lower_threshold(struct tsl2591_chip *chip, + u16 als_lower_threshold) +{ + struct tsl2591_als_settings als_settings = chip->als_settings; + struct i2c_client *client = chip->client; + u16 als_upper_threshold; + u8 als_lower_l; + u8 als_lower_h; + int ret; + + chip->als_settings.als_lower_thresh = als_lower_threshold; + + /* + * Lower threshold should not be greater or equal to upper. + * If this is the case, then assert upper threshold to new lower + * threshold + 1 to avoid ordering issues when setting thresholds. + */ + if (als_lower_threshold >= als_settings.als_upper_thresh) { + als_upper_threshold = als_lower_threshold + 1; + tsl2591_set_als_upper_threshold(chip, als_upper_threshold); + } + + als_lower_l = als_lower_threshold; + als_lower_h = als_lower_threshold >> 8; + + ret = i2c_smbus_write_byte_data(client, + TSL2591_CMD_NOP | TSL2591_AILTL, + als_lower_l); + if (ret) { + dev_err(&client->dev, "Failed to set als lower threshold\n"); + return ret; + } + + ret = i2c_smbus_write_byte_data(client, + TSL2591_CMD_NOP | TSL2591_AILTH, + als_lower_h); + if (ret) { + dev_err(&client->dev, "Failed to set als lower threshold\n"); + return ret; + } + + return 0; +} + +static int tsl2591_set_als_upper_threshold(struct tsl2591_chip *chip, + u16 als_upper_threshold) +{ + struct tsl2591_als_settings als_settings = chip->als_settings; + struct i2c_client *client = chip->client; + u16 als_lower_threshold; + u8 als_upper_l; + u8 als_upper_h; + int ret; + + if (als_upper_threshold > TSL2591_ALS_MAX_VALUE) + return -EINVAL; + + chip->als_settings.als_upper_thresh = als_upper_threshold; + + /* + * Upper threshold should not be less than lower. If this + * is the case, then assert lower threshold to new upper + * threshold - 1 to avoid ordering issues when setting thresholds. + */ + if (als_upper_threshold < als_settings.als_lower_thresh) { + als_lower_threshold = als_upper_threshold - 1; + tsl2591_set_als_lower_threshold(chip, als_lower_threshold); + } + + als_upper_l = als_upper_threshold; + als_upper_h = als_upper_threshold >> 8; + + ret = i2c_smbus_write_byte_data(client, + TSL2591_CMD_NOP | TSL2591_AIHTL, + als_upper_l); + if (ret) { + dev_err(&client->dev, "Failed to set als upper threshold\n"); + return ret; + } + + ret = i2c_smbus_write_byte_data(client, + TSL2591_CMD_NOP | TSL2591_AIHTH, + als_upper_h); + if (ret) { + dev_err(&client->dev, "Failed to set als upper threshold\n"); + return ret; + } + + return 0; +} + +static int tsl2591_set_als_persist_cycle(struct tsl2591_chip *chip, + u8 als_persist) +{ + struct i2c_client *client = chip->client; + int ret; + + ret = i2c_smbus_write_byte_data(client, + TSL2591_CMD_NOP | TSL2591_PERSIST, + als_persist); + if (ret) + dev_err(&client->dev, "Failed to set als persist cycle\n"); + + chip->als_settings.als_persist = als_persist; + + return ret; +} + +static int tsl2591_set_power_state(struct tsl2591_chip *chip, u8 state) +{ + struct i2c_client *client = chip->client; + int ret; + + ret = i2c_smbus_write_byte_data(client, + TSL2591_CMD_NOP | TSL2591_ENABLE, + state); + if (ret) + dev_err(&client->dev, + "Failed to set the power state to %#04x\n", state); + + return ret; +} + +static ssize_t tsl2591_in_illuminance_period_available_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct tsl2591_chip *chip = iio_priv(indio_dev); + + return sysfs_emit(buf, "%s\n", + tsl2591_als_period_list[chip->als_settings.als_int_time]); +} + +static IIO_DEVICE_ATTR_RO(tsl2591_in_illuminance_period_available, 0); + +static struct attribute *tsl2591_event_attrs_ctrl[] = { + &iio_dev_attr_tsl2591_in_illuminance_period_available.dev_attr.attr, + NULL +}; + +static const struct attribute_group tsl2591_event_attribute_group = { + .attrs = tsl2591_event_attrs_ctrl, +}; + +static const struct iio_event_spec tsl2591_events[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_PERIOD) | + BIT(IIO_EV_INFO_ENABLE), + }, +}; + +static const struct iio_chan_spec tsl2591_channels[] = { + { + .type = IIO_INTENSITY, + .modified = 1, + .channel2 = IIO_MOD_LIGHT_IR, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_CALIBSCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_CALIBSCALE) + }, + { + .type = IIO_INTENSITY, + .modified = 1, + .channel2 = IIO_MOD_LIGHT_BOTH, + .event_spec = tsl2591_events, + .num_event_specs = ARRAY_SIZE(tsl2591_events), + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_CALIBSCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_CALIBSCALE) + }, + { + .type = IIO_LIGHT, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_CALIBSCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_CALIBSCALE) + }, +}; + +static int tsl2591_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct tsl2591_chip *chip = iio_priv(indio_dev); + struct i2c_client *client = chip->client; + int ret; + + pm_runtime_get_sync(&client->dev); + + mutex_lock(&chip->als_mutex); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (chan->type != IIO_INTENSITY) { + ret = -EINVAL; + goto err_unlock; + } + + ret = tsl2591_read_channel_data(indio_dev, chan, val, val2); + if (ret < 0) + goto err_unlock; + + ret = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_PROCESSED: + if (chan->type != IIO_LIGHT) { + ret = -EINVAL; + goto err_unlock; + } + + ret = tsl2591_read_channel_data(indio_dev, chan, val, val2); + if (ret < 0) + break; + + ret = IIO_VAL_INT_PLUS_MICRO; + break; + case IIO_CHAN_INFO_INT_TIME: + if (chan->type != IIO_INTENSITY) { + ret = -EINVAL; + goto err_unlock; + } + + *val = TSL2591_FVAL_TO_SEC(chip->als_settings.als_int_time); + ret = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_CALIBSCALE: + if (chan->type != IIO_INTENSITY) { + ret = -EINVAL; + goto err_unlock; + } + + *val = tsl2591_gain_to_multiplier(chip->als_settings.als_gain); + ret = IIO_VAL_INT; + break; + default: + ret = -EINVAL; + break; + } + +err_unlock: + mutex_unlock(&chip->als_mutex); + + pm_runtime_mark_last_busy(&client->dev); + pm_runtime_put_autosuspend(&client->dev); + + return ret; +} + +static int tsl2591_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct tsl2591_chip *chip = iio_priv(indio_dev); + int int_time; + int gain; + int ret; + + mutex_lock(&chip->als_mutex); + + switch (mask) { + case IIO_CHAN_INFO_INT_TIME: + int_time = tsl2591_als_time_to_fval(val); + if (int_time < 0) { + ret = int_time; + goto err_unlock; + } + ret = tsl2591_compatible_int_time(chip, int_time); + if (ret < 0) + goto err_unlock; + + chip->als_settings.als_int_time = int_time; + break; + case IIO_CHAN_INFO_CALIBSCALE: + gain = tsl2591_multiplier_to_gain(val); + if (gain < 0) { + ret = gain; + goto err_unlock; + } + ret = tsl2591_compatible_gain(chip, gain); + if (ret < 0) + goto err_unlock; + + chip->als_settings.als_gain = gain; + break; + default: + ret = -EINVAL; + goto err_unlock; + } + + ret = tsl2591_set_als_gain_int_time(chip); + +err_unlock: + mutex_unlock(&chip->als_mutex); + return ret; +} + +static int tsl2591_read_available(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_INT_TIME: + *length = ARRAY_SIZE(tsl2591_int_time_available); + *vals = tsl2591_int_time_available; + *type = IIO_VAL_INT; + return IIO_AVAIL_LIST; + + case IIO_CHAN_INFO_CALIBSCALE: + *length = ARRAY_SIZE(tsl2591_calibscale_available); + *vals = tsl2591_calibscale_available; + *type = IIO_VAL_INT; + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + +static int tsl2591_read_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, int *val, + int *val2) +{ + struct tsl2591_chip *chip = iio_priv(indio_dev); + struct i2c_client *client = chip->client; + int als_persist, int_time, period; + int ret; + + mutex_lock(&chip->als_mutex); + + switch (info) { + case IIO_EV_INFO_VALUE: + switch (dir) { + case IIO_EV_DIR_RISING: + *val = chip->als_settings.als_upper_thresh; + break; + case IIO_EV_DIR_FALLING: + *val = chip->als_settings.als_lower_thresh; + break; + default: + ret = -EINVAL; + goto err_unlock; + } + ret = IIO_VAL_INT; + break; + case IIO_EV_INFO_PERIOD: + ret = i2c_smbus_read_byte_data(client, + TSL2591_CMD_NOP | TSL2591_PERSIST); + if (ret <= 0 || ret > TSL2591_PRST_ALS_INT_CYCLE_MAX) + goto err_unlock; + + als_persist = tsl2591_persist_cycle_to_lit(ret); + int_time = TSL2591_FVAL_TO_MSEC(chip->als_settings.als_int_time); + period = als_persist * (int_time * MSEC_PER_SEC); + + *val = period / USEC_PER_SEC; + *val2 = period % USEC_PER_SEC; + + ret = IIO_VAL_INT_PLUS_MICRO; + break; + default: + ret = -EINVAL; + break; + } + +err_unlock: + mutex_unlock(&chip->als_mutex); + return ret; +} + +static int tsl2591_write_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, int val, + int val2) +{ + struct tsl2591_chip *chip = iio_priv(indio_dev); + int period, int_time, als_persist; + int ret; + + if (val < 0 || val2 < 0) + return -EINVAL; + + mutex_lock(&chip->als_mutex); + + switch (info) { + case IIO_EV_INFO_VALUE: + if (val > TSL2591_ALS_MAX_VALUE) { + ret = -EINVAL; + goto err_unlock; + } + + switch (dir) { + case IIO_EV_DIR_RISING: + ret = tsl2591_set_als_upper_threshold(chip, val); + if (ret < 0) + goto err_unlock; + break; + case IIO_EV_DIR_FALLING: + ret = tsl2591_set_als_lower_threshold(chip, val); + if (ret < 0) + goto err_unlock; + break; + default: + ret = -EINVAL; + goto err_unlock; + } + break; + case IIO_EV_INFO_PERIOD: + int_time = TSL2591_FVAL_TO_MSEC(chip->als_settings.als_int_time); + + period = ((val * MSEC_PER_SEC) + + (val2 / MSEC_PER_SEC)) / int_time; + + als_persist = tsl2591_persist_lit_to_cycle(period); + if (als_persist < 0) { + ret = -EINVAL; + goto err_unlock; + } + + ret = tsl2591_compatible_als_persist_cycle(chip, als_persist); + if (ret < 0) + goto err_unlock; + + ret = tsl2591_set_als_persist_cycle(chip, als_persist); + if (ret < 0) + goto err_unlock; + break; + default: + ret = -EINVAL; + break; + } + +err_unlock: + mutex_unlock(&chip->als_mutex); + return ret; +} + +static int tsl2591_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct tsl2591_chip *chip = iio_priv(indio_dev); + + return chip->events_enabled; +} + +static int tsl2591_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + int state) +{ + struct tsl2591_chip *chip = iio_priv(indio_dev); + struct i2c_client *client = chip->client; + + if (state && !chip->events_enabled) { + chip->events_enabled = true; + pm_runtime_get_sync(&client->dev); + } else if (!state && chip->events_enabled) { + chip->events_enabled = false; + pm_runtime_mark_last_busy(&client->dev); + pm_runtime_put_autosuspend(&client->dev); + } + + return 0; +} + +static const struct iio_info tsl2591_info = { + .event_attrs = &tsl2591_event_attribute_group, + .read_raw = tsl2591_read_raw, + .write_raw = tsl2591_write_raw, + .read_avail = tsl2591_read_available, + .read_event_value = tsl2591_read_event_value, + .write_event_value = tsl2591_write_event_value, + .read_event_config = tsl2591_read_event_config, + .write_event_config = tsl2591_write_event_config, +}; + +static const struct iio_info tsl2591_info_no_irq = { + .read_raw = tsl2591_read_raw, + .write_raw = tsl2591_write_raw, + .read_avail = tsl2591_read_available, +}; + +static int __maybe_unused tsl2591_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct tsl2591_chip *chip = iio_priv(indio_dev); + int ret; + + mutex_lock(&chip->als_mutex); + ret = tsl2591_set_power_state(chip, TSL2591_PWR_OFF); + mutex_unlock(&chip->als_mutex); + + return ret; +} + +static int __maybe_unused tsl2591_resume(struct device *dev) +{ + int power_state = TSL2591_PWR_ON | TSL2591_ENABLE_ALS; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct tsl2591_chip *chip = iio_priv(indio_dev); + int ret; + + if (chip->events_enabled) + power_state |= TSL2591_ENABLE_ALS_INT; + + mutex_lock(&chip->als_mutex); + ret = tsl2591_set_power_state(chip, power_state); + mutex_unlock(&chip->als_mutex); + + return ret; +} + +static const struct dev_pm_ops tsl2591_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(tsl2591_suspend, tsl2591_resume, NULL) +}; + +static irqreturn_t tsl2591_event_handler(int irq, void *private) +{ + struct iio_dev *dev_info = private; + struct tsl2591_chip *chip = iio_priv(dev_info); + struct i2c_client *client = chip->client; + + if (!chip->events_enabled) + return IRQ_NONE; + + iio_push_event(dev_info, + IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_EITHER), + iio_get_time_ns(dev_info)); + + /* Clear ALS irq */ + i2c_smbus_write_byte(client, TSL2591_CMD_SF_CALS_NPI); + + return IRQ_HANDLED; +} + +static int tsl2591_load_defaults(struct tsl2591_chip *chip) +{ + int ret; + + chip->als_settings.als_int_time = TSL2591_DEFAULT_ALS_INT_TIME; + chip->als_settings.als_gain = TSL2591_DEFAULT_ALS_GAIN; + chip->als_settings.als_lower_thresh = TSL2591_DEFAULT_ALS_LOWER_THRESH; + chip->als_settings.als_upper_thresh = TSL2591_DEFAULT_ALS_UPPER_THRESH; + + ret = tsl2591_set_als_gain_int_time(chip); + if (ret < 0) + return ret; + + ret = tsl2591_set_als_persist_cycle(chip, TSL2591_DEFAULT_ALS_PERSIST); + if (ret < 0) + return ret; + + ret = tsl2591_set_als_lower_threshold(chip, TSL2591_DEFAULT_ALS_LOWER_THRESH); + if (ret < 0) + return ret; + + ret = tsl2591_set_als_upper_threshold(chip, TSL2591_DEFAULT_ALS_UPPER_THRESH); + if (ret < 0) + return ret; + + return 0; +} + +static void tsl2591_chip_off(void *data) +{ + struct iio_dev *indio_dev = data; + struct tsl2591_chip *chip = iio_priv(indio_dev); + struct i2c_client *client = chip->client; + + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + pm_runtime_put_noidle(&client->dev); + + tsl2591_set_power_state(chip, TSL2591_PWR_OFF); +} + +static int tsl2591_probe(struct i2c_client *client) +{ + struct tsl2591_chip *chip; + struct iio_dev *indio_dev; + int ret; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, + "I2C smbus byte data functionality is not supported\n"); + return -EOPNOTSUPP; + } + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); + if (!indio_dev) + return -ENOMEM; + + chip = iio_priv(indio_dev); + chip->client = client; + i2c_set_clientdata(client, indio_dev); + + if (client->irq) { + ret = devm_request_threaded_irq(&client->dev, client->irq, + NULL, tsl2591_event_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "tsl2591_irq", indio_dev); + if (ret) { + dev_err_probe(&client->dev, ret, "IRQ request error\n"); + return -EINVAL; + } + indio_dev->info = &tsl2591_info; + } else { + indio_dev->info = &tsl2591_info_no_irq; + } + + mutex_init(&chip->als_mutex); + + ret = i2c_smbus_read_byte_data(client, + TSL2591_CMD_NOP | TSL2591_DEVICE_ID); + if (ret < 0) { + dev_err(&client->dev, + "Failed to read the device ID register\n"); + return ret; + } + ret = FIELD_GET(TSL2591_DEVICE_ID_MASK, ret); + if (ret != TSL2591_DEVICE_ID_VAL) { + dev_err(&client->dev, "Device ID: %#04x unknown\n", ret); + return -EINVAL; + } + + indio_dev->channels = tsl2591_channels; + indio_dev->num_channels = ARRAY_SIZE(tsl2591_channels); + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->name = chip->client->name; + chip->events_enabled = false; + + pm_runtime_enable(&client->dev); + pm_runtime_set_autosuspend_delay(&client->dev, + TSL2591_POWER_OFF_DELAY_MS); + pm_runtime_use_autosuspend(&client->dev); + + /* + * Add chip off to automatically managed path and disable runtime + * power management. This ensures that the chip power management + * is handled correctly on driver remove. tsl2591_chip_off() must be + * added to the managed path after pm runtime is enabled and before + * any error exit paths are met to ensure we're not left in a state + * of pm runtime not being disabled properly. + */ + ret = devm_add_action_or_reset(&client->dev, tsl2591_chip_off, + indio_dev); + if (ret < 0) + return -EINVAL; + + ret = tsl2591_load_defaults(chip); + if (ret < 0) { + dev_err(&client->dev, "Failed to load sensor defaults\n"); + return -EINVAL; + } + + ret = i2c_smbus_write_byte(client, TSL2591_CMD_SF_CALS_NPI); + if (ret < 0) { + dev_err(&client->dev, "Failed to clear als irq\n"); + return -EINVAL; + } + + return devm_iio_device_register(&client->dev, indio_dev); +} + +static const struct of_device_id tsl2591_of_match[] = { + { .compatible = "amstaos,tsl2591"}, + {} +}; +MODULE_DEVICE_TABLE(of, tsl2591_of_match); + +static struct i2c_driver tsl2591_driver = { + .driver = { + .name = "tsl2591", + .pm = &tsl2591_pm_ops, + .of_match_table = tsl2591_of_match, + }, + .probe_new = tsl2591_probe +}; +module_i2c_driver(tsl2591_driver); + +MODULE_AUTHOR("Joe Sandom <joe.g.sandom@gmail.com>"); +MODULE_DESCRIPTION("TAOS tsl2591 ambient light sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/light/us5182d.c b/drivers/iio/light/us5182d.c index 393f27b75c75..96e4a66ddf28 100644 --- a/drivers/iio/light/us5182d.c +++ b/drivers/iio/light/us5182d.c @@ -367,9 +367,7 @@ static int us5182d_set_power_state(struct us5182d_data *data, bool on) return 0; if (on) { - ret = pm_runtime_get_sync(&data->client->dev); - if (ret < 0) - pm_runtime_put_noidle(&data->client->dev); + ret = pm_runtime_resume_and_get(&data->client->dev); } else { pm_runtime_mark_last_busy(&data->client->dev); ret = pm_runtime_put_autosuspend(&data->client->dev); diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 2f7916f95689..e02e92bc2928 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -413,9 +413,7 @@ static int vcnl4000_set_pm_runtime_state(struct vcnl4000_data *data, bool on) int ret; if (on) { - ret = pm_runtime_get_sync(dev); - if (ret < 0) - pm_runtime_put_noidle(dev); + ret = pm_runtime_resume_and_get(dev); } else { pm_runtime_mark_last_busy(dev); ret = pm_runtime_put_autosuspend(dev); @@ -910,7 +908,7 @@ static irqreturn_t vcnl4010_trigger_handler(int irq, void *p) struct iio_dev *indio_dev = pf->indio_dev; struct vcnl4000_data *data = iio_priv(indio_dev); const unsigned long *active_scan_mask = indio_dev->active_scan_mask; - u16 buffer[8] = {0}; /* 1x16-bit + ts */ + u16 buffer[8] __aligned(8) = {0}; /* 1x16-bit + naturally aligned ts */ bool data_read = false; unsigned long isr; int val = 0; @@ -998,7 +996,8 @@ static int vcnl4010_probe_trigger(struct iio_dev *indio_dev) struct iio_trigger *trigger; trigger = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", - indio_dev->name, indio_dev->id); + indio_dev->name, + iio_device_id(indio_dev)); if (!trigger) return -ENOMEM; diff --git a/drivers/iio/light/vcnl4035.c b/drivers/iio/light/vcnl4035.c index ae87740d9cef..0db306ee910e 100644 --- a/drivers/iio/light/vcnl4035.c +++ b/drivers/iio/light/vcnl4035.c @@ -102,7 +102,8 @@ static irqreturn_t vcnl4035_trigger_consumer_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct vcnl4035_data *data = iio_priv(indio_dev); - u8 buffer[ALIGN(sizeof(u16), sizeof(s64)) + sizeof(s64)]; + /* Ensure naturally aligned timestamp */ + u8 buffer[ALIGN(sizeof(u16), sizeof(s64)) + sizeof(s64)] __aligned(8); int ret; ret = regmap_read(data->regmap, VCNL4035_ALS_DATA, (int *)buffer); @@ -144,9 +145,7 @@ static int vcnl4035_set_pm_runtime_state(struct vcnl4035_data *data, bool on) struct device *dev = &data->client->dev; if (on) { - ret = pm_runtime_get_sync(dev); - if (ret < 0) - pm_runtime_put_noidle(dev); + ret = pm_runtime_resume_and_get(dev); } else { pm_runtime_mark_last_busy(dev); ret = pm_runtime_put_autosuspend(dev); @@ -507,7 +506,7 @@ static int vcnl4035_probe_trigger(struct iio_dev *indio_dev) data->drdy_trigger0 = devm_iio_trigger_alloc( indio_dev->dev.parent, - "%s-dev%d", indio_dev->name, indio_dev->id); + "%s-dev%d", indio_dev->name, iio_device_id(indio_dev)); if (!data->drdy_trigger0) return -ENOMEM; diff --git a/drivers/iio/light/veml6030.c b/drivers/iio/light/veml6030.c index de85c9b30be1..3c937c55a10d 100644 --- a/drivers/iio/light/veml6030.c +++ b/drivers/iio/light/veml6030.c @@ -128,7 +128,7 @@ static ssize_t in_illuminance_period_available_show(struct device *dev, return -EINVAL; } - return snprintf(buf, PAGE_SIZE, "%s\n", period_values[x]); + return sysfs_emit(buf, "%s\n", period_values[x]); } static IIO_DEVICE_ATTR_RO(in_illuminance_period_available, 0); diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c index 24b2f7b1fe44..e54feacfb980 100644 --- a/drivers/iio/magnetometer/ak8974.c +++ b/drivers/iio/magnetometer/ak8974.c @@ -833,8 +833,7 @@ static int ak8974_probe(struct i2c_client *i2c, ak8974->i2c = i2c; mutex_init(&ak8974->lock); - ret = iio_read_mount_matrix(&i2c->dev, "mount-matrix", - &ak8974->orientation); + ret = iio_read_mount_matrix(&i2c->dev, &ak8974->orientation); if (ret) return ret; diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index d988b6ac3659..42b8a2680e3a 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -890,7 +890,7 @@ static int ak8975_probe(struct i2c_client *client, data->reset_gpiod = reset_gpiod; data->eoc_irq = 0; - err = iio_read_mount_matrix(&client->dev, "mount-matrix", &data->orientation); + err = iio_read_mount_matrix(&client->dev, &data->orientation); if (err) return err; diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c index 00f9766bad5c..f96f53175349 100644 --- a/drivers/iio/magnetometer/bmc150_magn.c +++ b/drivers/iio/magnetometer/bmc150_magn.c @@ -138,8 +138,11 @@ struct bmc150_magn_data { struct regmap *regmap; struct regulator_bulk_data regulators[2]; struct iio_mount_matrix orientation; - /* 4 x 32 bits for x, y z, 4 bytes align, 64 bits timestamp */ - s32 buffer[6]; + /* Ensure timestamp is naturally aligned */ + struct { + s32 chans[3]; + s64 timestamp __aligned(8); + } scan; struct iio_trigger *dready_trig; bool dready_trigger_on; int max_odr; @@ -262,7 +265,7 @@ static int bmc150_magn_set_power_state(struct bmc150_magn_data *data, bool on) int ret; if (on) { - ret = pm_runtime_get_sync(data->dev); + ret = pm_runtime_resume_and_get(data->dev); } else { pm_runtime_mark_last_busy(data->dev); ret = pm_runtime_put_autosuspend(data->dev); @@ -271,9 +274,6 @@ static int bmc150_magn_set_power_state(struct bmc150_magn_data *data, bool on) if (ret < 0) { dev_err(data->dev, "failed to change power state to %d\n", on); - if (on) - pm_runtime_put_noidle(data->dev); - return ret; } #endif @@ -675,11 +675,11 @@ static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p) int ret; mutex_lock(&data->mutex); - ret = bmc150_magn_read_xyz(data, data->buffer); + ret = bmc150_magn_read_xyz(data, data->scan.chans); if (ret < 0) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, pf->timestamp); err: @@ -890,8 +890,7 @@ int bmc150_magn_probe(struct device *dev, struct regmap *regmap, if (ret) return dev_err_probe(dev, ret, "failed to get regulators\n"); - ret = iio_read_mount_matrix(dev, "mount-matrix", - &data->orientation); + ret = iio_read_mount_matrix(dev, &data->orientation); if (ret) return ret; @@ -915,7 +914,7 @@ int bmc150_magn_probe(struct device *dev, struct regmap *regmap, data->dready_trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!data->dready_trig) { ret = -ENOMEM; dev_err(dev, "iio trigger alloc failed\n"); @@ -963,12 +962,14 @@ int bmc150_magn_probe(struct device *dev, struct regmap *regmap, ret = iio_device_register(indio_dev); if (ret < 0) { dev_err(dev, "unable to register iio device\n"); - goto err_buffer_cleanup; + goto err_disable_runtime_pm; } dev_dbg(dev, "Registered device %s\n", name); return 0; +err_disable_runtime_pm: + pm_runtime_disable(dev); err_buffer_cleanup: iio_triggered_buffer_cleanup(indio_dev); err_free_irq: @@ -992,7 +993,6 @@ int bmc150_magn_remove(struct device *dev) pm_runtime_disable(dev); pm_runtime_set_suspended(dev); - pm_runtime_put_noidle(dev); iio_triggered_buffer_cleanup(indio_dev); diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c index b78691523dd4..e85a3a8eea90 100644 --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c @@ -6,13 +6,9 @@ #include <linux/device.h> #include <linux/platform_device.h> #include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/slab.h> -#include <linux/delay.h> +#include <linux/mod_devicetable.h> #include <linux/hid-sensor-hub.h> #include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> #include <linux/iio/buffer.h> #include "../common/hid-sensors/hid-sensor-trigger.h" @@ -587,3 +583,4 @@ module_platform_driver(hid_magn_3d_platform_driver); MODULE_DESCRIPTION("HID Sensor Magnetometer 3D"); MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(IIO_HID); diff --git a/drivers/iio/magnetometer/hmc5843.h b/drivers/iio/magnetometer/hmc5843.h index 3f6c0b662941..242f742f2643 100644 --- a/drivers/iio/magnetometer/hmc5843.h +++ b/drivers/iio/magnetometer/hmc5843.h @@ -33,7 +33,8 @@ enum hmc5843_ids { * @lock: update and read regmap data * @regmap: hardware access register maps * @variant: describe chip variants - * @buffer: 3x 16-bit channels + padding + 64-bit timestamp + * @scan: buffer to pack data for passing to + * iio_push_to_buffers_with_timestamp() */ struct hmc5843_data { struct device *dev; @@ -41,7 +42,10 @@ struct hmc5843_data { struct regmap *regmap; const struct hmc5843_chip_info *variant; struct iio_mount_matrix orientation; - __be16 buffer[8]; + struct { + __be16 chans[3]; + s64 timestamp __aligned(8); + } scan; }; int hmc5843_common_probe(struct device *dev, struct regmap *regmap, diff --git a/drivers/iio/magnetometer/hmc5843_core.c b/drivers/iio/magnetometer/hmc5843_core.c index 780faea61d82..cf62057480cf 100644 --- a/drivers/iio/magnetometer/hmc5843_core.c +++ b/drivers/iio/magnetometer/hmc5843_core.c @@ -446,13 +446,13 @@ static irqreturn_t hmc5843_trigger_handler(int irq, void *p) } ret = regmap_bulk_read(data->regmap, HMC5843_DATA_OUT_MSB_REGS, - data->buffer, 3 * sizeof(__be16)); + data->scan.chans, sizeof(data->scan.chans)); mutex_unlock(&data->lock); if (ret < 0) goto done; - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, iio_get_time_ns(indio_dev)); done: @@ -637,8 +637,7 @@ int hmc5843_common_probe(struct device *dev, struct regmap *regmap, data->variant = &hmc5843_chip_info_tbl[id]; mutex_init(&data->lock); - ret = iio_read_mount_matrix(dev, "mount-matrix", - &data->orientation); + ret = iio_read_mount_matrix(dev, &data->orientation); if (ret) return ret; diff --git a/drivers/iio/magnetometer/rm3100-core.c b/drivers/iio/magnetometer/rm3100-core.c index dd811da9cb6d..13914273c999 100644 --- a/drivers/iio/magnetometer/rm3100-core.c +++ b/drivers/iio/magnetometer/rm3100-core.c @@ -78,7 +78,8 @@ struct rm3100_data { bool use_interrupt; int conversion_time; int scale; - u8 buffer[RM3100_SCAN_BYTES]; + /* Ensure naturally aligned timestamp */ + u8 buffer[RM3100_SCAN_BYTES] __aligned(8); struct iio_trigger *drdy_trig; /* @@ -575,7 +576,7 @@ int rm3100_common_probe(struct device *dev, struct regmap *regmap, int irq) data->drdy_trig = devm_iio_trigger_alloc(dev, "%s-drdy%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!data->drdy_trig) return -ENOMEM; diff --git a/drivers/iio/magnetometer/st_magn.h b/drivers/iio/magnetometer/st_magn.h index 7ba6a6ba5c58..fb6c906c4c0c 100644 --- a/drivers/iio/magnetometer/st_magn.h +++ b/drivers/iio/magnetometer/st_magn.h @@ -23,10 +23,6 @@ #define LSM9DS1_MAGN_DEV_NAME "lsm9ds1_magn" #define IIS2MDC_MAGN_DEV_NAME "iis2mdc" -const struct st_sensor_settings *st_magn_get_settings(const char *name); -int st_magn_common_probe(struct iio_dev *indio_dev); -void st_magn_common_remove(struct iio_dev *indio_dev); - #ifdef CONFIG_IIO_BUFFER int st_magn_allocate_ring(struct iio_dev *indio_dev); void st_magn_deallocate_ring(struct iio_dev *indio_dev); diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c index 71faebd07feb..0048c3cd36ee 100644 --- a/drivers/iio/magnetometer/st_magn_core.c +++ b/drivers/iio/magnetometer/st_magn_core.c @@ -33,6 +33,7 @@ /* FULLSCALE */ #define ST_MAGN_FS_AVL_1300MG 1300 #define ST_MAGN_FS_AVL_1900MG 1900 +#define ST_MAGN_FS_AVL_2000MG 2000 #define ST_MAGN_FS_AVL_2500MG 2500 #define ST_MAGN_FS_AVL_4000MG 4000 #define ST_MAGN_FS_AVL_4700MG 4700 @@ -53,51 +54,95 @@ #define ST_MAGN_3_OUT_Y_L_ADDR 0x6a #define ST_MAGN_3_OUT_Z_L_ADDR 0x6c +/* Special L addresses for sensor 4 */ +#define ST_MAGN_4_OUT_X_L_ADDR 0x08 +#define ST_MAGN_4_OUT_Y_L_ADDR 0x0a +#define ST_MAGN_4_OUT_Z_L_ADDR 0x0c + +static const struct iio_mount_matrix * +st_magn_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct st_sensor_data *mdata = iio_priv(indio_dev); + + return &mdata->mount_matrix; +} + +static const struct iio_chan_spec_ext_info st_magn_mount_matrix_ext_info[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_magn_get_mount_matrix), + { } +}; + static const struct iio_chan_spec st_magn_16bit_channels[] = { - ST_SENSORS_LSM_CHANNELS(IIO_MAGN, + ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_BE, 16, 16, - ST_MAGN_DEFAULT_OUT_X_H_ADDR), - ST_SENSORS_LSM_CHANNELS(IIO_MAGN, + ST_MAGN_DEFAULT_OUT_X_H_ADDR, + st_magn_mount_matrix_ext_info), + ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_BE, 16, 16, - ST_MAGN_DEFAULT_OUT_Y_H_ADDR), - ST_SENSORS_LSM_CHANNELS(IIO_MAGN, + ST_MAGN_DEFAULT_OUT_Y_H_ADDR, + st_magn_mount_matrix_ext_info), + ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_BE, 16, 16, - ST_MAGN_DEFAULT_OUT_Z_H_ADDR), + ST_MAGN_DEFAULT_OUT_Z_H_ADDR, + st_magn_mount_matrix_ext_info), IIO_CHAN_SOFT_TIMESTAMP(3) }; static const struct iio_chan_spec st_magn_2_16bit_channels[] = { - ST_SENSORS_LSM_CHANNELS(IIO_MAGN, + ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16, - ST_MAGN_2_OUT_X_L_ADDR), - ST_SENSORS_LSM_CHANNELS(IIO_MAGN, + ST_MAGN_2_OUT_X_L_ADDR, + st_magn_mount_matrix_ext_info), + ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16, - ST_MAGN_2_OUT_Y_L_ADDR), - ST_SENSORS_LSM_CHANNELS(IIO_MAGN, + ST_MAGN_2_OUT_Y_L_ADDR, + st_magn_mount_matrix_ext_info), + ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16, - ST_MAGN_2_OUT_Z_L_ADDR), + ST_MAGN_2_OUT_Z_L_ADDR, + st_magn_mount_matrix_ext_info), IIO_CHAN_SOFT_TIMESTAMP(3) }; static const struct iio_chan_spec st_magn_3_16bit_channels[] = { + ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN, + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16, + ST_MAGN_3_OUT_X_L_ADDR, + st_magn_mount_matrix_ext_info), + ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN, + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16, + ST_MAGN_3_OUT_Y_L_ADDR, + st_magn_mount_matrix_ext_info), + ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN, + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16, + ST_MAGN_3_OUT_Z_L_ADDR, + st_magn_mount_matrix_ext_info), + IIO_CHAN_SOFT_TIMESTAMP(3) +}; + +static const struct iio_chan_spec st_magn_4_16bit_channels[] = { ST_SENSORS_LSM_CHANNELS(IIO_MAGN, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16, - ST_MAGN_3_OUT_X_L_ADDR), + ST_MAGN_4_OUT_X_L_ADDR), ST_SENSORS_LSM_CHANNELS(IIO_MAGN, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16, - ST_MAGN_3_OUT_Y_L_ADDR), + ST_MAGN_4_OUT_Y_L_ADDR), ST_SENSORS_LSM_CHANNELS(IIO_MAGN, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16, - ST_MAGN_3_OUT_Z_L_ADDR), + ST_MAGN_4_OUT_Z_L_ADDR), IIO_CHAN_SOFT_TIMESTAMP(3) }; @@ -381,6 +426,87 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = { .multi_read_bit = false, .bootime = 2, }, + { + .wai = 0x49, + .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, + .sensors_supported = { + [0] = LSM9DS0_IMU_DEV_NAME, + }, + .ch = (struct iio_chan_spec *)st_magn_4_16bit_channels, + .odr = { + .addr = 0x24, + .mask = GENMASK(4, 2), + .odr_avl = { + { 3, 0x00, }, + { 6, 0x01, }, + { 12, 0x02, }, + { 25, 0x03, }, + { 50, 0x04, }, + { 100, 0x05, }, + }, + }, + .pw = { + .addr = 0x26, + .mask = GENMASK(1, 0), + .value_on = 0x00, + .value_off = 0x03, + }, + .fs = { + .addr = 0x25, + .mask = GENMASK(6, 5), + .fs_avl = { + [0] = { + .num = ST_MAGN_FS_AVL_2000MG, + .value = 0x00, + .gain = 73, + }, + [1] = { + .num = ST_MAGN_FS_AVL_4000MG, + .value = 0x01, + .gain = 146, + }, + [2] = { + .num = ST_MAGN_FS_AVL_8000MG, + .value = 0x02, + .gain = 292, + }, + [3] = { + .num = ST_MAGN_FS_AVL_12000MG, + .value = 0x03, + .gain = 438, + }, + }, + }, + .bdu = { + .addr = 0x20, + .mask = BIT(3), + }, + .drdy_irq = { + .int1 = { + .addr = 0x22, + .mask = BIT(1), + }, + .int2 = { + .addr = 0x23, + .mask = BIT(2), + }, + .stat_drdy = { + .addr = 0x07, + .mask = GENMASK(2, 0), + }, + }, + .sim = { + .addr = 0x21, + .value = BIT(0), + }, + .multi_read_bit = true, + .bootime = 2, + }, +}; + +/* Default magn DRDY is available on INT2 pin */ +static const struct st_sensors_platform_data default_magn_pdata = { + .drdy_int_pin = 2, }; static int st_magn_read_raw(struct iio_dev *indio_dev, @@ -490,33 +616,37 @@ EXPORT_SYMBOL(st_magn_get_settings); int st_magn_common_probe(struct iio_dev *indio_dev) { struct st_sensor_data *mdata = iio_priv(indio_dev); + struct st_sensors_platform_data *pdata = dev_get_platdata(mdata->dev); int err; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &magn_info; - err = st_sensors_power_enable(indio_dev); - if (err) - return err; - err = st_sensors_verify_id(indio_dev); if (err < 0) - goto st_magn_power_off; + return err; mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS; indio_dev->channels = mdata->sensor_settings->ch; indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; + err = iio_read_mount_matrix(mdata->dev, &mdata->mount_matrix); + if (err) + return err; + mdata->current_fullscale = &mdata->sensor_settings->fs.fs_avl[0]; mdata->odr = mdata->sensor_settings->odr.odr_avl[0].hz; - err = st_sensors_init_sensor(indio_dev, NULL); + if (!pdata) + pdata = (struct st_sensors_platform_data *)&default_magn_pdata; + + err = st_sensors_init_sensor(indio_dev, pdata); if (err < 0) - goto st_magn_power_off; + return err; err = st_magn_allocate_ring(indio_dev); if (err < 0) - goto st_magn_power_off; + return err; if (mdata->irq > 0) { err = st_sensors_allocate_trigger(indio_dev, @@ -539,9 +669,6 @@ st_magn_device_register_error: st_sensors_deallocate_trigger(indio_dev); st_magn_probe_trigger_error: st_magn_deallocate_ring(indio_dev); -st_magn_power_off: - st_sensors_power_disable(indio_dev); - return err; } EXPORT_SYMBOL(st_magn_common_probe); @@ -550,8 +677,6 @@ void st_magn_common_remove(struct iio_dev *indio_dev) { struct st_sensor_data *mdata = iio_priv(indio_dev); - st_sensors_power_disable(indio_dev); - iio_device_unregister(indio_dev); if (mdata->irq > 0) st_sensors_deallocate_trigger(indio_dev); diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c index 36f4e7b53b24..3e23c117de8e 100644 --- a/drivers/iio/magnetometer/st_magn_i2c.c +++ b/drivers/iio/magnetometer/st_magn_i2c.c @@ -82,16 +82,28 @@ static int st_magn_i2c_probe(struct i2c_client *client, if (err < 0) return err; + err = st_sensors_power_enable(indio_dev); + if (err) + return err; + err = st_magn_common_probe(indio_dev); if (err < 0) - return err; + goto st_magn_power_off; return 0; + +st_magn_power_off: + st_sensors_power_disable(indio_dev); + + return err; } static int st_magn_i2c_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); + + st_sensors_power_disable(indio_dev); + st_magn_common_remove(indio_dev); return 0; diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c index 0e2323dfc687..03c0a737aba6 100644 --- a/drivers/iio/magnetometer/st_magn_spi.c +++ b/drivers/iio/magnetometer/st_magn_spi.c @@ -76,16 +76,28 @@ static int st_magn_spi_probe(struct spi_device *spi) if (err < 0) return err; + err = st_sensors_power_enable(indio_dev); + if (err) + return err; + err = st_magn_common_probe(indio_dev); if (err < 0) - return err; + goto st_magn_power_off; return 0; + +st_magn_power_off: + st_sensors_power_disable(indio_dev); + + return err; } static int st_magn_spi_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); + + st_sensors_power_disable(indio_dev); + st_magn_common_remove(indio_dev); return 0; diff --git a/drivers/iio/magnetometer/yamaha-yas530.c b/drivers/iio/magnetometer/yamaha-yas530.c index 2f2f8cb3c26c..9ff7b0e56cf6 100644 --- a/drivers/iio/magnetometer/yamaha-yas530.c +++ b/drivers/iio/magnetometer/yamaha-yas530.c @@ -831,7 +831,7 @@ static int yas5xx_probe(struct i2c_client *i2c, yas5xx->dev = dev; mutex_init(&yas5xx->lock); - ret = iio_read_mount_matrix(dev, "mount-matrix", &yas5xx->orientation); + ret = iio_read_mount_matrix(dev, &yas5xx->orientation); if (ret) return ret; diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c index 7af48d336285..c0079e2c8807 100644 --- a/drivers/iio/orientation/hid-sensor-incl-3d.c +++ b/drivers/iio/orientation/hid-sensor-incl-3d.c @@ -7,13 +7,10 @@ #include <linux/device.h> #include <linux/platform_device.h> #include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/irq.h> +#include <linux/mod_devicetable.h> #include <linux/slab.h> -#include <linux/delay.h> #include <linux/hid-sensor-hub.h> #include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> #include <linux/iio/buffer.h> #include "../common/hid-sensors/hid-sensor-trigger.h" @@ -425,3 +422,4 @@ module_platform_driver(hid_incl_3d_platform_driver); MODULE_DESCRIPTION("HID Sensor Inclinometer 3D"); MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(IIO_HID); diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c index cf7f57a47681..a033699910e8 100644 --- a/drivers/iio/orientation/hid-sensor-rotation.c +++ b/drivers/iio/orientation/hid-sensor-rotation.c @@ -7,9 +7,7 @@ #include <linux/device.h> #include <linux/platform_device.h> #include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/slab.h> +#include <linux/mod_devicetable.h> #include <linux/hid-sensor-hub.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> @@ -373,3 +371,4 @@ module_platform_driver(hid_dev_rot_platform_driver); MODULE_DESCRIPTION("HID Sensor Device Rotation"); MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(IIO_HID); diff --git a/drivers/iio/position/hid-sensor-custom-intel-hinge.c b/drivers/iio/position/hid-sensor-custom-intel-hinge.c index fd77e7ee87f3..07c30d217255 100644 --- a/drivers/iio/position/hid-sensor-custom-intel-hinge.c +++ b/drivers/iio/position/hid-sensor-custom-intel-hinge.c @@ -7,6 +7,8 @@ #include <linux/iio/buffer.h> #include <linux/iio/iio.h> #include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> #include "../common/hid-sensors/hid-sensor-trigger.h" @@ -303,7 +305,6 @@ static int hid_hinge_probe(struct platform_device *pdev) return ret; } - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &hinge_info; indio_dev->name = "hinge"; indio_dev->modes = INDIO_DIRECT_MODE; @@ -377,3 +378,4 @@ module_platform_driver(hid_hinge_platform_driver); MODULE_DESCRIPTION("HID Sensor INTEL Hinge"); MODULE_AUTHOR("Ye Xiang <xiang.ye@intel.com>"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(IIO_HID); diff --git a/drivers/iio/potentiostat/lmp91000.c b/drivers/iio/potentiostat/lmp91000.c index 8a9c576616ee..ed30bdaa10ec 100644 --- a/drivers/iio/potentiostat/lmp91000.c +++ b/drivers/iio/potentiostat/lmp91000.c @@ -71,8 +71,8 @@ struct lmp91000_data { struct completion completion; u8 chan_select; - - u32 buffer[4]; /* 64-bit data + 64-bit timestamp */ + /* 64-bit data + 64-bit naturally aligned timestamp */ + u32 buffer[4] __aligned(8); }; static const struct iio_chan_spec lmp91000_channels[] = { @@ -323,7 +323,8 @@ static int lmp91000_probe(struct i2c_client *client, } data->trig = devm_iio_trigger_alloc(dev, "%s-mux%d", - indio_dev->name, indio_dev->id); + indio_dev->name, + iio_device_id(indio_dev)); if (!data->trig) { dev_err(dev, "cannot allocate iio trigger.\n"); return -ENOMEM; diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c index c416d261e3e3..10c52b8df2ba 100644 --- a/drivers/iio/pressure/hid-sensor-press.c +++ b/drivers/iio/pressure/hid-sensor-press.c @@ -6,13 +6,10 @@ #include <linux/device.h> #include <linux/platform_device.h> #include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/irq.h> +#include <linux/mod_devicetable.h> #include <linux/slab.h> -#include <linux/delay.h> #include <linux/hid-sensor-hub.h> #include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> #include <linux/iio/buffer.h> #include "../common/hid-sensors/hid-sensor-trigger.h" @@ -357,3 +354,4 @@ module_platform_driver(hid_press_platform_driver); MODULE_DESCRIPTION("HID Sensor Pressure"); MODULE_AUTHOR("Archana Patni <archana.patni@intel.com>"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(IIO_HID); diff --git a/drivers/iio/pressure/icp10100.c b/drivers/iio/pressure/icp10100.c index 48759fc4bf18..af4621eaa6b5 100644 --- a/drivers/iio/pressure/icp10100.c +++ b/drivers/iio/pressure/icp10100.c @@ -250,7 +250,9 @@ static int icp10100_get_measures(struct icp10100_state *st, __be16 measures[3]; int ret; - pm_runtime_get_sync(&st->client->dev); + ret = pm_runtime_resume_and_get(&st->client->dev); + if (ret < 0) + return ret; mutex_lock(&st->lock); cmd = &icp10100_cmd_measure[st->mode]; @@ -525,7 +527,6 @@ static void icp10100_pm_disable(void *data) { struct device *dev = data; - pm_runtime_put_sync_suspend(dev); pm_runtime_disable(dev); } diff --git a/drivers/iio/pressure/st_pressure.h b/drivers/iio/pressure/st_pressure.h index 5c746ff6087e..9417b3bd7513 100644 --- a/drivers/iio/pressure/st_pressure.h +++ b/drivers/iio/pressure/st_pressure.h @@ -41,10 +41,6 @@ static __maybe_unused const struct st_sensors_platform_data default_press_pdata .drdy_int_pin = 1, }; -const struct st_sensor_settings *st_press_get_settings(const char *name); -int st_press_common_probe(struct iio_dev *indio_dev); -void st_press_common_remove(struct iio_dev *indio_dev); - #ifdef CONFIG_IIO_BUFFER int st_press_allocate_ring(struct iio_dev *indio_dev); void st_press_deallocate_ring(struct iio_dev *indio_dev); diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index 789a2928504a..7912b5a68395 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -689,13 +689,9 @@ int st_press_common_probe(struct iio_dev *indio_dev) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &press_info; - err = st_sensors_power_enable(indio_dev); - if (err) - return err; - err = st_sensors_verify_id(indio_dev); if (err < 0) - goto st_press_power_off; + return err; /* * Skip timestamping channel while declaring available channels to @@ -718,11 +714,11 @@ int st_press_common_probe(struct iio_dev *indio_dev) err = st_sensors_init_sensor(indio_dev, pdata); if (err < 0) - goto st_press_power_off; + return err; err = st_press_allocate_ring(indio_dev); if (err < 0) - goto st_press_power_off; + return err; if (press_data->irq > 0) { err = st_sensors_allocate_trigger(indio_dev, @@ -745,9 +741,6 @@ st_press_device_register_error: st_sensors_deallocate_trigger(indio_dev); st_press_probe_trigger_error: st_press_deallocate_ring(indio_dev); -st_press_power_off: - st_sensors_power_disable(indio_dev); - return err; } EXPORT_SYMBOL(st_press_common_probe); @@ -756,8 +749,6 @@ void st_press_common_remove(struct iio_dev *indio_dev) { struct st_sensor_data *press_data = iio_priv(indio_dev); - st_sensors_power_disable(indio_dev); - iio_device_unregister(indio_dev); if (press_data->irq > 0) st_sensors_deallocate_trigger(indio_dev); diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c index 09c6903f99b8..f0a5af314ceb 100644 --- a/drivers/iio/pressure/st_pressure_i2c.c +++ b/drivers/iio/pressure/st_pressure_i2c.c @@ -98,16 +98,29 @@ static int st_press_i2c_probe(struct i2c_client *client, if (ret < 0) return ret; + ret = st_sensors_power_enable(indio_dev); + if (ret) + return ret; + ret = st_press_common_probe(indio_dev); if (ret < 0) - return ret; + goto st_press_power_off; return 0; + +st_press_power_off: + st_sensors_power_disable(indio_dev); + + return ret; } static int st_press_i2c_remove(struct i2c_client *client) { - st_press_common_remove(i2c_get_clientdata(client)); + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + st_sensors_power_disable(indio_dev); + + st_press_common_remove(indio_dev); return 0; } diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c index b5ee3ec2764f..b48cf7d01cd7 100644 --- a/drivers/iio/pressure/st_pressure_spi.c +++ b/drivers/iio/pressure/st_pressure_spi.c @@ -82,16 +82,29 @@ static int st_press_spi_probe(struct spi_device *spi) if (err < 0) return err; + err = st_sensors_power_enable(indio_dev); + if (err) + return err; + err = st_press_common_probe(indio_dev); if (err < 0) - return err; + goto st_press_power_off; return 0; + +st_press_power_off: + st_sensors_power_disable(indio_dev); + + return err; } static int st_press_spi_remove(struct spi_device *spi) { - st_press_common_remove(spi_get_drvdata(spi)); + struct iio_dev *indio_dev = spi_get_drvdata(spi); + + st_sensors_power_disable(indio_dev); + + st_press_common_remove(indio_dev); return 0; } diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c index a93411216aee..89295c90f801 100644 --- a/drivers/iio/pressure/zpa2326.c +++ b/drivers/iio/pressure/zpa2326.c @@ -1408,7 +1408,8 @@ static int zpa2326_init_managed_trigger(struct device *parent, return 0; trigger = devm_iio_trigger_alloc(parent, "%s-dev%d", - indio_dev->name, indio_dev->id); + indio_dev->name, + iio_device_id(indio_dev)); if (!trigger) return -ENOMEM; diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c index edc4a35ae66d..3797a8f54276 100644 --- a/drivers/iio/proximity/as3935.c +++ b/drivers/iio/proximity/as3935.c @@ -59,7 +59,11 @@ struct as3935_state { unsigned long noise_tripped; u32 tune_cap; u32 nflwdth_reg; - u8 buffer[16]; /* 8-bit data + 56-bit padding + 64-bit timestamp */ + /* Ensure timestamp is naturally aligned */ + struct { + u8 chan; + s64 timestamp __aligned(8); + } scan; u8 buf[2] ____cacheline_aligned; }; @@ -225,8 +229,8 @@ static irqreturn_t as3935_trigger_handler(int irq, void *private) if (ret) goto err_read; - st->buffer[0] = val & AS3935_DATA_MASK; - iio_push_to_buffers_with_timestamp(indio_dev, &st->buffer, + st->scan.chan = val & AS3935_DATA_MASK; + iio_push_to_buffers_with_timestamp(indio_dev, &st->scan, iio_get_time_ns(indio_dev)); err_read: iio_trigger_notify_done(indio_dev->trig); @@ -404,7 +408,8 @@ static int as3935_probe(struct spi_device *spi) indio_dev->info = &as3935_info; trig = devm_iio_trigger_alloc(dev, "%s-dev%d", - indio_dev->name, indio_dev->id); + indio_dev->name, + iio_device_id(indio_dev)); if (!trig) return -ENOMEM; diff --git a/drivers/iio/proximity/isl29501.c b/drivers/iio/proximity/isl29501.c index 90e76451c972..5b6ea783795d 100644 --- a/drivers/iio/proximity/isl29501.c +++ b/drivers/iio/proximity/isl29501.c @@ -938,7 +938,7 @@ static irqreturn_t isl29501_trigger_handler(int irq, void *p) struct iio_dev *indio_dev = pf->indio_dev; struct isl29501_private *isl29501 = iio_priv(indio_dev); const unsigned long *active_mask = indio_dev->active_scan_mask; - u32 buffer[4] = {}; /* 1x16-bit + ts */ + u32 buffer[4] __aligned(8) = {}; /* 1x16-bit + naturally aligned ts */ if (test_bit(ISL29501_DISTANCE_SCAN_INDEX, active_mask)) isl29501_register_read(isl29501, REG_DISTANCE, buffer); diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c index cc206bfa09c7..27026c060ab9 100644 --- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c +++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c @@ -44,7 +44,11 @@ struct lidar_data { int (*xfer)(struct lidar_data *data, u8 reg, u8 *val, int len); int i2c_enabled; - u16 buffer[8]; /* 2 byte distance + 8 byte timestamp */ + /* Ensure timestamp is naturally aligned */ + struct { + u16 chan; + s64 timestamp __aligned(8); + } scan; }; static const struct iio_chan_spec lidar_channels[] = { @@ -154,7 +158,9 @@ static int lidar_get_measurement(struct lidar_data *data, u16 *reg) int tries = 10; int ret; - pm_runtime_get_sync(&client->dev); + ret = pm_runtime_resume_and_get(&client->dev); + if (ret < 0) + return ret; /* start sample */ ret = lidar_write_control(data, LIDAR_REG_CONTROL_ACQUIRE); @@ -230,9 +236,9 @@ static irqreturn_t lidar_trigger_handler(int irq, void *private) struct lidar_data *data = iio_priv(indio_dev); int ret; - ret = lidar_get_measurement(data, data->buffer); + ret = lidar_get_measurement(data, &data->scan.chan); if (!ret) { - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, iio_get_time_ns(indio_dev)); } else if (ret != -EINVAL) { dev_err(&data->client->dev, "cannot read LIDAR measurement"); diff --git a/drivers/iio/proximity/srf04.c b/drivers/iio/proximity/srf04.c index 420c37c72de4..fe88b2bb60bc 100644 --- a/drivers/iio/proximity/srf04.c +++ b/drivers/iio/proximity/srf04.c @@ -100,9 +100,11 @@ static int srf04_read(struct srf04_data *data) u64 dt_ns; u32 time_ns, distance_mm; - if (data->gpiod_power) - pm_runtime_get_sync(data->dev); - + if (data->gpiod_power) { + ret = pm_runtime_resume_and_get(data->dev); + if (ret < 0) + return ret; + } /* * just one read-echo-cycle can take place at a time * ==> lock against concurrent reading calls diff --git a/drivers/iio/proximity/srf08.c b/drivers/iio/proximity/srf08.c index 70beac5c9c1d..9b0886760f76 100644 --- a/drivers/iio/proximity/srf08.c +++ b/drivers/iio/proximity/srf08.c @@ -63,11 +63,11 @@ struct srf08_data { int range_mm; struct mutex lock; - /* - * triggered buffer - * 1x16-bit channel + 3x16 padding + 4x16 timestamp - */ - s16 buffer[8]; + /* Ensure timestamp is naturally aligned */ + struct { + s16 chan; + s64 timestamp __aligned(8); + } scan; /* Sensor-Type */ enum srf08_sensor_type sensor_type; @@ -190,9 +190,9 @@ static irqreturn_t srf08_trigger_handler(int irq, void *p) mutex_lock(&data->lock); - data->buffer[0] = sensor_data; + data->scan.chan = sensor_data; iio_push_to_buffers_with_timestamp(indio_dev, - data->buffer, pf->timestamp); + &data->scan, pf->timestamp); mutex_unlock(&data->lock); err: diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index 327ebb7ddbb9..175f3b7c61d7 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -1473,7 +1473,7 @@ static int sx9310_probe(struct i2c_client *client) data->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!data->trig) return -ENOMEM; diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index a87f4a8e4327..3e4ddb2e8c2b 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -946,7 +946,7 @@ static int sx9500_probe(struct i2c_client *client, return ret; data->trig = devm_iio_trigger_alloc(&client->dev, - "%s-dev%d", indio_dev->name, indio_dev->id); + "%s-dev%d", indio_dev->name, iio_device_id(indio_dev)); if (!data->trig) return -ENOMEM; diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig index 4df60082c1fa..f20ae3c963cb 100644 --- a/drivers/iio/temperature/Kconfig +++ b/drivers/iio/temperature/Kconfig @@ -96,6 +96,16 @@ config TMP007 This driver can also be built as a module. If so, the module will be called tmp007. +config TMP117 + tristate "TMP117 Digital temperature sensor with integrated NV memory" + depends on I2C + help + If you say yes here you get support for the Texas Instruments + TMP117 Digital temperature sensor with integrated NV memory. + + This driver can also be built as a module. If so, the module will + be called tmp117. + config TSYS01 tristate "Measurement Specialties TSYS01 temperature sensor using I2C bus connection" depends on I2C diff --git a/drivers/iio/temperature/Makefile b/drivers/iio/temperature/Makefile index 90c113115422..e3392c4b29b4 100644 --- a/drivers/iio/temperature/Makefile +++ b/drivers/iio/temperature/Makefile @@ -12,5 +12,6 @@ obj-$(CONFIG_MLX90614) += mlx90614.o obj-$(CONFIG_MLX90632) += mlx90632.o obj-$(CONFIG_TMP006) += tmp006.o obj-$(CONFIG_TMP007) += tmp007.o +obj-$(CONFIG_TMP117) += tmp117.o obj-$(CONFIG_TSYS01) += tsys01.o obj-$(CONFIG_TSYS02D) += tsys02d.o diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c index dc534ed784c3..d40f235af1d4 100644 --- a/drivers/iio/temperature/hid-sensor-temperature.c +++ b/drivers/iio/temperature/hid-sensor-temperature.c @@ -8,6 +8,7 @@ #include <linux/iio/buffer.h> #include <linux/iio/iio.h> #include <linux/module.h> +#include <linux/mod_devicetable.h> #include <linux/platform_device.h> #include "../common/hid-sensors/hid-sensor-trigger.h" @@ -291,3 +292,4 @@ module_platform_driver(hid_temperature_platform_driver); MODULE_DESCRIPTION("HID Environmental temperature sensor"); MODULE_AUTHOR("Song Hongyan <hongyan.song@intel.com>"); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS(IIO_HID); diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c index ef0fec94d269..afcb10ea7c44 100644 --- a/drivers/iio/temperature/mlx90614.c +++ b/drivers/iio/temperature/mlx90614.c @@ -176,11 +176,14 @@ static inline s32 mlx90614_iir_search(const struct i2c_client *client, static int mlx90614_power_get(struct mlx90614_data *data, bool startup) { unsigned long now; + int ret; if (!data->wakeup_gpio) return 0; - pm_runtime_get_sync(&data->client->dev); + ret = pm_runtime_resume_and_get(&data->client->dev); + if (ret < 0) + return ret; if (startup) { now = jiffies; @@ -267,7 +270,10 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev, *val = MLX90614_CONST_SCALE; return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */ - mlx90614_power_get(data, false); + ret = mlx90614_power_get(data, false); + if (ret < 0) + return ret; + mutex_lock(&data->lock); ret = i2c_smbus_read_word_data(data->client, MLX90614_EMISSIVITY); @@ -287,7 +293,10 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_NANO; case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: /* IIR setting with FIR = 1024 */ - mlx90614_power_get(data, false); + ret = mlx90614_power_get(data, false); + if (ret < 0) + return ret; + mutex_lock(&data->lock); ret = i2c_smbus_read_word_data(data->client, MLX90614_CONFIG); mutex_unlock(&data->lock); @@ -319,7 +328,10 @@ static int mlx90614_write_raw(struct iio_dev *indio_dev, val = val * MLX90614_CONST_RAW_EMISSIVITY_MAX + val2 / MLX90614_CONST_EMISSIVITY_RESOLUTION; - mlx90614_power_get(data, false); + ret = mlx90614_power_get(data, false); + if (ret < 0) + return ret; + mutex_lock(&data->lock); ret = mlx90614_write_word(data->client, MLX90614_EMISSIVITY, val); @@ -331,7 +343,10 @@ static int mlx90614_write_raw(struct iio_dev *indio_dev, if (val < 0 || val2 < 0) return -EINVAL; - mlx90614_power_get(data, false); + ret = mlx90614_power_get(data, false); + if (ret < 0) + return ret; + mutex_lock(&data->lock); ret = mlx90614_iir_search(data->client, val * 100 + val2 / 10000); diff --git a/drivers/iio/temperature/tmp117.c b/drivers/iio/temperature/tmp117.c new file mode 100644 index 000000000000..f9b8f2b570f6 --- /dev/null +++ b/drivers/iio/temperature/tmp117.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Digital temperature sensor with integrated Non-volatile memory + * Copyright (c) 2021 Puranjay Mohan <puranjay12@gmail.com> + * + * Driver for the Texas Instruments TMP117 Temperature Sensor + * (7-bit I2C slave address (0x48 - 0x4B), changeable via ADD pins) + * + * Note: This driver assumes that the sensor has been calibrated beforehand. + */ + +#include <linux/err.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/bitops.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/limits.h> + +#include <linux/iio/iio.h> + +#define TMP117_REG_TEMP 0x0 +#define TMP117_REG_CFGR 0x1 +#define TMP117_REG_HIGH_LIM 0x2 +#define TMP117_REG_LOW_LIM 0x3 +#define TMP117_REG_EEPROM_UL 0x4 +#define TMP117_REG_EEPROM1 0x5 +#define TMP117_REG_EEPROM2 0x6 +#define TMP117_REG_TEMP_OFFSET 0x7 +#define TMP117_REG_EEPROM3 0x8 +#define TMP117_REG_DEVICE_ID 0xF + +#define TMP117_RESOLUTION_10UC 78125 +#define TMP117_DEVICE_ID 0x0117 +#define MICRODEGREE_PER_10MILLIDEGREE 10000 + +struct tmp117_data { + struct i2c_client *client; + s16 calibbias; +}; + +static int tmp117_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *channel, int *val, + int *val2, long mask) +{ + struct tmp117_data *data = iio_priv(indio_dev); + s32 ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = i2c_smbus_read_word_swapped(data->client, + TMP117_REG_TEMP); + if (ret < 0) + return ret; + *val = sign_extend32(ret, 15); + return IIO_VAL_INT; + + case IIO_CHAN_INFO_CALIBBIAS: + ret = i2c_smbus_read_word_swapped(data->client, + TMP117_REG_TEMP_OFFSET); + if (ret < 0) + return ret; + *val = sign_extend32(ret, 15); + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + /* + * Conversion from 10s of uC to mC + * as IIO reports temperature in mC + */ + *val = TMP117_RESOLUTION_10UC / MICRODEGREE_PER_10MILLIDEGREE; + *val2 = (TMP117_RESOLUTION_10UC % + MICRODEGREE_PER_10MILLIDEGREE) * 100; + + return IIO_VAL_INT_PLUS_MICRO; + + default: + return -EINVAL; + } +} + +static int tmp117_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *channel, int val, + int val2, long mask) +{ + struct tmp117_data *data = iio_priv(indio_dev); + s16 off; + + switch (mask) { + case IIO_CHAN_INFO_CALIBBIAS: + off = clamp_t(int, val, S16_MIN, S16_MAX); + if (off == data->calibbias) + return 0; + data->calibbias = off; + return i2c_smbus_write_word_swapped(data->client, + TMP117_REG_TEMP_OFFSET, off); + + default: + return -EINVAL; + } +} + +static const struct iio_chan_spec tmp117_channels[] = { + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_SCALE), + }, +}; + +static const struct iio_info tmp117_info = { + .read_raw = tmp117_read_raw, + .write_raw = tmp117_write_raw, +}; + +static int tmp117_identify(struct i2c_client *client) +{ + int dev_id; + + dev_id = i2c_smbus_read_word_swapped(client, TMP117_REG_DEVICE_ID); + if (dev_id < 0) + return dev_id; + if (dev_id != TMP117_DEVICE_ID) { + dev_err(&client->dev, "TMP117 not found\n"); + return -ENODEV; + } + return 0; +} + +static int tmp117_probe(struct i2c_client *client) +{ + struct tmp117_data *data; + struct iio_dev *indio_dev; + int ret; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) + return -EOPNOTSUPP; + + ret = tmp117_identify(client); + if (ret < 0) + return ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->client = client; + data->calibbias = 0; + + indio_dev->name = "tmp117"; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &tmp117_info; + + indio_dev->channels = tmp117_channels; + indio_dev->num_channels = ARRAY_SIZE(tmp117_channels); + + return devm_iio_device_register(&client->dev, indio_dev); +} + +static const struct of_device_id tmp117_of_match[] = { + { .compatible = "ti,tmp117", }, + { } +}; +MODULE_DEVICE_TABLE(of, tmp117_of_match); + +static const struct i2c_device_id tmp117_id[] = { + { "tmp117", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tmp117_id); + +static struct i2c_driver tmp117_driver = { + .driver = { + .name = "tmp117", + .of_match_table = tmp117_of_match, + }, + .probe_new = tmp117_probe, + .id_table = tmp117_id, +}; +module_i2c_driver(tmp117_driver); + +MODULE_AUTHOR("Puranjay Mohan <puranjay12@gmail.com>"); +MODULE_DESCRIPTION("TI TMP117 Temperature sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c index 3aa9e8bba005..33083877cd19 100644 --- a/drivers/iio/trigger/stm32-timer-trigger.c +++ b/drivers/iio/trigger/stm32-timer-trigger.c @@ -296,7 +296,7 @@ static ssize_t stm32_tt_show_master_mode(struct device *dev, else cr2 = (cr2 & TIM_CR2_MMS) >> TIM_CR2_MMS_SHIFT; - return snprintf(buf, PAGE_SIZE, "%s\n", master_mode_table[cr2]); + return sysfs_emit(buf, "%s\n", master_mode_table[cr2]); } static ssize_t stm32_tt_store_master_mode(struct device *dev, diff --git a/drivers/infiniband/hw/hfi1/trace_misc.h b/drivers/infiniband/hw/hfi1/trace_misc.h index 8db2253523ff..93338988b922 100644 --- a/drivers/infiniband/hw/hfi1/trace_misc.h +++ b/drivers/infiniband/hw/hfi1/trace_misc.h @@ -63,7 +63,7 @@ TRACE_EVENT(hfi1_interrupt, __array(char, buf, 64) __field(int, src) ), - TP_fast_assign(DD_DEV_ASSIGN(dd) + TP_fast_assign(DD_DEV_ASSIGN(dd); is_entry->is_name(__entry->buf, 64, src - is_entry->start); __entry->src = src; @@ -100,7 +100,7 @@ TRACE_EVENT(hfi1_fault_opcode, __field(u32, qpn) __field(u8, opcode) ), - TP_fast_assign(DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device)) + TP_fast_assign(DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device)); __entry->qpn = qp->ibqp.qp_num; __entry->opcode = opcode; ), diff --git a/drivers/infiniband/hw/hfi1/trace_rc.h b/drivers/infiniband/hw/hfi1/trace_rc.h index 1ebca37862e0..5f49e1eeb211 100644 --- a/drivers/infiniband/hw/hfi1/trace_rc.h +++ b/drivers/infiniband/hw/hfi1/trace_rc.h @@ -70,7 +70,7 @@ DECLARE_EVENT_CLASS(hfi1_rc_template, __field(u32, r_psn) ), TP_fast_assign( - DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device)) + DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device)); __entry->qpn = qp->ibqp.qp_num; __entry->s_flags = qp->s_flags; __entry->psn = psn; @@ -130,7 +130,7 @@ DECLARE_EVENT_CLASS(/* rc_ack */ __field(u32, lpsn) ), TP_fast_assign(/* assign */ - DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device)) + DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device)); __entry->qpn = qp->ibqp.qp_num; __entry->aeth = aeth; __entry->psn = psn; diff --git a/drivers/infiniband/hw/hfi1/trace_tid.h b/drivers/infiniband/hw/hfi1/trace_tid.h index 985ffa9cc958..d129b8195959 100644 --- a/drivers/infiniband/hw/hfi1/trace_tid.h +++ b/drivers/infiniband/hw/hfi1/trace_tid.h @@ -886,7 +886,7 @@ DECLARE_EVENT_CLASS(/* sender_info */ __field(u8, s_retry) ), TP_fast_assign(/* assign */ - DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device)) + DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device)); __entry->qpn = qp->ibqp.qp_num; __entry->state = qp->state; __entry->s_cur = qp->s_cur; @@ -1285,7 +1285,7 @@ DECLARE_EVENT_CLASS(/* rc_rcv_err */ __field(int, diff) ), TP_fast_assign(/* assign */ - DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device)) + DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device)); __entry->qpn = qp->ibqp.qp_num; __entry->s_flags = qp->s_flags; __entry->state = qp->state; @@ -1574,7 +1574,7 @@ DECLARE_EVENT_CLASS(/* tid_ack */ __field(u32, resync_psn) ), TP_fast_assign(/* assign */ - DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device)) + DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device)); __entry->qpn = qp->ibqp.qp_num; __entry->aeth = aeth; __entry->psn = psn; diff --git a/drivers/infiniband/hw/hfi1/trace_tx.h b/drivers/infiniband/hw/hfi1/trace_tx.h index d44fc54858b9..f1922a7619fe 100644 --- a/drivers/infiniband/hw/hfi1/trace_tx.h +++ b/drivers/infiniband/hw/hfi1/trace_tx.h @@ -120,7 +120,7 @@ DECLARE_EVENT_CLASS(hfi1_qpsleepwakeup_template, __field(unsigned long, iow_flags) ), TP_fast_assign( - DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device)) + DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device)); __entry->flags = flags; __entry->qpn = qp->ibqp.qp_num; __entry->s_flags = qp->s_flags; @@ -868,7 +868,7 @@ TRACE_EVENT( __field(int, send_flags) ), TP_fast_assign( - DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device)) + DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device)); __entry->wqe = wqe; __entry->wr_id = wqe->wr.wr_id; __entry->qpn = qp->ibqp.qp_num; @@ -904,7 +904,7 @@ DECLARE_EVENT_CLASS( __field(bool, flag) ), TP_fast_assign( - DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device)) + DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device)); __entry->qpn = qp->ibqp.qp_num; __entry->flag = flag; ), @@ -952,7 +952,7 @@ DECLARE_EVENT_CLASS(/* AIP */ __field(u8, stopped) ), TP_fast_assign(/* assign */ - DD_DEV_ASSIGN(txq->priv->dd) + DD_DEV_ASSIGN(txq->priv->dd); __entry->txq = txq; __entry->sde = txq->sde; __entry->head = txq->tx_ring.head; diff --git a/drivers/infiniband/sw/rdmavt/trace_cq.h b/drivers/infiniband/sw/rdmavt/trace_cq.h index e3c416c6f900..91bc192cee5e 100644 --- a/drivers/infiniband/sw/rdmavt/trace_cq.h +++ b/drivers/infiniband/sw/rdmavt/trace_cq.h @@ -85,7 +85,7 @@ DECLARE_EVENT_CLASS(rvt_cq_template, __field(int, comp_vector_cpu) __field(u32, flags) ), - TP_fast_assign(RDI_DEV_ASSIGN(cq->rdi) + TP_fast_assign(RDI_DEV_ASSIGN(cq->rdi); __entry->ip = cq->ip; __entry->cqe = attr->cqe; __entry->comp_vector = attr->comp_vector; @@ -123,7 +123,7 @@ DECLARE_EVENT_CLASS( __field(u32, imm) ), TP_fast_assign( - RDI_DEV_ASSIGN(cq->rdi) + RDI_DEV_ASSIGN(cq->rdi); __entry->wr_id = wc->wr_id; __entry->status = wc->status; __entry->opcode = wc->opcode; diff --git a/drivers/infiniband/sw/rdmavt/trace_mr.h b/drivers/infiniband/sw/rdmavt/trace_mr.h index 95b8a0e3b8bd..c5b675ca4fa0 100644 --- a/drivers/infiniband/sw/rdmavt/trace_mr.h +++ b/drivers/infiniband/sw/rdmavt/trace_mr.h @@ -195,7 +195,7 @@ TRACE_EVENT( __field(uint, sg_offset) ), TP_fast_assign( - RDI_DEV_ASSIGN(ib_to_rvt(to_imr(ibmr)->mr.pd->device)) + RDI_DEV_ASSIGN(ib_to_rvt(to_imr(ibmr)->mr.pd->device)); __entry->ibmr_iova = ibmr->iova; __entry->iova = to_imr(ibmr)->mr.iova; __entry->user_base = to_imr(ibmr)->mr.user_base; diff --git a/drivers/infiniband/sw/rdmavt/trace_qp.h b/drivers/infiniband/sw/rdmavt/trace_qp.h index c32d21cc615e..800cec8bb3c7 100644 --- a/drivers/infiniband/sw/rdmavt/trace_qp.h +++ b/drivers/infiniband/sw/rdmavt/trace_qp.h @@ -65,7 +65,7 @@ DECLARE_EVENT_CLASS(rvt_qphash_template, __field(u32, bucket) ), TP_fast_assign( - RDI_DEV_ASSIGN(ib_to_rvt(qp->ibqp.device)) + RDI_DEV_ASSIGN(ib_to_rvt(qp->ibqp.device)); __entry->qpn = qp->ibqp.qp_num; __entry->bucket = bucket; ), @@ -97,7 +97,7 @@ DECLARE_EVENT_CLASS( __field(u32, to) ), TP_fast_assign( - RDI_DEV_ASSIGN(ib_to_rvt(qp->ibqp.device)) + RDI_DEV_ASSIGN(ib_to_rvt(qp->ibqp.device)); __entry->qpn = qp->ibqp.qp_num; __entry->hrtimer = &qp->s_rnr_timer; __entry->s_flags = qp->s_flags; diff --git a/drivers/infiniband/sw/rdmavt/trace_rc.h b/drivers/infiniband/sw/rdmavt/trace_rc.h index c47357af2099..9de52e138025 100644 --- a/drivers/infiniband/sw/rdmavt/trace_rc.h +++ b/drivers/infiniband/sw/rdmavt/trace_rc.h @@ -71,7 +71,7 @@ DECLARE_EVENT_CLASS(rvt_rc_template, __field(u32, r_psn) ), TP_fast_assign( - RDI_DEV_ASSIGN(ib_to_rvt(qp->ibqp.device)) + RDI_DEV_ASSIGN(ib_to_rvt(qp->ibqp.device)); __entry->qpn = qp->ibqp.qp_num; __entry->s_flags = qp->s_flags; __entry->psn = psn; diff --git a/drivers/infiniband/sw/rdmavt/trace_tx.h b/drivers/infiniband/sw/rdmavt/trace_tx.h index d963ca755828..cb96be0f8f19 100644 --- a/drivers/infiniband/sw/rdmavt/trace_tx.h +++ b/drivers/infiniband/sw/rdmavt/trace_tx.h @@ -111,7 +111,7 @@ TRACE_EVENT( __field(int, wr_num_sge) ), TP_fast_assign( - RDI_DEV_ASSIGN(ib_to_rvt(qp->ibqp.device)) + RDI_DEV_ASSIGN(ib_to_rvt(qp->ibqp.device)); __entry->wqe = wqe; __entry->wr_id = wqe->wr.wr_id; __entry->qpn = qp->ibqp.qp_num; @@ -170,7 +170,7 @@ TRACE_EVENT( __field(int, send_flags) ), TP_fast_assign( - RDI_DEV_ASSIGN(ib_to_rvt(qp->ibqp.device)) + RDI_DEV_ASSIGN(ib_to_rvt(qp->ibqp.device)); __entry->wqe = wqe; __entry->wr_id = wqe->wr.wr_id; __entry->qpn = qp->ibqp.qp_num; diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index ec0e861f185f..5baebf62df33 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -4,7 +4,6 @@ # menu "Input device support" - depends on !UML config INPUT tristate "Generic input layer (needed for keyboard, mouse, ...)" if EXPERT diff --git a/drivers/input/evbug.c b/drivers/input/evbug.c index c0d0b121ae7e..e47bdf92088a 100644 --- a/drivers/input/evbug.c +++ b/drivers/input/evbug.c @@ -7,9 +7,6 @@ * Input driver event debug module - dumps all events into syslog */ -/* - */ - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/slab.h> diff --git a/drivers/input/gameport/Kconfig b/drivers/input/gameport/Kconfig index 4761795cb49f..5a2c2fb3217d 100644 --- a/drivers/input/gameport/Kconfig +++ b/drivers/input/gameport/Kconfig @@ -4,6 +4,7 @@ # config GAMEPORT tristate "Gameport support" + depends on !UML help Gameport support is for the standard 15-pin PC gameport. If you have a joystick, gamepad, gameport card, a soundcard with a gameport diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index da8963a9f044..947d440a3be6 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -499,7 +499,7 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev, memcpy(joydev->keypam, keypam, len); for (i = 0; i < joydev->nkey; i++) - joydev->keymap[keypam[i] - BTN_MISC] = i; + joydev->keymap[joydev->keypam[i] - BTN_MISC] = i; out: kfree(keypam); diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig index 5e38899058c1..3b23078bc7b5 100644 --- a/drivers/input/joystick/Kconfig +++ b/drivers/input/joystick/Kconfig @@ -4,6 +4,7 @@ # menuconfig INPUT_JOYSTICK bool "Joysticks/Gamepads" + depends on !UML help If you have a joystick, 6dof controller, gamepad, steering wheel, weapon control system or something like that you can say Y here @@ -372,6 +373,15 @@ config JOYSTICK_PXRC To compile this driver as a module, choose M here: the module will be called pxrc. +config JOYSTICK_QWIIC + tristate "SparkFun Qwiic Joystick" + depends on I2C + help + Say Y here if you want to use the SparkFun Qwiic Joystick. + + To compile this driver as a module, choose M here: the + module will be called qwiic-joystick. + config JOYSTICK_FSIA6B tristate "FlySky FS-iA6B RC Receiver" select SERIO diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile index 31d720c9e493..5174b8aba2dd 100644 --- a/drivers/input/joystick/Makefile +++ b/drivers/input/joystick/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_JOYSTICK_MAPLE) += maplecontrol.o obj-$(CONFIG_JOYSTICK_N64) += n64joy.o obj-$(CONFIG_JOYSTICK_PSXPAD_SPI) += psxpad-spi.o obj-$(CONFIG_JOYSTICK_PXRC) += pxrc.o +obj-$(CONFIG_JOYSTICK_QWIIC) += qwiic-joystick.o obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o obj-$(CONFIG_JOYSTICK_SPACEBALL) += spaceball.o obj-$(CONFIG_JOYSTICK_SPACEORB) += spaceorb.o diff --git a/drivers/input/joystick/qwiic-joystick.c b/drivers/input/joystick/qwiic-joystick.c new file mode 100644 index 000000000000..d4da31c0616c --- /dev/null +++ b/drivers/input/joystick/qwiic-joystick.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021 Oleh Kravchenko <oleg@kaa.org.ua> + * + * SparkFun Qwiic Joystick + * Product page:https://www.sparkfun.com/products/15168 + * Firmware and hardware sources:https://github.com/sparkfun/Qwiic_Joystick + */ + +#include <linux/bits.h> +#include <linux/i2c.h> +#include <linux/input.h> +#include <linux/kernel.h> +#include <linux/module.h> + +#define DRV_NAME "qwiic-joystick" + +#define QWIIC_JSK_REG_VERS 1 +#define QWIIC_JSK_REG_DATA 3 + +#define QWIIC_JSK_MAX_AXIS GENMASK(9, 0) +#define QWIIC_JSK_FUZZ 2 +#define QWIIC_JSK_FLAT 2 +#define QWIIC_JSK_POLL_INTERVAL 16 +#define QWIIC_JSK_POLL_MIN 8 +#define QWIIC_JSK_POLL_MAX 32 + +struct qwiic_jsk { + char phys[32]; + struct input_dev *dev; + struct i2c_client *client; +}; + +struct qwiic_ver { + u8 major; + u8 minor; +}; + +struct qwiic_data { + __be16 x; + __be16 y; + u8 thumb; +}; + +static void qwiic_poll(struct input_dev *input) +{ + struct qwiic_jsk *priv = input_get_drvdata(input); + struct qwiic_data data; + int err; + + err = i2c_smbus_read_i2c_block_data(priv->client, QWIIC_JSK_REG_DATA, + sizeof(data), (u8 *)&data); + if (err != sizeof(data)) + return; + + input_report_abs(input, ABS_X, be16_to_cpu(data.x) >> 6); + input_report_abs(input, ABS_Y, be16_to_cpu(data.y) >> 6); + input_report_key(input, BTN_THUMBL, !data.thumb); + input_sync(input); +} + +static int qwiic_probe(struct i2c_client *client) +{ + struct qwiic_jsk *priv; + struct qwiic_ver vers; + int err; + + err = i2c_smbus_read_i2c_block_data(client, QWIIC_JSK_REG_VERS, + sizeof(vers), (u8 *)&vers); + if (err < 0) + return err; + if (err != sizeof(vers)) + return -EIO; + + dev_dbg(&client->dev, "SparkFun Qwiic Joystick, FW: %u.%u\n", + vers.major, vers.minor); + + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->client = client; + snprintf(priv->phys, sizeof(priv->phys), + "i2c/%s", dev_name(&client->dev)); + i2c_set_clientdata(client, priv); + + priv->dev = devm_input_allocate_device(&client->dev); + if (!priv->dev) + return -ENOMEM; + + priv->dev->id.bustype = BUS_I2C; + priv->dev->name = "SparkFun Qwiic Joystick"; + priv->dev->phys = priv->phys; + input_set_drvdata(priv->dev, priv); + + input_set_abs_params(priv->dev, ABS_X, 0, QWIIC_JSK_MAX_AXIS, + QWIIC_JSK_FUZZ, QWIIC_JSK_FLAT); + input_set_abs_params(priv->dev, ABS_Y, 0, QWIIC_JSK_MAX_AXIS, + QWIIC_JSK_FUZZ, QWIIC_JSK_FLAT); + input_set_capability(priv->dev, EV_KEY, BTN_THUMBL); + + err = input_setup_polling(priv->dev, qwiic_poll); + if (err) { + dev_err(&client->dev, "failed to set up polling: %d\n", err); + return err; + } + input_set_poll_interval(priv->dev, QWIIC_JSK_POLL_INTERVAL); + input_set_min_poll_interval(priv->dev, QWIIC_JSK_POLL_MIN); + input_set_max_poll_interval(priv->dev, QWIIC_JSK_POLL_MAX); + + err = input_register_device(priv->dev); + if (err) { + dev_err(&client->dev, "failed to register joystick: %d\n", err); + return err; + } + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id of_qwiic_match[] = { + { .compatible = "sparkfun,qwiic-joystick", }, + { }, +}; +MODULE_DEVICE_TABLE(of, of_qwiic_match); +#endif /* CONFIG_OF */ + +static const struct i2c_device_id qwiic_id_table[] = { + { KBUILD_MODNAME, 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, qwiic_id_table); + +static struct i2c_driver qwiic_driver = { + .driver = { + .name = DRV_NAME, + .of_match_table = of_match_ptr(of_qwiic_match), + }, + .id_table = qwiic_id_table, + .probe_new = qwiic_probe, +}; +module_i2c_driver(qwiic_driver); + +MODULE_AUTHOR("Oleh Kravchenko <oleg@kaa.org.ua>"); +MODULE_DESCRIPTION("SparkFun Qwiic Joystick driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c index fac91ea14f17..8e9672deb1eb 100644 --- a/drivers/input/joystick/sidewinder.c +++ b/drivers/input/joystick/sidewinder.c @@ -660,6 +660,7 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) fallthrough; case 45: /* Ambiguous packet length */ if (j <= 40) { /* ID length less or eq 40 -> FSP */ + fallthrough; case 43: sw->type = SW_ID_FSP; break; diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index d69d7657ab12..29de8412e416 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -79,6 +79,7 @@ #define MAP_DPAD_TO_BUTTONS (1 << 0) #define MAP_TRIGGERS_TO_BUTTONS (1 << 1) #define MAP_STICKS_TO_NULL (1 << 2) +#define MAP_SELECT_BUTTON (1 << 3) #define DANCEPAD_MAP_CONFIG (MAP_DPAD_TO_BUTTONS | \ MAP_TRIGGERS_TO_BUTTONS | MAP_STICKS_TO_NULL) @@ -130,6 +131,7 @@ static const struct xpad_device { { 0x045e, 0x02e3, "Microsoft X-Box One Elite pad", 0, XTYPE_XBOXONE }, { 0x045e, 0x02ea, "Microsoft X-Box One S pad", 0, XTYPE_XBOXONE }, { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, + { 0x045e, 0x0b12, "Microsoft Xbox One X pad", MAP_SELECT_BUTTON, XTYPE_XBOXONE }, { 0x046d, 0xc21d, "Logitech Gamepad F310", 0, XTYPE_XBOX360 }, { 0x046d, 0xc21e, "Logitech Gamepad F510", 0, XTYPE_XBOX360 }, { 0x046d, 0xc21f, "Logitech Gamepad F710", 0, XTYPE_XBOX360 }, @@ -864,6 +866,8 @@ static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char /* menu/view buttons */ input_report_key(dev, BTN_START, data[4] & 0x04); input_report_key(dev, BTN_SELECT, data[4] & 0x08); + if (xpad->mapping & MAP_SELECT_BUTTON) + input_report_key(dev, KEY_RECORD, data[22] & 0x01); /* buttons A,B,X,Y */ input_report_key(dev, BTN_A, data[4] & 0x10); @@ -1674,6 +1678,8 @@ static int xpad_init_input(struct usb_xpad *xpad) xpad->xtype == XTYPE_XBOXONE) { for (i = 0; xpad360_btn[i] >= 0; i++) input_set_capability(input_dev, EV_KEY, xpad360_btn[i]); + if (xpad->mapping & MAP_SELECT_BUTTON) + input_set_capability(input_dev, EV_KEY, KEY_RECORD); } else { for (i = 0; xpad_btn[i] >= 0; i++) input_set_capability(input_dev, EV_KEY, xpad_btn[i]); diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index edc613efc158..fbdef95291e9 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -324,7 +324,7 @@ static ssize_t atkbd_show_function_row_physmap(struct atkbd *atkbd, char *buf) static umode_t atkbd_attr_is_visible(struct kobject *kobj, struct attribute *attr, int i) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct serio *serio = to_serio_port(dev); struct atkbd *atkbd = serio_get_drvdata(serio); diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index 38457d9641bd..fc02c540636e 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c @@ -644,7 +644,7 @@ static umode_t cros_ec_keyb_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct cros_ec_keyb *ckdev = dev_get_drvdata(dev); if (attr == &dev_attr_function_row_physmap.attr && diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index bb29a7c9a1c0..54afb38601b9 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c @@ -512,6 +512,7 @@ static int hil_dev_connect(struct serio *serio, struct serio_driver *drv) HIL_IDD_NUM_AXES_PER_SET(*idd)) { printk(KERN_INFO PREFIX "combo devices are not supported.\n"); + error = -EINVAL; goto bail1; } diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c index 81de8c4e37d0..6f38aa23a1ff 100644 --- a/drivers/input/misc/ims-pcu.c +++ b/drivers/input/misc/ims-pcu.c @@ -647,8 +647,8 @@ static int __ims_pcu_execute_command(struct ims_pcu *pcu, #define IMS_PCU_BL_DATA_OFFSET 3 static int __ims_pcu_execute_bl_command(struct ims_pcu *pcu, - u8 command, const void *data, size_t len, - u8 expected_response, int response_time) + u8 command, const void *data, size_t len, + u8 expected_response, int response_time) { int error; @@ -1228,7 +1228,7 @@ static struct attribute *ims_pcu_attrs[] = { static umode_t ims_pcu_is_attr_visible(struct kobject *kobj, struct attribute *attr, int n) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct usb_interface *intf = to_usb_interface(dev); struct ims_pcu *pcu = usb_get_intfdata(intf); umode_t mode = attr->mode; diff --git a/drivers/input/misc/pm8941-pwrkey.c b/drivers/input/misc/pm8941-pwrkey.c index cf8104454e74..10e3fc0eac6e 100644 --- a/drivers/input/misc/pm8941-pwrkey.c +++ b/drivers/input/misc/pm8941-pwrkey.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, 2020-2021, The Linux Foundation. All rights reserved. * Copyright (c) 2014, Sony Mobile Communications Inc. */ @@ -22,6 +22,8 @@ #define PON_RT_STS 0x10 #define PON_KPDPWR_N_SET BIT(0) #define PON_RESIN_N_SET BIT(1) +#define PON_GEN3_RESIN_N_SET BIT(6) +#define PON_GEN3_KPDPWR_N_SET BIT(7) #define PON_PS_HOLD_RST_CTL 0x5a #define PON_PS_HOLD_RST_CTL2 0x5b @@ -38,8 +40,12 @@ #define PON_DBC_DELAY_MASK 0x7 struct pm8941_data { - unsigned int pull_up_bit; - unsigned int status_bit; + unsigned int pull_up_bit; + unsigned int status_bit; + bool supports_ps_hold_poff_config; + bool supports_debounce_config; + const char *name; + const char *phys; }; struct pm8941_pwrkey { @@ -231,34 +237,40 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev) input_set_capability(pwrkey->input, EV_KEY, pwrkey->code); - pwrkey->input->name = "pm8941_pwrkey"; - pwrkey->input->phys = "pm8941_pwrkey/input0"; - - req_delay = (req_delay << 6) / USEC_PER_SEC; - req_delay = ilog2(req_delay); - - error = regmap_update_bits(pwrkey->regmap, - pwrkey->baseaddr + PON_DBC_CTL, - PON_DBC_DELAY_MASK, - req_delay); - if (error) { - dev_err(&pdev->dev, "failed to set debounce: %d\n", error); - return error; + pwrkey->input->name = pwrkey->data->name; + pwrkey->input->phys = pwrkey->data->phys; + + if (pwrkey->data->supports_debounce_config) { + req_delay = (req_delay << 6) / USEC_PER_SEC; + req_delay = ilog2(req_delay); + + error = regmap_update_bits(pwrkey->regmap, + pwrkey->baseaddr + PON_DBC_CTL, + PON_DBC_DELAY_MASK, + req_delay); + if (error) { + dev_err(&pdev->dev, "failed to set debounce: %d\n", + error); + return error; + } } - error = regmap_update_bits(pwrkey->regmap, - pwrkey->baseaddr + PON_PULL_CTL, - pwrkey->data->pull_up_bit, - pull_up ? pwrkey->data->pull_up_bit : 0); - if (error) { - dev_err(&pdev->dev, "failed to set pull: %d\n", error); - return error; + if (pwrkey->data->pull_up_bit) { + error = regmap_update_bits(pwrkey->regmap, + pwrkey->baseaddr + PON_PULL_CTL, + pwrkey->data->pull_up_bit, + pull_up ? pwrkey->data->pull_up_bit : + 0); + if (error) { + dev_err(&pdev->dev, "failed to set pull: %d\n", error); + return error; + } } error = devm_request_threaded_irq(&pdev->dev, pwrkey->irq, NULL, pm8941_pwrkey_irq, IRQF_ONESHOT, - "pm8941_pwrkey", pwrkey); + pwrkey->data->name, pwrkey); if (error) { dev_err(&pdev->dev, "failed requesting IRQ: %d\n", error); return error; @@ -271,12 +283,14 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev) return error; } - pwrkey->reboot_notifier.notifier_call = pm8941_reboot_notify, - error = register_reboot_notifier(&pwrkey->reboot_notifier); - if (error) { - dev_err(&pdev->dev, "failed to register reboot notifier: %d\n", - error); - return error; + if (pwrkey->data->supports_ps_hold_poff_config) { + pwrkey->reboot_notifier.notifier_call = pm8941_reboot_notify, + error = register_reboot_notifier(&pwrkey->reboot_notifier); + if (error) { + dev_err(&pdev->dev, "failed to register reboot notifier: %d\n", + error); + return error; + } } platform_set_drvdata(pdev, pwrkey); @@ -289,7 +303,8 @@ static int pm8941_pwrkey_remove(struct platform_device *pdev) { struct pm8941_pwrkey *pwrkey = platform_get_drvdata(pdev); - unregister_reboot_notifier(&pwrkey->reboot_notifier); + if (pwrkey->data->supports_ps_hold_poff_config) + unregister_reboot_notifier(&pwrkey->reboot_notifier); return 0; } @@ -297,16 +312,42 @@ static int pm8941_pwrkey_remove(struct platform_device *pdev) static const struct pm8941_data pwrkey_data = { .pull_up_bit = PON_KPDPWR_PULL_UP, .status_bit = PON_KPDPWR_N_SET, + .name = "pm8941_pwrkey", + .phys = "pm8941_pwrkey/input0", + .supports_ps_hold_poff_config = true, + .supports_debounce_config = true, }; static const struct pm8941_data resin_data = { .pull_up_bit = PON_RESIN_PULL_UP, .status_bit = PON_RESIN_N_SET, + .name = "pm8941_resin", + .phys = "pm8941_resin/input0", + .supports_ps_hold_poff_config = true, + .supports_debounce_config = true, +}; + +static const struct pm8941_data pon_gen3_pwrkey_data = { + .status_bit = PON_GEN3_KPDPWR_N_SET, + .name = "pmic_pwrkey", + .phys = "pmic_pwrkey/input0", + .supports_ps_hold_poff_config = false, + .supports_debounce_config = false, +}; + +static const struct pm8941_data pon_gen3_resin_data = { + .status_bit = PON_GEN3_RESIN_N_SET, + .name = "pmic_resin", + .phys = "pmic_resin/input0", + .supports_ps_hold_poff_config = false, + .supports_debounce_config = false, }; static const struct of_device_id pm8941_pwr_key_id_table[] = { { .compatible = "qcom,pm8941-pwrkey", .data = &pwrkey_data }, { .compatible = "qcom,pm8941-resin", .data = &resin_data }, + { .compatible = "qcom,pmk8350-pwrkey", .data = &pon_gen3_pwrkey_data }, + { .compatible = "qcom,pmk8350-resin", .data = &pon_gen3_resin_data }, { } }; MODULE_DEVICE_TABLE(of, pm8941_pwr_key_id_table); diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index ef2fa0905208..4a86b3e31d3b 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c @@ -214,7 +214,7 @@ static bool trackpoint_is_attr_available(struct psmouse *psmouse, static umode_t trackpoint_is_attr_visible(struct kobject *kobj, struct attribute *attr, int n) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct serio *serio = to_serio_port(dev); struct psmouse *psmouse = serio_get_drvdata(serio); diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index abae23af0791..0b9f1d0a8f8b 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -139,7 +139,7 @@ static DEFINE_SPINLOCK(i8042_lock); /* * Writers to AUX and KBD ports as well as users issuing i8042_command * directly should acquire i8042_mutex (by means of calling - * i8042_lock_chip() and i8042_unlock_ship() helpers) to ensure that + * i8042_lock_chip() and i8042_unlock_chip() helpers) to ensure that * they do not disturb each other (unfortunately in many i8042 * implementations write to one of the ports will immediately abort * command that is being processed by another port). @@ -979,7 +979,7 @@ static int i8042_controller_selftest(void) } /* - * i8042_controller init initializes the i8042 controller, and, + * i8042_controller_init initializes the i8042 controller, and, * most importantly, sets it into non-xlated mode if that's * desired. */ diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index 33e9d9bfd036..7fbbe00e3553 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c @@ -114,7 +114,8 @@ static void serport_ldisc_close(struct tty_struct *tty) * 'interrupt' routine. */ -static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) +static void serport_ldisc_receive(struct tty_struct *tty, + const unsigned char *cp, const char *fp, int count) { struct serport *serport = (struct serport*) tty->disc_data; unsigned long flags; @@ -273,6 +274,7 @@ static void serport_ldisc_write_wakeup(struct tty_struct * tty) static struct tty_ldisc_ops serport_ldisc = { .owner = THIS_MODULE, + .num = N_MOUSE, .name = "input", .open = serport_ldisc_open, .close = serport_ldisc_close, @@ -293,7 +295,7 @@ static struct tty_ldisc_ops serport_ldisc = { static int __init serport_init(void) { int retval; - retval = tty_register_ldisc(N_MOUSE, &serport_ldisc); + retval = tty_register_ldisc(&serport_ldisc); if (retval) printk(KERN_ERR "serport.c: Error registering line discipline.\n"); @@ -302,7 +304,7 @@ static int __init serport_init(void) static void __exit serport_exit(void) { - tty_unregister_ldisc(N_MOUSE); + tty_unregister_ldisc(&serport_ldisc); } module_init(serport_init); diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index f465bae618fe..495ef156cf43 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c @@ -7,15 +7,14 @@ * Some cleanups by Alan Cox <alan@linux.intel.com> */ -#include <linux/module.h> -#include <linux/kernel.h> +#include <linux/i2c.h> #include <linux/input.h> -#include <linux/slab.h> #include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/i2c.h> -#include <linux/gpio.h> -#include <linux/input/cy8ctmg110_pdata.h> +#include <linux/gpio/consumer.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <asm/byteorder.h> #define CY8CTMG110_DRIVER_NAME "cy8ctmg110" @@ -45,18 +44,18 @@ struct cy8ctmg110 { struct input_dev *input; char phys[32]; struct i2c_client *client; - int reset_pin; - int irq_pin; + struct gpio_desc *reset_gpio; }; /* * cy8ctmg110_power is the routine that is called when touch hardware - * will powered off or on. + * is being powered off or on. When powering on this routine de-asserts + * the RESET line, when powering off reset line is asserted. */ static void cy8ctmg110_power(struct cy8ctmg110 *ts, bool poweron) { - if (ts->reset_pin) - gpio_direction_output(ts->reset_pin, 1 - poweron); + if (ts->reset_gpio) + gpiod_set_value_cansleep(ts->reset_gpio, !poweron); } static int cy8ctmg110_write_regs(struct cy8ctmg110 *tsc, unsigned char reg, @@ -112,7 +111,6 @@ static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc) { struct input_dev *input = tsc->input; unsigned char reg_p[CY8CTMG110_REG_MAX]; - int x, y; memset(reg_p, 0, CY8CTMG110_REG_MAX); @@ -120,16 +118,15 @@ static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc) if (cy8ctmg110_read_regs(tsc, reg_p, 9, CY8CTMG110_TOUCH_X1) != 0) return -EIO; - y = reg_p[2] << 8 | reg_p[3]; - x = reg_p[0] << 8 | reg_p[1]; - /* Number of touch */ if (reg_p[8] == 0) { input_report_key(input, BTN_TOUCH, 0); } else { input_report_key(input, BTN_TOUCH, 1); - input_report_abs(input, ABS_X, x); - input_report_abs(input, ABS_Y, y); + input_report_abs(input, ABS_X, + be16_to_cpup((__be16 *)(reg_p + 0))); + input_report_abs(input, ABS_Y, + be16_to_cpup((__be16 *)(reg_p + 2))); } input_sync(input); @@ -163,35 +160,35 @@ static irqreturn_t cy8ctmg110_irq_thread(int irq, void *dev_id) return IRQ_HANDLED; } +static void cy8ctmg110_shut_off(void *_ts) +{ + struct cy8ctmg110 *ts = _ts; + + cy8ctmg110_set_sleepmode(ts, true); + cy8ctmg110_power(ts, false); +} + static int cy8ctmg110_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct cy8ctmg110_pdata *pdata = dev_get_platdata(&client->dev); struct cy8ctmg110 *ts; struct input_dev *input_dev; int err; - /* No pdata no way forward */ - if (pdata == NULL) { - dev_err(&client->dev, "no pdata\n"); - return -ENODEV; - } - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) return -EIO; - ts = kzalloc(sizeof(struct cy8ctmg110), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ts || !input_dev) { - err = -ENOMEM; - goto err_free_mem; - } + ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL); + if (!ts) + return -ENOMEM; + + input_dev = devm_input_allocate_device(&client->dev); + if (!input_dev) + return -ENOMEM; ts->client = client; ts->input = input_dev; - ts->reset_pin = pdata->reset_pin; - ts->irq_pin = pdata->irq_pin; snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&client->dev)); @@ -199,84 +196,46 @@ static int cy8ctmg110_probe(struct i2c_client *client, input_dev->name = CY8CTMG110_DRIVER_NAME " Touchscreen"; input_dev->phys = ts->phys; input_dev->id.bustype = BUS_I2C; - input_dev->dev.parent = &client->dev; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); + input_set_capability(input_dev, EV_KEY, BTN_TOUCH); input_set_abs_params(input_dev, ABS_X, CY8CTMG110_X_MIN, CY8CTMG110_X_MAX, 4, 0); input_set_abs_params(input_dev, ABS_Y, CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 4, 0); - if (ts->reset_pin) { - err = gpio_request(ts->reset_pin, NULL); - if (err) { - dev_err(&client->dev, - "Unable to request GPIO pin %d.\n", - ts->reset_pin); - goto err_free_mem; - } + /* Request and assert reset line */ + ts->reset_gpio = devm_gpiod_get_optional(&client->dev, NULL, + GPIOD_OUT_HIGH); + if (IS_ERR(ts->reset_gpio)) { + err = PTR_ERR(ts->reset_gpio); + dev_err(&client->dev, + "Unable to request reset GPIO: %d\n", err); + return err; } cy8ctmg110_power(ts, true); cy8ctmg110_set_sleepmode(ts, false); - err = gpio_request(ts->irq_pin, "touch_irq_key"); - if (err < 0) { - dev_err(&client->dev, - "Failed to request GPIO %d, error %d\n", - ts->irq_pin, err); - goto err_shutoff_device; - } - - err = gpio_direction_input(ts->irq_pin); - if (err < 0) { - dev_err(&client->dev, - "Failed to configure input direction for GPIO %d, error %d\n", - ts->irq_pin, err); - goto err_free_irq_gpio; - } - - client->irq = gpio_to_irq(ts->irq_pin); - if (client->irq < 0) { - err = client->irq; - dev_err(&client->dev, - "Unable to get irq number for GPIO %d, error %d\n", - ts->irq_pin, err); - goto err_free_irq_gpio; - } + err = devm_add_action_or_reset(&client->dev, cy8ctmg110_shut_off, ts); + if (err) + return err; - err = request_threaded_irq(client->irq, NULL, cy8ctmg110_irq_thread, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - "touch_reset_key", ts); - if (err < 0) { + err = devm_request_threaded_irq(&client->dev, client->irq, + NULL, cy8ctmg110_irq_thread, + IRQF_ONESHOT, "touch_reset_key", ts); + if (err) { dev_err(&client->dev, "irq %d busy? error %d\n", client->irq, err); - goto err_free_irq_gpio; + return err; } err = input_register_device(input_dev); if (err) - goto err_free_irq; + return err; i2c_set_clientdata(client, ts); - device_init_wakeup(&client->dev, 1); - return 0; -err_free_irq: - free_irq(client->irq, ts); -err_free_irq_gpio: - gpio_free(ts->irq_pin); -err_shutoff_device: - cy8ctmg110_set_sleepmode(ts, true); - cy8ctmg110_power(ts, false); - if (ts->reset_pin) - gpio_free(ts->reset_pin); -err_free_mem: - input_free_device(input_dev); - kfree(ts); - return err; + return 0; } static int __maybe_unused cy8ctmg110_suspend(struct device *dev) @@ -284,12 +243,11 @@ static int __maybe_unused cy8ctmg110_suspend(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct cy8ctmg110 *ts = i2c_get_clientdata(client); - if (device_may_wakeup(&client->dev)) - enable_irq_wake(client->irq); - else { + if (!device_may_wakeup(&client->dev)) { cy8ctmg110_set_sleepmode(ts, true); cy8ctmg110_power(ts, false); } + return 0; } @@ -298,34 +256,16 @@ static int __maybe_unused cy8ctmg110_resume(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct cy8ctmg110 *ts = i2c_get_clientdata(client); - if (device_may_wakeup(&client->dev)) - disable_irq_wake(client->irq); - else { + if (!device_may_wakeup(&client->dev)) { cy8ctmg110_power(ts, true); cy8ctmg110_set_sleepmode(ts, false); } + return 0; } static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume); -static int cy8ctmg110_remove(struct i2c_client *client) -{ - struct cy8ctmg110 *ts = i2c_get_clientdata(client); - - cy8ctmg110_set_sleepmode(ts, true); - cy8ctmg110_power(ts, false); - - free_irq(client->irq, ts); - input_unregister_device(ts->input); - gpio_free(ts->irq_pin); - if (ts->reset_pin) - gpio_free(ts->reset_pin); - kfree(ts); - - return 0; -} - static const struct i2c_device_id cy8ctmg110_idtable[] = { { CY8CTMG110_DRIVER_NAME, 1 }, { } @@ -340,7 +280,6 @@ static struct i2c_driver cy8ctmg110_driver = { }, .id_table = cy8ctmg110_idtable, .probe = cy8ctmg110_probe, - .remove = cy8ctmg110_remove, }; module_i2c_driver(cy8ctmg110_driver); diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index 106dd4962785..1dbd849c9613 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c @@ -22,6 +22,7 @@ #include <linux/slab.h> #include <linux/property.h> #include <linux/gpio/consumer.h> +#include <linux/regulator/consumer.h> #include "cyttsp_core.h" @@ -45,8 +46,15 @@ #define CY_MAXZ 255 #define CY_DELAY_DFLT 20 /* ms */ #define CY_DELAY_MAX 500 -#define CY_ACT_DIST_DFLT 0xF8 +/* Active distance in pixels for a gesture to be reported */ +#define CY_ACT_DIST_DFLT 0xF8 /* pixels */ #define CY_ACT_DIST_MASK 0x0F +/* Active Power state scanning/processing refresh interval */ +#define CY_ACT_INTRVL_DFLT 0x00 /* ms */ +/* Low Power state scanning/processing refresh interval */ +#define CY_LP_INTRVL_DFLT 0x0A /* ms */ +/* touch timeout for the Active power */ +#define CY_TCH_TMOUT_DFLT 0xFF /* ms */ #define CY_HNDSHK_BIT 0x80 /* device mode bits */ #define CY_OPERATE_MODE 0x00 @@ -608,6 +616,14 @@ static int cyttsp_parse_properties(struct cyttsp *ts) return 0; } +static void cyttsp_disable_regulators(void *_ts) +{ + struct cyttsp *ts = _ts; + + regulator_bulk_disable(ARRAY_SIZE(ts->regulators), + ts->regulators); +} + struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, struct device *dev, int irq, size_t xfer_buf_size) { @@ -628,6 +644,32 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, ts->bus_ops = bus_ops; ts->irq = irq; + /* + * VCPIN is the analog voltage supply + * VDD is the digital voltage supply + */ + ts->regulators[0].supply = "vcpin"; + ts->regulators[1].supply = "vdd"; + error = devm_regulator_bulk_get(dev, ARRAY_SIZE(ts->regulators), + ts->regulators); + if (error) { + dev_err(dev, "Failed to get regulators: %d\n", error); + return ERR_PTR(error); + } + + error = regulator_bulk_enable(ARRAY_SIZE(ts->regulators), + ts->regulators); + if (error) { + dev_err(dev, "Cannot enable regulators: %d\n", error); + return ERR_PTR(error); + } + + error = devm_add_action_or_reset(dev, cyttsp_disable_regulators, ts); + if (error) { + dev_err(dev, "failed to install chip disable handler\n"); + return ERR_PTR(error); + } + ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(ts->reset_gpio)) { error = PTR_ERR(ts->reset_gpio); @@ -664,8 +706,7 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, } error = devm_request_threaded_irq(dev, ts->irq, NULL, cyttsp_irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT | - IRQF_NO_AUTOEN, + IRQF_ONESHOT | IRQF_NO_AUTOEN, "cyttsp", ts); if (error) { dev_err(ts->dev, "failed to request IRQ %d, err: %d\n", diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h index 9bc4fe7e6ac5..075509e695a2 100644 --- a/drivers/input/touchscreen/cyttsp_core.h +++ b/drivers/input/touchscreen/cyttsp_core.h @@ -22,7 +22,7 @@ #include <linux/module.h> #include <linux/types.h> #include <linux/device.h> -#include <linux/input/cyttsp.h> +#include <linux/regulator/consumer.h> #define CY_NUM_RETRY 16 /* max number of retries for read ops */ @@ -122,6 +122,7 @@ struct cyttsp { enum cyttsp_state state; bool suspended; + struct regulator_bulk_data regulators[2]; struct gpio_desc *reset_gpio; bool use_hndshk; u8 act_dist; diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c index 061debf64a2b..4c8473d327ab 100644 --- a/drivers/input/touchscreen/cyttsp_i2c.c +++ b/drivers/input/touchscreen/cyttsp_i2c.c @@ -18,6 +18,8 @@ #include <linux/i2c.h> #include <linux/input.h> +#define CY_I2C_NAME "cyttsp-i2c" + #define CY_I2C_DATA_SIZE 128 static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = { @@ -52,10 +54,18 @@ static const struct i2c_device_id cyttsp_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id); +static const struct of_device_id cyttsp_of_i2c_match[] = { + { .compatible = "cypress,cy8ctma340", }, + { .compatible = "cypress,cy8ctst341", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, cyttsp_of_i2c_match); + static struct i2c_driver cyttsp_i2c_driver = { .driver = { .name = CY_I2C_NAME, .pm = &cyttsp_pm_ops, + .of_match_table = cyttsp_of_i2c_match, }, .probe = cyttsp_i2c_probe, .id_table = cyttsp_i2c_id, diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c index 54e410921d53..30c6fbf86a86 100644 --- a/drivers/input/touchscreen/cyttsp_spi.c +++ b/drivers/input/touchscreen/cyttsp_spi.c @@ -20,6 +20,8 @@ #include <linux/input.h> #include <linux/spi/spi.h> +#define CY_SPI_NAME "cyttsp-spi" + #define CY_SPI_WR_OP 0x00 /* r/~w */ #define CY_SPI_RD_OP 0x01 #define CY_SPI_CMD_BYTES 4 @@ -160,10 +162,18 @@ static int cyttsp_spi_probe(struct spi_device *spi) return 0; } +static const struct of_device_id cyttsp_of_spi_match[] = { + { .compatible = "cypress,cy8ctma340", }, + { .compatible = "cypress,cy8ctst341", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, cyttsp_of_spi_match); + static struct spi_driver cyttsp_spi_driver = { .driver = { .name = CY_SPI_NAME, .pm = &cyttsp_pm_ops, + .of_match_table = cyttsp_of_spi_match, }, .probe = cyttsp_spi_probe, }; diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 2eefbc2485bc..263de3bfb6cd 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -104,6 +104,7 @@ struct edt_ft5x06_ts_data { u16 num_x; u16 num_y; struct regulator *vcc; + struct regulator *iovcc; struct gpio_desc *reset_gpio; struct gpio_desc *wake_gpio; @@ -1062,11 +1063,12 @@ static void edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) } } -static void edt_ft5x06_disable_regulator(void *arg) +static void edt_ft5x06_disable_regulators(void *arg) { struct edt_ft5x06_ts_data *data = arg; regulator_disable(data->vcc); + regulator_disable(data->iovcc); } static int edt_ft5x06_ts_probe(struct i2c_client *client, @@ -1107,14 +1109,33 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, return error; } + tsdata->iovcc = devm_regulator_get(&client->dev, "iovcc"); + if (IS_ERR(tsdata->iovcc)) { + error = PTR_ERR(tsdata->iovcc); + if (error != -EPROBE_DEFER) + dev_err(&client->dev, + "failed to request iovcc regulator: %d\n", error); + return error; + } + + error = regulator_enable(tsdata->iovcc); + if (error < 0) { + dev_err(&client->dev, "failed to enable iovcc: %d\n", error); + return error; + } + + /* Delay enabling VCC for > 10us (T_ivd) after IOVCC */ + usleep_range(10, 100); + error = regulator_enable(tsdata->vcc); if (error < 0) { dev_err(&client->dev, "failed to enable vcc: %d\n", error); + regulator_disable(tsdata->iovcc); return error; } error = devm_add_action_or_reset(&client->dev, - edt_ft5x06_disable_regulator, + edt_ft5x06_disable_regulators, tsdata); if (error) return error; @@ -1289,6 +1310,9 @@ static int __maybe_unused edt_ft5x06_ts_suspend(struct device *dev) ret = regulator_disable(tsdata->vcc); if (ret) dev_warn(dev, "Failed to disable vcc\n"); + ret = regulator_disable(tsdata->iovcc); + if (ret) + dev_warn(dev, "Failed to disable iovcc\n"); return 0; } @@ -1319,9 +1343,19 @@ static int __maybe_unused edt_ft5x06_ts_resume(struct device *dev) gpiod_set_value_cansleep(reset_gpio, 1); usleep_range(5000, 6000); + ret = regulator_enable(tsdata->iovcc); + if (ret) { + dev_err(dev, "Failed to enable iovcc\n"); + return ret; + } + + /* Delay enabling VCC for > 10us (T_ivd) after IOVCC */ + usleep_range(10, 100); + ret = regulator_enable(tsdata->vcc); if (ret) { dev_err(dev, "Failed to enable vcc\n"); + regulator_disable(tsdata->iovcc); return ret; } diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 17540bdb1eaf..68f542bb809f 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -1369,8 +1369,7 @@ static bool elants_acpi_is_hid_device(struct device *dev) } #endif -static int elants_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int elants_i2c_probe(struct i2c_client *client) { union i2c_smbus_data dummy; struct elants_data *ts; @@ -1396,7 +1395,7 @@ static int elants_i2c_probe(struct i2c_client *client, init_completion(&ts->cmd_done); ts->client = client; - ts->chip_id = (enum elants_chip_id)id->driver_data; + ts->chip_id = (enum elants_chip_id)(uintptr_t)device_get_match_data(&client->dev); i2c_set_clientdata(client, ts); ts->vcc33 = devm_regulator_get(&client->dev, "vcc33"); @@ -1636,15 +1635,15 @@ MODULE_DEVICE_TABLE(acpi, elants_acpi_id); #ifdef CONFIG_OF static const struct of_device_id elants_of_match[] = { - { .compatible = "elan,ekth3500" }, - { .compatible = "elan,ektf3624" }, + { .compatible = "elan,ekth3500", .data = (void *)EKTH3500 }, + { .compatible = "elan,ektf3624", .data = (void *)EKTF3624 }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, elants_of_match); #endif static struct i2c_driver elants_i2c_driver = { - .probe = elants_i2c_probe, + .probe_new = elants_i2c_probe, .id_table = elants_i2c_id, .driver = { .name = DEVICE_NAME, diff --git a/drivers/input/touchscreen/hideep.c b/drivers/input/touchscreen/hideep.c index ddad4a82a5e5..e9547ee29756 100644 --- a/drivers/input/touchscreen/hideep.c +++ b/drivers/input/touchscreen/hideep.c @@ -361,13 +361,16 @@ static int hideep_enter_pgm(struct hideep_ts *ts) return -EIO; } -static void hideep_nvm_unlock(struct hideep_ts *ts) +static int hideep_nvm_unlock(struct hideep_ts *ts) { u32 unmask_code; + int error; hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_SFR_RPAGE); - hideep_pgm_r_reg(ts, 0x0000000C, &unmask_code); + error = hideep_pgm_r_reg(ts, 0x0000000C, &unmask_code); hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE); + if (error) + return error; /* make it unprotected code */ unmask_code &= ~HIDEEP_PROT_MODE; @@ -384,6 +387,8 @@ static void hideep_nvm_unlock(struct hideep_ts *ts) NVM_W_SFR(HIDEEP_NVM_MASK_OFS, ts->nvm_mask); SET_FLASH_HWCONTROL(); hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE); + + return 0; } static int hideep_check_status(struct hideep_ts *ts) @@ -462,7 +467,9 @@ static int hideep_program_nvm(struct hideep_ts *ts, u32 addr = 0; int error; - hideep_nvm_unlock(ts); + error = hideep_nvm_unlock(ts); + if (error) + return error; while (ucode_len > 0) { xfer_len = min_t(size_t, ucode_len, HIDEEP_NVM_PAGE_SIZE); diff --git a/drivers/input/touchscreen/resistive-adc-touch.c b/drivers/input/touchscreen/resistive-adc-touch.c index e50af30183f4..744544a723b7 100644 --- a/drivers/input/touchscreen/resistive-adc-touch.c +++ b/drivers/input/touchscreen/resistive-adc-touch.c @@ -13,44 +13,78 @@ #include <linux/input/touchscreen.h> #include <linux/iio/consumer.h> #include <linux/iio/iio.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> +#include <linux/property.h> #define DRIVER_NAME "resistive-adc-touch" #define GRTS_DEFAULT_PRESSURE_MIN 50000 +#define GRTS_DEFAULT_PRESSURE_MAX 65535 #define GRTS_MAX_POS_MASK GENMASK(11, 0) +#define GRTS_MAX_CHANNELS 4 + +enum grts_ch_type { + GRTS_CH_X, + GRTS_CH_Y, + GRTS_CH_PRESSURE, + GRTS_CH_Z1, + GRTS_CH_Z2, + GRTS_CH_MAX = GRTS_CH_Z2 + 1 +}; /** * struct grts_state - generic resistive touch screen information struct + * @x_plate_ohms: resistance of the X plate * @pressure_min: number representing the minimum for the pressure * @pressure: are we getting pressure info or not * @iio_chans: list of channels acquired * @iio_cb: iio_callback buffer for the data * @input: the input device structure that we register * @prop: touchscreen properties struct + * @ch_map: map of channels that are defined for the touchscreen */ struct grts_state { + u32 x_plate_ohms; u32 pressure_min; bool pressure; struct iio_channel *iio_chans; struct iio_cb_buffer *iio_cb; struct input_dev *input; struct touchscreen_properties prop; + u8 ch_map[GRTS_CH_MAX]; }; static int grts_cb(const void *data, void *private) { const u16 *touch_info = data; struct grts_state *st = private; - unsigned int x, y, press = 0x0; - - /* channel data coming in buffer in the order below */ - x = touch_info[0]; - y = touch_info[1]; - if (st->pressure) - press = touch_info[2]; + unsigned int x, y, press = 0; + + x = touch_info[st->ch_map[GRTS_CH_X]]; + y = touch_info[st->ch_map[GRTS_CH_Y]]; + + if (st->ch_map[GRTS_CH_PRESSURE] < GRTS_MAX_CHANNELS) { + press = touch_info[st->ch_map[GRTS_CH_PRESSURE]]; + } else if (st->ch_map[GRTS_CH_Z1] < GRTS_MAX_CHANNELS) { + unsigned int z1 = touch_info[st->ch_map[GRTS_CH_Z1]]; + unsigned int z2 = touch_info[st->ch_map[GRTS_CH_Z2]]; + unsigned int Rt; + + Rt = z2; + Rt -= z1; + Rt *= st->x_plate_ohms; + Rt = DIV_ROUND_CLOSEST(Rt, 16); + Rt *= x; + Rt /= z1; + Rt = DIV_ROUND_CLOSEST(Rt, 256); + /* + * On increased pressure the resistance (Rt) is decreasing + * so, convert values to make it looks as real pressure. + */ + if (Rt < GRTS_DEFAULT_PRESSURE_MAX) + press = GRTS_DEFAULT_PRESSURE_MAX - Rt; + } if ((!x && !y) || (st->pressure && (press < st->pressure_min))) { /* report end of touch */ @@ -94,12 +128,77 @@ static void grts_disable(void *data) iio_channel_release_all_cb(data); } +static int grts_map_channel(struct grts_state *st, struct device *dev, + enum grts_ch_type type, const char *name, + bool optional) +{ + int idx; + + idx = device_property_match_string(dev, "io-channel-names", name); + if (idx < 0) { + if (!optional) + return idx; + idx = GRTS_MAX_CHANNELS; + } else if (idx >= GRTS_MAX_CHANNELS) { + return -EOVERFLOW; + } + + st->ch_map[type] = idx; + return 0; +} + +static int grts_get_properties(struct grts_state *st, struct device *dev) +{ + int error; + + error = grts_map_channel(st, dev, GRTS_CH_X, "x", false); + if (error) + return error; + + error = grts_map_channel(st, dev, GRTS_CH_Y, "y", false); + if (error) + return error; + + /* pressure is optional */ + error = grts_map_channel(st, dev, GRTS_CH_PRESSURE, "pressure", true); + if (error) + return error; + + if (st->ch_map[GRTS_CH_PRESSURE] < GRTS_MAX_CHANNELS) { + st->pressure = true; + return 0; + } + + /* if no pressure is defined, try optional z1 + z2 */ + error = grts_map_channel(st, dev, GRTS_CH_Z1, "z1", true); + if (error) + return error; + + if (st->ch_map[GRTS_CH_Z1] >= GRTS_MAX_CHANNELS) + return 0; + + /* if z1 is provided z2 is not optional */ + error = grts_map_channel(st, dev, GRTS_CH_Z2, "z2", true); + if (error) + return error; + + error = device_property_read_u32(dev, + "touchscreen-x-plate-ohms", + &st->x_plate_ohms); + if (error) { + dev_err(dev, "can't get touchscreen-x-plate-ohms property\n"); + return error; + } + + st->pressure = true; + return 0; +} + static int grts_probe(struct platform_device *pdev) { struct grts_state *st; struct input_dev *input; struct device *dev = &pdev->dev; - struct iio_channel *chan; int error; st = devm_kzalloc(dev, sizeof(struct grts_state), GFP_KERNEL); @@ -115,12 +214,13 @@ static int grts_probe(struct platform_device *pdev) return error; } - chan = &st->iio_chans[0]; - st->pressure = false; - while (chan && chan->indio_dev) { - if (!strcmp(chan->channel->datasheet_name, "pressure")) - st->pressure = true; - chan++; + if (!device_property_present(dev, "io-channel-names")) + return -ENODEV; + + error = grts_get_properties(st, dev); + if (error) { + dev_err(dev, "Failed to parse properties\n"); + return error; } if (st->pressure) { @@ -148,7 +248,7 @@ static int grts_probe(struct platform_device *pdev) input_set_abs_params(input, ABS_Y, 0, GRTS_MAX_POS_MASK - 1, 0, 0); if (st->pressure) input_set_abs_params(input, ABS_PRESSURE, st->pressure_min, - 0xffff, 0, 0); + GRTS_DEFAULT_PRESSURE_MAX, 0, 0); input_set_capability(input, EV_KEY, BTN_TOUCH); @@ -193,7 +293,7 @@ static struct platform_driver grts_driver = { .probe = grts_probe, .driver = { .name = DRIVER_NAME, - .of_match_table = of_match_ptr(grts_of_match), + .of_match_table = grts_of_match, }, }; diff --git a/drivers/input/touchscreen/tsc200x-core.c b/drivers/input/touchscreen/tsc200x-core.c index ce2fe30d6b8a..b8d720d52013 100644 --- a/drivers/input/touchscreen/tsc200x-core.c +++ b/drivers/input/touchscreen/tsc200x-core.c @@ -338,7 +338,7 @@ static struct attribute *tsc200x_attrs[] = { static umode_t tsc200x_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct tsc200x *ts = dev_get_drvdata(dev); umode_t mode = attr->mode; diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index c847453a03c2..43c521f50c85 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -251,7 +251,7 @@ static int e2i_init(struct usbtouch_usb *usbtouch) int ret; struct usb_device *udev = interface_to_usbdev(usbtouch->interface); - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01, 0x02, 0x0000, 0x0081, NULL, 0, USB_CTRL_SET_TIMEOUT); @@ -531,7 +531,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch) if (ret) return ret; - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), MTOUCHUSB_RESET, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); @@ -543,7 +543,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch) msleep(150); for (i = 0; i < 3; i++) { - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), MTOUCHUSB_ASYNC_REPORT, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); @@ -722,7 +722,7 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) } /* start sending data */ - ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), TSC10_CMD_DATA1, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig index cdb3e11462c6..0d7a2500d0b8 100644 --- a/drivers/interconnect/qcom/Kconfig +++ b/drivers/interconnect/qcom/Kconfig @@ -74,6 +74,15 @@ config INTERCONNECT_QCOM_SC7180 This is a driver for the Qualcomm Network-on-Chip on sc7180-based platforms. +config INTERCONNECT_QCOM_SC7280 + tristate "Qualcomm SC7280 interconnect driver" + depends on INTERCONNECT_QCOM_RPMH_POSSIBLE + select INTERCONNECT_QCOM_RPMH + select INTERCONNECT_QCOM_BCM_VOTER + help + This is a driver for the Qualcomm Network-on-Chip on sc7280-based + platforms. + config INTERCONNECT_QCOM_SDM660 tristate "Qualcomm SDM660 interconnect driver" depends on INTERCONNECT_QCOM diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile index 46fc62447156..2880129a6fe4 100644 --- a/drivers/interconnect/qcom/Makefile +++ b/drivers/interconnect/qcom/Makefile @@ -8,6 +8,7 @@ icc-osm-l3-objs := osm-l3.o qnoc-qcs404-objs := qcs404.o icc-rpmh-obj := icc-rpmh.o qnoc-sc7180-objs := sc7180.o +qnoc-sc7280-objs := sc7280.o qnoc-sdm660-objs := sdm660.o qnoc-sdm845-objs := sdm845.o qnoc-sdx55-objs := sdx55.o @@ -24,6 +25,7 @@ obj-$(CONFIG_INTERCONNECT_QCOM_OSM_L3) += icc-osm-l3.o obj-$(CONFIG_INTERCONNECT_QCOM_QCS404) += qnoc-qcs404.o obj-$(CONFIG_INTERCONNECT_QCOM_RPMH) += icc-rpmh.o obj-$(CONFIG_INTERCONNECT_QCOM_SC7180) += qnoc-sc7180.o +obj-$(CONFIG_INTERCONNECT_QCOM_SC7280) += qnoc-sc7280.o obj-$(CONFIG_INTERCONNECT_QCOM_SDM660) += qnoc-sdm660.o obj-$(CONFIG_INTERCONNECT_QCOM_SDM845) += qnoc-sdm845.o obj-$(CONFIG_INTERCONNECT_QCOM_SDX55) += qnoc-sdx55.o diff --git a/drivers/interconnect/qcom/sc7280.c b/drivers/interconnect/qcom/sc7280.c new file mode 100644 index 000000000000..8d1b55c3705c --- /dev/null +++ b/drivers/interconnect/qcom/sc7280.c @@ -0,0 +1,1938 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + * + */ + +#include <linux/device.h> +#include <linux/interconnect.h> +#include <linux/interconnect-provider.h> +#include <linux/module.h> +#include <linux/of_platform.h> +#include <dt-bindings/interconnect/qcom,sc7280.h> + +#include "bcm-voter.h" +#include "icc-rpmh.h" +#include "sc7280.h" + +static struct qcom_icc_node qhm_qspi = { + .name = "qhm_qspi", + .id = SC7280_MASTER_QSPI_0, + .channels = 1, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_SLAVE_A1NOC_SNOC }, +}; + +static struct qcom_icc_node qhm_qup0 = { + .name = "qhm_qup0", + .id = SC7280_MASTER_QUP_0, + .channels = 1, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_SLAVE_A1NOC_SNOC }, +}; + +static struct qcom_icc_node qhm_qup1 = { + .name = "qhm_qup1", + .id = SC7280_MASTER_QUP_1, + .channels = 1, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_SLAVE_A1NOC_SNOC }, +}; + +static struct qcom_icc_node qnm_a1noc_cfg = { + .name = "qnm_a1noc_cfg", + .id = SC7280_MASTER_A1NOC_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_SLAVE_SERVICE_A1NOC }, +}; + +static struct qcom_icc_node xm_sdc1 = { + .name = "xm_sdc1", + .id = SC7280_MASTER_SDCC_1, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_SLAVE_A1NOC_SNOC }, +}; + +static struct qcom_icc_node xm_sdc2 = { + .name = "xm_sdc2", + .id = SC7280_MASTER_SDCC_2, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_SLAVE_A1NOC_SNOC }, +}; + +static struct qcom_icc_node xm_sdc4 = { + .name = "xm_sdc4", + .id = SC7280_MASTER_SDCC_4, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_SLAVE_A1NOC_SNOC }, +}; + +static struct qcom_icc_node xm_ufs_mem = { + .name = "xm_ufs_mem", + .id = SC7280_MASTER_UFS_MEM, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_SLAVE_A1NOC_SNOC }, +}; + +static struct qcom_icc_node xm_usb2 = { + .name = "xm_usb2", + .id = SC7280_MASTER_USB2, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_SLAVE_A1NOC_SNOC }, +}; + +static struct qcom_icc_node xm_usb3_0 = { + .name = "xm_usb3_0", + .id = SC7280_MASTER_USB3_0, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_SLAVE_A1NOC_SNOC }, +}; + +static struct qcom_icc_node qhm_qdss_bam = { + .name = "qhm_qdss_bam", + .id = SC7280_MASTER_QDSS_BAM, + .channels = 1, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_SLAVE_A2NOC_SNOC }, +}; + +static struct qcom_icc_node qnm_a2noc_cfg = { + .name = "qnm_a2noc_cfg", + .id = SC7280_MASTER_A2NOC_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_SLAVE_SERVICE_A2NOC }, +}; + +static struct qcom_icc_node qnm_cnoc_datapath = { + .name = "qnm_cnoc_datapath", + .id = SC7280_MASTER_CNOC_A2NOC, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_SLAVE_A2NOC_SNOC }, +}; + +static struct qcom_icc_node qxm_crypto = { + .name = "qxm_crypto", + .id = SC7280_MASTER_CRYPTO, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_SLAVE_A2NOC_SNOC }, +}; + +static struct qcom_icc_node qxm_ipa = { + .name = "qxm_ipa", + .id = SC7280_MASTER_IPA, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_SLAVE_A2NOC_SNOC }, +}; + +static struct qcom_icc_node xm_pcie3_0 = { + .name = "xm_pcie3_0", + .id = SC7280_MASTER_PCIE_0, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_SLAVE_ANOC_PCIE_GEM_NOC }, +}; + +static struct qcom_icc_node xm_pcie3_1 = { + .name = "xm_pcie3_1", + .id = SC7280_MASTER_PCIE_1, + .channels = 1, + .buswidth = 8, + .links = { SC7280_SLAVE_ANOC_PCIE_GEM_NOC }, +}; + +static struct qcom_icc_node xm_qdss_etr = { + .name = "xm_qdss_etr", + .id = SC7280_MASTER_QDSS_ETR, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_SLAVE_A2NOC_SNOC }, +}; + +static struct qcom_icc_node qup0_core_master = { + .name = "qup0_core_master", + .id = SC7280_MASTER_QUP_CORE_0, + .channels = 1, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_SLAVE_QUP_CORE_0 }, +}; + +static struct qcom_icc_node qup1_core_master = { + .name = "qup1_core_master", + .id = SC7280_MASTER_QUP_CORE_1, + .channels = 1, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_SLAVE_QUP_CORE_1 }, +}; + +static struct qcom_icc_node qnm_cnoc3_cnoc2 = { + .name = "qnm_cnoc3_cnoc2", + .id = SC7280_MASTER_CNOC3_CNOC2, + .channels = 1, + .buswidth = 8, + .num_links = 44, + .links = { SC7280_SLAVE_AHB2PHY_SOUTH, SC7280_SLAVE_AHB2PHY_NORTH, + SC7280_SLAVE_CAMERA_CFG, SC7280_SLAVE_CLK_CTL, + SC7280_SLAVE_CDSP_CFG, SC7280_SLAVE_RBCPR_CX_CFG, + SC7280_SLAVE_RBCPR_MX_CFG, SC7280_SLAVE_CRYPTO_0_CFG, + SC7280_SLAVE_CX_RDPM, SC7280_SLAVE_DCC_CFG, + SC7280_SLAVE_DISPLAY_CFG, SC7280_SLAVE_GFX3D_CFG, + SC7280_SLAVE_HWKM, SC7280_SLAVE_IMEM_CFG, + SC7280_SLAVE_IPA_CFG, SC7280_SLAVE_IPC_ROUTER_CFG, + SC7280_SLAVE_LPASS, SC7280_SLAVE_CNOC_MSS, + SC7280_SLAVE_MX_RDPM, SC7280_SLAVE_PCIE_0_CFG, + SC7280_SLAVE_PCIE_1_CFG, SC7280_SLAVE_PDM, + SC7280_SLAVE_PIMEM_CFG, SC7280_SLAVE_PKA_WRAPPER_CFG, + SC7280_SLAVE_PMU_WRAPPER_CFG, SC7280_SLAVE_QDSS_CFG, + SC7280_SLAVE_QSPI_0, SC7280_SLAVE_QUP_0, + SC7280_SLAVE_QUP_1, SC7280_SLAVE_SDCC_1, + SC7280_SLAVE_SDCC_2, SC7280_SLAVE_SDCC_4, + SC7280_SLAVE_SECURITY, SC7280_SLAVE_TCSR, + SC7280_SLAVE_TLMM, SC7280_SLAVE_UFS_MEM_CFG, + SC7280_SLAVE_USB2, SC7280_SLAVE_USB3_0, + SC7280_SLAVE_VENUS_CFG, SC7280_SLAVE_VSENSE_CTRL_CFG, + SC7280_SLAVE_A1NOC_CFG, SC7280_SLAVE_A2NOC_CFG, + SC7280_SLAVE_CNOC_MNOC_CFG, SC7280_SLAVE_SNOC_CFG }, +}; + +static struct qcom_icc_node xm_qdss_dap = { + .name = "xm_qdss_dap", + .id = SC7280_MASTER_QDSS_DAP, + .channels = 1, + .buswidth = 8, + .num_links = 45, + .links = { SC7280_SLAVE_AHB2PHY_SOUTH, SC7280_SLAVE_AHB2PHY_NORTH, + SC7280_SLAVE_CAMERA_CFG, SC7280_SLAVE_CLK_CTL, + SC7280_SLAVE_CDSP_CFG, SC7280_SLAVE_RBCPR_CX_CFG, + SC7280_SLAVE_RBCPR_MX_CFG, SC7280_SLAVE_CRYPTO_0_CFG, + SC7280_SLAVE_CX_RDPM, SC7280_SLAVE_DCC_CFG, + SC7280_SLAVE_DISPLAY_CFG, SC7280_SLAVE_GFX3D_CFG, + SC7280_SLAVE_HWKM, SC7280_SLAVE_IMEM_CFG, + SC7280_SLAVE_IPA_CFG, SC7280_SLAVE_IPC_ROUTER_CFG, + SC7280_SLAVE_LPASS, SC7280_SLAVE_CNOC_MSS, + SC7280_SLAVE_MX_RDPM, SC7280_SLAVE_PCIE_0_CFG, + SC7280_SLAVE_PCIE_1_CFG, SC7280_SLAVE_PDM, + SC7280_SLAVE_PIMEM_CFG, SC7280_SLAVE_PKA_WRAPPER_CFG, + SC7280_SLAVE_PMU_WRAPPER_CFG, SC7280_SLAVE_QDSS_CFG, + SC7280_SLAVE_QSPI_0, SC7280_SLAVE_QUP_0, + SC7280_SLAVE_QUP_1, SC7280_SLAVE_SDCC_1, + SC7280_SLAVE_SDCC_2, SC7280_SLAVE_SDCC_4, + SC7280_SLAVE_SECURITY, SC7280_SLAVE_TCSR, + SC7280_SLAVE_TLMM, SC7280_SLAVE_UFS_MEM_CFG, + SC7280_SLAVE_USB2, SC7280_SLAVE_USB3_0, + SC7280_SLAVE_VENUS_CFG, SC7280_SLAVE_VSENSE_CTRL_CFG, + SC7280_SLAVE_A1NOC_CFG, SC7280_SLAVE_A2NOC_CFG, + SC7280_SLAVE_CNOC2_CNOC3, SC7280_SLAVE_CNOC_MNOC_CFG, + SC7280_SLAVE_SNOC_CFG }, +}; + +static struct qcom_icc_node qnm_cnoc2_cnoc3 = { + .name = "qnm_cnoc2_cnoc3", + .id = SC7280_MASTER_CNOC2_CNOC3, + .channels = 1, + .buswidth = 8, + .num_links = 9, + .links = { SC7280_SLAVE_AOSS, SC7280_SLAVE_APPSS, + SC7280_SLAVE_CNOC_A2NOC, SC7280_SLAVE_DDRSS_CFG, + SC7280_SLAVE_BOOT_IMEM, SC7280_SLAVE_IMEM, + SC7280_SLAVE_PIMEM, SC7280_SLAVE_QDSS_STM, + SC7280_SLAVE_TCU }, +}; + +static struct qcom_icc_node qnm_gemnoc_cnoc = { + .name = "qnm_gemnoc_cnoc", + .id = SC7280_MASTER_GEM_NOC_CNOC, + .channels = 1, + .buswidth = 16, + .num_links = 9, + .links = { SC7280_SLAVE_AOSS, SC7280_SLAVE_APPSS, + SC7280_SLAVE_CNOC3_CNOC2, SC7280_SLAVE_DDRSS_CFG, + SC7280_SLAVE_BOOT_IMEM, SC7280_SLAVE_IMEM, + SC7280_SLAVE_PIMEM, SC7280_SLAVE_QDSS_STM, + SC7280_SLAVE_TCU }, +}; + +static struct qcom_icc_node qnm_gemnoc_pcie = { + .name = "qnm_gemnoc_pcie", + .id = SC7280_MASTER_GEM_NOC_PCIE_SNOC, + .channels = 1, + .buswidth = 8, + .num_links = 2, + .links = { SC7280_SLAVE_PCIE_0, SC7280_SLAVE_PCIE_1 }, +}; + +static struct qcom_icc_node qnm_cnoc_dc_noc = { + .name = "qnm_cnoc_dc_noc", + .id = SC7280_MASTER_CNOC_DC_NOC, + .channels = 1, + .buswidth = 4, + .num_links = 2, + .links = { SC7280_SLAVE_LLCC_CFG, SC7280_SLAVE_GEM_NOC_CFG }, +}; + +static struct qcom_icc_node alm_gpu_tcu = { + .name = "alm_gpu_tcu", + .id = SC7280_MASTER_GPU_TCU, + .channels = 1, + .buswidth = 8, + .num_links = 2, + .links = { SC7280_SLAVE_GEM_NOC_CNOC, SC7280_SLAVE_LLCC }, +}; + +static struct qcom_icc_node alm_sys_tcu = { + .name = "alm_sys_tcu", + .id = SC7280_MASTER_SYS_TCU, + .channels = 1, + .buswidth = 8, + .num_links = 2, + .links = { SC7280_SLAVE_GEM_NOC_CNOC, SC7280_SLAVE_LLCC }, +}; + +static struct qcom_icc_node chm_apps = { + .name = "chm_apps", + .id = SC7280_MASTER_APPSS_PROC, + .channels = 1, + .buswidth = 32, + .num_links = 3, + .links = { SC7280_SLAVE_GEM_NOC_CNOC, SC7280_SLAVE_LLCC, + SC7280_SLAVE_MEM_NOC_PCIE_SNOC }, +}; + +static struct qcom_icc_node qnm_cmpnoc = { + .name = "qnm_cmpnoc", + .id = SC7280_MASTER_COMPUTE_NOC, + .channels = 2, + .buswidth = 32, + .num_links = 2, + .links = { SC7280_SLAVE_GEM_NOC_CNOC, SC7280_SLAVE_LLCC }, +}; + +static struct qcom_icc_node qnm_gemnoc_cfg = { + .name = "qnm_gemnoc_cfg", + .id = SC7280_MASTER_GEM_NOC_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 5, + .links = { SC7280_SLAVE_MSS_PROC_MS_MPU_CFG, SC7280_SLAVE_MCDMA_MS_MPU_CFG, + SC7280_SLAVE_SERVICE_GEM_NOC_1, SC7280_SLAVE_SERVICE_GEM_NOC_2, + SC7280_SLAVE_SERVICE_GEM_NOC }, +}; + +static struct qcom_icc_node qnm_gpu = { + .name = "qnm_gpu", + .id = SC7280_MASTER_GFX3D, + .channels = 2, + .buswidth = 32, + .num_links = 2, + .links = { SC7280_SLAVE_GEM_NOC_CNOC, SC7280_SLAVE_LLCC }, +}; + +static struct qcom_icc_node qnm_mnoc_hf = { + .name = "qnm_mnoc_hf", + .id = SC7280_MASTER_MNOC_HF_MEM_NOC, + .channels = 2, + .buswidth = 32, + .num_links = 1, + .links = { SC7280_SLAVE_LLCC }, +}; + +static struct qcom_icc_node qnm_mnoc_sf = { + .name = "qnm_mnoc_sf", + .id = SC7280_MASTER_MNOC_SF_MEM_NOC, + .channels = 1, + .buswidth = 32, + .num_links = 2, + .links = { SC7280_SLAVE_GEM_NOC_CNOC, SC7280_SLAVE_LLCC }, +}; + +static struct qcom_icc_node qnm_pcie = { + .name = "qnm_pcie", + .id = SC7280_MASTER_ANOC_PCIE_GEM_NOC, + .channels = 1, + .buswidth = 16, + .num_links = 2, + .links = { SC7280_SLAVE_GEM_NOC_CNOC, SC7280_SLAVE_LLCC }, +}; + +static struct qcom_icc_node qnm_snoc_gc = { + .name = "qnm_snoc_gc", + .id = SC7280_MASTER_SNOC_GC_MEM_NOC, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_SLAVE_LLCC }, +}; + +static struct qcom_icc_node qnm_snoc_sf = { + .name = "qnm_snoc_sf", + .id = SC7280_MASTER_SNOC_SF_MEM_NOC, + .channels = 1, + .buswidth = 16, + .num_links = 3, + .links = { SC7280_SLAVE_GEM_NOC_CNOC, SC7280_SLAVE_LLCC, + SC7280_SLAVE_MEM_NOC_PCIE_SNOC }, +}; + +static struct qcom_icc_node qhm_config_noc = { + .name = "qhm_config_noc", + .id = SC7280_MASTER_CNOC_LPASS_AG_NOC, + .channels = 1, + .buswidth = 4, + .num_links = 6, + .links = { SC7280_SLAVE_LPASS_CORE_CFG, SC7280_SLAVE_LPASS_LPI_CFG, + SC7280_SLAVE_LPASS_MPU_CFG, SC7280_SLAVE_LPASS_TOP_CFG, + SC7280_SLAVE_SERVICES_LPASS_AML_NOC, SC7280_SLAVE_SERVICE_LPASS_AG_NOC }, +}; + +static struct qcom_icc_node llcc_mc = { + .name = "llcc_mc", + .id = SC7280_MASTER_LLCC, + .channels = 2, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_SLAVE_EBI1 }, +}; + +static struct qcom_icc_node qnm_mnoc_cfg = { + .name = "qnm_mnoc_cfg", + .id = SC7280_MASTER_CNOC_MNOC_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_SLAVE_SERVICE_MNOC }, +}; + +static struct qcom_icc_node qnm_video0 = { + .name = "qnm_video0", + .id = SC7280_MASTER_VIDEO_P0, + .channels = 1, + .buswidth = 32, + .num_links = 1, + .links = { SC7280_SLAVE_MNOC_SF_MEM_NOC }, +}; + +static struct qcom_icc_node qnm_video_cpu = { + .name = "qnm_video_cpu", + .id = SC7280_MASTER_VIDEO_PROC, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_SLAVE_MNOC_SF_MEM_NOC }, +}; + +static struct qcom_icc_node qxm_camnoc_hf = { + .name = "qxm_camnoc_hf", + .id = SC7280_MASTER_CAMNOC_HF, + .channels = 2, + .buswidth = 32, + .num_links = 1, + .links = { SC7280_SLAVE_MNOC_HF_MEM_NOC }, +}; + +static struct qcom_icc_node qxm_camnoc_icp = { + .name = "qxm_camnoc_icp", + .id = SC7280_MASTER_CAMNOC_ICP, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_SLAVE_MNOC_SF_MEM_NOC }, +}; + +static struct qcom_icc_node qxm_camnoc_sf = { + .name = "qxm_camnoc_sf", + .id = SC7280_MASTER_CAMNOC_SF, + .channels = 1, + .buswidth = 32, + .num_links = 1, + .links = { SC7280_SLAVE_MNOC_SF_MEM_NOC }, +}; + +static struct qcom_icc_node qxm_mdp0 = { + .name = "qxm_mdp0", + .id = SC7280_MASTER_MDP0, + .channels = 1, + .buswidth = 32, + .num_links = 1, + .links = { SC7280_SLAVE_MNOC_HF_MEM_NOC }, +}; + +static struct qcom_icc_node qhm_nsp_noc_config = { + .name = "qhm_nsp_noc_config", + .id = SC7280_MASTER_CDSP_NOC_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_SLAVE_SERVICE_NSP_NOC }, +}; + +static struct qcom_icc_node qxm_nsp = { + .name = "qxm_nsp", + .id = SC7280_MASTER_CDSP_PROC, + .channels = 2, + .buswidth = 32, + .num_links = 1, + .links = { SC7280_SLAVE_CDSP_MEM_NOC }, +}; + +static struct qcom_icc_node qnm_aggre1_noc = { + .name = "qnm_aggre1_noc", + .id = SC7280_MASTER_A1NOC_SNOC, + .channels = 1, + .buswidth = 16, + .num_links = 1, + .links = { SC7280_SLAVE_SNOC_GEM_NOC_SF }, +}; + +static struct qcom_icc_node qnm_aggre2_noc = { + .name = "qnm_aggre2_noc", + .id = SC7280_MASTER_A2NOC_SNOC, + .channels = 1, + .buswidth = 16, + .num_links = 1, + .links = { SC7280_SLAVE_SNOC_GEM_NOC_SF }, +}; + +static struct qcom_icc_node qnm_snoc_cfg = { + .name = "qnm_snoc_cfg", + .id = SC7280_MASTER_SNOC_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_SLAVE_SERVICE_SNOC }, +}; + +static struct qcom_icc_node qxm_pimem = { + .name = "qxm_pimem", + .id = SC7280_MASTER_PIMEM, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_SLAVE_SNOC_GEM_NOC_GC }, +}; + +static struct qcom_icc_node xm_gic = { + .name = "xm_gic", + .id = SC7280_MASTER_GIC, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_SLAVE_SNOC_GEM_NOC_GC }, +}; + +static struct qcom_icc_node qns_a1noc_snoc = { + .name = "qns_a1noc_snoc", + .id = SC7280_SLAVE_A1NOC_SNOC, + .channels = 1, + .buswidth = 16, + .num_links = 1, + .links = { SC7280_MASTER_A1NOC_SNOC }, +}; + +static struct qcom_icc_node srvc_aggre1_noc = { + .name = "srvc_aggre1_noc", + .id = SC7280_SLAVE_SERVICE_A1NOC, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qns_a2noc_snoc = { + .name = "qns_a2noc_snoc", + .id = SC7280_SLAVE_A2NOC_SNOC, + .channels = 1, + .buswidth = 16, + .num_links = 1, + .links = { SC7280_MASTER_A2NOC_SNOC }, +}; + +static struct qcom_icc_node qns_pcie_mem_noc = { + .name = "qns_pcie_mem_noc", + .id = SC7280_SLAVE_ANOC_PCIE_GEM_NOC, + .channels = 1, + .buswidth = 16, + .num_links = 1, + .links = { SC7280_MASTER_ANOC_PCIE_GEM_NOC }, +}; + +static struct qcom_icc_node srvc_aggre2_noc = { + .name = "srvc_aggre2_noc", + .id = SC7280_SLAVE_SERVICE_A2NOC, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qup0_core_slave = { + .name = "qup0_core_slave", + .id = SC7280_SLAVE_QUP_CORE_0, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qup1_core_slave = { + .name = "qup1_core_slave", + .id = SC7280_SLAVE_QUP_CORE_1, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_ahb2phy0 = { + .name = "qhs_ahb2phy0", + .id = SC7280_SLAVE_AHB2PHY_SOUTH, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_ahb2phy1 = { + .name = "qhs_ahb2phy1", + .id = SC7280_SLAVE_AHB2PHY_NORTH, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_camera_cfg = { + .name = "qhs_camera_cfg", + .id = SC7280_SLAVE_CAMERA_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_clk_ctl = { + .name = "qhs_clk_ctl", + .id = SC7280_SLAVE_CLK_CTL, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_compute_cfg = { + .name = "qhs_compute_cfg", + .id = SC7280_SLAVE_CDSP_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_MASTER_CDSP_NOC_CFG }, +}; + +static struct qcom_icc_node qhs_cpr_cx = { + .name = "qhs_cpr_cx", + .id = SC7280_SLAVE_RBCPR_CX_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_cpr_mx = { + .name = "qhs_cpr_mx", + .id = SC7280_SLAVE_RBCPR_MX_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_crypto0_cfg = { + .name = "qhs_crypto0_cfg", + .id = SC7280_SLAVE_CRYPTO_0_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_cx_rdpm = { + .name = "qhs_cx_rdpm", + .id = SC7280_SLAVE_CX_RDPM, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_dcc_cfg = { + .name = "qhs_dcc_cfg", + .id = SC7280_SLAVE_DCC_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_display_cfg = { + .name = "qhs_display_cfg", + .id = SC7280_SLAVE_DISPLAY_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_gpuss_cfg = { + .name = "qhs_gpuss_cfg", + .id = SC7280_SLAVE_GFX3D_CFG, + .channels = 1, + .buswidth = 8, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_hwkm = { + .name = "qhs_hwkm", + .id = SC7280_SLAVE_HWKM, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_imem_cfg = { + .name = "qhs_imem_cfg", + .id = SC7280_SLAVE_IMEM_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_ipa = { + .name = "qhs_ipa", + .id = SC7280_SLAVE_IPA_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_ipc_router = { + .name = "qhs_ipc_router", + .id = SC7280_SLAVE_IPC_ROUTER_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_lpass_cfg = { + .name = "qhs_lpass_cfg", + .id = SC7280_SLAVE_LPASS, + .channels = 1, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_MASTER_CNOC_LPASS_AG_NOC }, +}; + +static struct qcom_icc_node qhs_mss_cfg = { + .name = "qhs_mss_cfg", + .id = SC7280_SLAVE_CNOC_MSS, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_mx_rdpm = { + .name = "qhs_mx_rdpm", + .id = SC7280_SLAVE_MX_RDPM, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_pcie0_cfg = { + .name = "qhs_pcie0_cfg", + .id = SC7280_SLAVE_PCIE_0_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_pcie1_cfg = { + .name = "qhs_pcie1_cfg", + .id = SC7280_SLAVE_PCIE_1_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_pdm = { + .name = "qhs_pdm", + .id = SC7280_SLAVE_PDM, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_pimem_cfg = { + .name = "qhs_pimem_cfg", + .id = SC7280_SLAVE_PIMEM_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_pka_wrapper_cfg = { + .name = "qhs_pka_wrapper_cfg", + .id = SC7280_SLAVE_PKA_WRAPPER_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_pmu_wrapper_cfg = { + .name = "qhs_pmu_wrapper_cfg", + .id = SC7280_SLAVE_PMU_WRAPPER_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_qdss_cfg = { + .name = "qhs_qdss_cfg", + .id = SC7280_SLAVE_QDSS_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_qspi = { + .name = "qhs_qspi", + .id = SC7280_SLAVE_QSPI_0, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_qup0 = { + .name = "qhs_qup0", + .id = SC7280_SLAVE_QUP_0, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_qup1 = { + .name = "qhs_qup1", + .id = SC7280_SLAVE_QUP_1, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_sdc1 = { + .name = "qhs_sdc1", + .id = SC7280_SLAVE_SDCC_1, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_sdc2 = { + .name = "qhs_sdc2", + .id = SC7280_SLAVE_SDCC_2, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_sdc4 = { + .name = "qhs_sdc4", + .id = SC7280_SLAVE_SDCC_4, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_security = { + .name = "qhs_security", + .id = SC7280_SLAVE_SECURITY, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_tcsr = { + .name = "qhs_tcsr", + .id = SC7280_SLAVE_TCSR, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_tlmm = { + .name = "qhs_tlmm", + .id = SC7280_SLAVE_TLMM, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_ufs_mem_cfg = { + .name = "qhs_ufs_mem_cfg", + .id = SC7280_SLAVE_UFS_MEM_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_usb2 = { + .name = "qhs_usb2", + .id = SC7280_SLAVE_USB2, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_usb3_0 = { + .name = "qhs_usb3_0", + .id = SC7280_SLAVE_USB3_0, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_venus_cfg = { + .name = "qhs_venus_cfg", + .id = SC7280_SLAVE_VENUS_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_vsense_ctrl_cfg = { + .name = "qhs_vsense_ctrl_cfg", + .id = SC7280_SLAVE_VSENSE_CTRL_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qns_a1_noc_cfg = { + .name = "qns_a1_noc_cfg", + .id = SC7280_SLAVE_A1NOC_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_MASTER_A1NOC_CFG }, +}; + +static struct qcom_icc_node qns_a2_noc_cfg = { + .name = "qns_a2_noc_cfg", + .id = SC7280_SLAVE_A2NOC_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_MASTER_A2NOC_CFG }, +}; + +static struct qcom_icc_node qns_cnoc2_cnoc3 = { + .name = "qns_cnoc2_cnoc3", + .id = SC7280_SLAVE_CNOC2_CNOC3, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_MASTER_CNOC2_CNOC3 }, +}; + +static struct qcom_icc_node qns_mnoc_cfg = { + .name = "qns_mnoc_cfg", + .id = SC7280_SLAVE_CNOC_MNOC_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_MASTER_CNOC_MNOC_CFG }, +}; + +static struct qcom_icc_node qns_snoc_cfg = { + .name = "qns_snoc_cfg", + .id = SC7280_SLAVE_SNOC_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_MASTER_SNOC_CFG }, +}; + +static struct qcom_icc_node qhs_aoss = { + .name = "qhs_aoss", + .id = SC7280_SLAVE_AOSS, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_apss = { + .name = "qhs_apss", + .id = SC7280_SLAVE_APPSS, + .channels = 1, + .buswidth = 8, + .num_links = 0, +}; + +static struct qcom_icc_node qns_cnoc3_cnoc2 = { + .name = "qns_cnoc3_cnoc2", + .id = SC7280_SLAVE_CNOC3_CNOC2, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_MASTER_CNOC3_CNOC2 }, +}; + +static struct qcom_icc_node qns_cnoc_a2noc = { + .name = "qns_cnoc_a2noc", + .id = SC7280_SLAVE_CNOC_A2NOC, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_MASTER_CNOC_A2NOC }, +}; + +static struct qcom_icc_node qns_ddrss_cfg = { + .name = "qns_ddrss_cfg", + .id = SC7280_SLAVE_DDRSS_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_MASTER_CNOC_DC_NOC }, +}; + +static struct qcom_icc_node qxs_boot_imem = { + .name = "qxs_boot_imem", + .id = SC7280_SLAVE_BOOT_IMEM, + .channels = 1, + .buswidth = 8, + .num_links = 0, +}; + +static struct qcom_icc_node qxs_imem = { + .name = "qxs_imem", + .id = SC7280_SLAVE_IMEM, + .channels = 1, + .buswidth = 8, + .num_links = 0, +}; + +static struct qcom_icc_node qxs_pimem = { + .name = "qxs_pimem", + .id = SC7280_SLAVE_PIMEM, + .channels = 1, + .buswidth = 8, + .num_links = 0, +}; + +static struct qcom_icc_node xs_pcie_0 = { + .name = "xs_pcie_0", + .id = SC7280_SLAVE_PCIE_0, + .channels = 1, + .buswidth = 8, + .num_links = 0, +}; + +static struct qcom_icc_node xs_pcie_1 = { + .name = "xs_pcie_1", + .id = SC7280_SLAVE_PCIE_1, + .channels = 1, + .buswidth = 8, + .num_links = 0, +}; + +static struct qcom_icc_node xs_qdss_stm = { + .name = "xs_qdss_stm", + .id = SC7280_SLAVE_QDSS_STM, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node xs_sys_tcu_cfg = { + .name = "xs_sys_tcu_cfg", + .id = SC7280_SLAVE_TCU, + .channels = 1, + .buswidth = 8, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_llcc = { + .name = "qhs_llcc", + .id = SC7280_SLAVE_LLCC_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qns_gemnoc = { + .name = "qns_gemnoc", + .id = SC7280_SLAVE_GEM_NOC_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 1, + .links = { SC7280_MASTER_GEM_NOC_CFG }, +}; + +static struct qcom_icc_node qhs_mdsp_ms_mpu_cfg = { + .name = "qhs_mdsp_ms_mpu_cfg", + .id = SC7280_SLAVE_MSS_PROC_MS_MPU_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_modem_ms_mpu_cfg = { + .name = "qhs_modem_ms_mpu_cfg", + .id = SC7280_SLAVE_MCDMA_MS_MPU_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qns_gem_noc_cnoc = { + .name = "qns_gem_noc_cnoc", + .id = SC7280_SLAVE_GEM_NOC_CNOC, + .channels = 1, + .buswidth = 16, + .num_links = 1, + .links = { SC7280_MASTER_GEM_NOC_CNOC }, +}; + +static struct qcom_icc_node qns_llcc = { + .name = "qns_llcc", + .id = SC7280_SLAVE_LLCC, + .channels = 2, + .buswidth = 16, + .num_links = 1, + .links = { SC7280_MASTER_LLCC }, +}; + +static struct qcom_icc_node qns_pcie = { + .name = "qns_pcie", + .id = SC7280_SLAVE_MEM_NOC_PCIE_SNOC, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_MASTER_GEM_NOC_PCIE_SNOC }, +}; + +static struct qcom_icc_node srvc_even_gemnoc = { + .name = "srvc_even_gemnoc", + .id = SC7280_SLAVE_SERVICE_GEM_NOC_1, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node srvc_odd_gemnoc = { + .name = "srvc_odd_gemnoc", + .id = SC7280_SLAVE_SERVICE_GEM_NOC_2, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node srvc_sys_gemnoc = { + .name = "srvc_sys_gemnoc", + .id = SC7280_SLAVE_SERVICE_GEM_NOC, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_lpass_core = { + .name = "qhs_lpass_core", + .id = SC7280_SLAVE_LPASS_CORE_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_lpass_lpi = { + .name = "qhs_lpass_lpi", + .id = SC7280_SLAVE_LPASS_LPI_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_lpass_mpu = { + .name = "qhs_lpass_mpu", + .id = SC7280_SLAVE_LPASS_MPU_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qhs_lpass_top = { + .name = "qhs_lpass_top", + .id = SC7280_SLAVE_LPASS_TOP_CFG, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node srvc_niu_aml_noc = { + .name = "srvc_niu_aml_noc", + .id = SC7280_SLAVE_SERVICES_LPASS_AML_NOC, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node srvc_niu_lpass_agnoc = { + .name = "srvc_niu_lpass_agnoc", + .id = SC7280_SLAVE_SERVICE_LPASS_AG_NOC, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node ebi = { + .name = "ebi", + .id = SC7280_SLAVE_EBI1, + .channels = 2, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qns_mem_noc_hf = { + .name = "qns_mem_noc_hf", + .id = SC7280_SLAVE_MNOC_HF_MEM_NOC, + .channels = 2, + .buswidth = 32, + .num_links = 1, + .links = { SC7280_MASTER_MNOC_HF_MEM_NOC }, +}; + +static struct qcom_icc_node qns_mem_noc_sf = { + .name = "qns_mem_noc_sf", + .id = SC7280_SLAVE_MNOC_SF_MEM_NOC, + .channels = 1, + .buswidth = 32, + .num_links = 1, + .links = { SC7280_MASTER_MNOC_SF_MEM_NOC }, +}; + +static struct qcom_icc_node srvc_mnoc = { + .name = "srvc_mnoc", + .id = SC7280_SLAVE_SERVICE_MNOC, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qns_nsp_gemnoc = { + .name = "qns_nsp_gemnoc", + .id = SC7280_SLAVE_CDSP_MEM_NOC, + .channels = 2, + .buswidth = 32, + .num_links = 1, + .links = { SC7280_MASTER_COMPUTE_NOC }, +}; + +static struct qcom_icc_node service_nsp_noc = { + .name = "service_nsp_noc", + .id = SC7280_SLAVE_SERVICE_NSP_NOC, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_node qns_gemnoc_gc = { + .name = "qns_gemnoc_gc", + .id = SC7280_SLAVE_SNOC_GEM_NOC_GC, + .channels = 1, + .buswidth = 8, + .num_links = 1, + .links = { SC7280_MASTER_SNOC_GC_MEM_NOC }, +}; + +static struct qcom_icc_node qns_gemnoc_sf = { + .name = "qns_gemnoc_sf", + .id = SC7280_SLAVE_SNOC_GEM_NOC_SF, + .channels = 1, + .buswidth = 16, + .num_links = 1, + .links = { SC7280_MASTER_SNOC_SF_MEM_NOC }, +}; + +static struct qcom_icc_node srvc_snoc = { + .name = "srvc_snoc", + .id = SC7280_SLAVE_SERVICE_SNOC, + .channels = 1, + .buswidth = 4, + .num_links = 0, +}; + +static struct qcom_icc_bcm bcm_acv = { + .name = "ACV", + .num_nodes = 1, + .nodes = { &ebi }, +}; + +static struct qcom_icc_bcm bcm_ce0 = { + .name = "CE0", + .num_nodes = 1, + .nodes = { &qxm_crypto }, +}; + +static struct qcom_icc_bcm bcm_cn0 = { + .name = "CN0", + .keepalive = true, + .num_nodes = 2, + .nodes = { &qnm_gemnoc_cnoc, &qnm_gemnoc_pcie }, +}; + +static struct qcom_icc_bcm bcm_cn1 = { + .name = "CN1", + .num_nodes = 47, + .nodes = { &qnm_cnoc3_cnoc2, &xm_qdss_dap, + &qhs_ahb2phy0, &qhs_ahb2phy1, + &qhs_camera_cfg, &qhs_clk_ctl, + &qhs_compute_cfg, &qhs_cpr_cx, + &qhs_cpr_mx, &qhs_crypto0_cfg, + &qhs_cx_rdpm, &qhs_dcc_cfg, + &qhs_display_cfg, &qhs_gpuss_cfg, + &qhs_hwkm, &qhs_imem_cfg, + &qhs_ipa, &qhs_ipc_router, + &qhs_mss_cfg, &qhs_mx_rdpm, + &qhs_pcie0_cfg, &qhs_pcie1_cfg, + &qhs_pimem_cfg, &qhs_pka_wrapper_cfg, + &qhs_pmu_wrapper_cfg, &qhs_qdss_cfg, + &qhs_qup0, &qhs_qup1, + &qhs_security, &qhs_tcsr, + &qhs_tlmm, &qhs_ufs_mem_cfg, &qhs_usb2, + &qhs_usb3_0, &qhs_venus_cfg, + &qhs_vsense_ctrl_cfg, &qns_a1_noc_cfg, + &qns_a2_noc_cfg, &qns_cnoc2_cnoc3, + &qns_mnoc_cfg, &qns_snoc_cfg, + &qnm_cnoc2_cnoc3, &qhs_aoss, + &qhs_apss, &qns_cnoc3_cnoc2, + &qns_cnoc_a2noc, &qns_ddrss_cfg }, +}; + +static struct qcom_icc_bcm bcm_cn2 = { + .name = "CN2", + .num_nodes = 6, + .nodes = { &qhs_lpass_cfg, &qhs_pdm, + &qhs_qspi, &qhs_sdc1, + &qhs_sdc2, &qhs_sdc4 }, +}; + +static struct qcom_icc_bcm bcm_co0 = { + .name = "CO0", + .num_nodes = 1, + .nodes = { &qns_nsp_gemnoc }, +}; + +static struct qcom_icc_bcm bcm_co3 = { + .name = "CO3", + .num_nodes = 1, + .nodes = { &qxm_nsp }, +}; + +static struct qcom_icc_bcm bcm_mc0 = { + .name = "MC0", + .keepalive = true, + .num_nodes = 1, + .nodes = { &ebi }, +}; + +static struct qcom_icc_bcm bcm_mm0 = { + .name = "MM0", + .keepalive = true, + .num_nodes = 1, + .nodes = { &qns_mem_noc_hf }, +}; + +static struct qcom_icc_bcm bcm_mm1 = { + .name = "MM1", + .num_nodes = 2, + .nodes = { &qxm_camnoc_hf, &qxm_mdp0 }, +}; + +static struct qcom_icc_bcm bcm_mm4 = { + .name = "MM4", + .num_nodes = 1, + .nodes = { &qns_mem_noc_sf }, +}; + +static struct qcom_icc_bcm bcm_mm5 = { + .name = "MM5", + .num_nodes = 3, + .nodes = { &qnm_video0, &qxm_camnoc_icp, + &qxm_camnoc_sf }, +}; + +static struct qcom_icc_bcm bcm_qup0 = { + .name = "QUP0", + .vote_scale = 1, + .num_nodes = 1, + .nodes = { &qup0_core_slave }, +}; + +static struct qcom_icc_bcm bcm_qup1 = { + .name = "QUP1", + .vote_scale = 1, + .num_nodes = 1, + .nodes = { &qup1_core_slave }, +}; + +static struct qcom_icc_bcm bcm_sh0 = { + .name = "SH0", + .keepalive = true, + .num_nodes = 1, + .nodes = { &qns_llcc }, +}; + +static struct qcom_icc_bcm bcm_sh2 = { + .name = "SH2", + .num_nodes = 2, + .nodes = { &alm_gpu_tcu, &alm_sys_tcu }, +}; + +static struct qcom_icc_bcm bcm_sh3 = { + .name = "SH3", + .num_nodes = 1, + .nodes = { &qnm_cmpnoc }, +}; + +static struct qcom_icc_bcm bcm_sh4 = { + .name = "SH4", + .num_nodes = 1, + .nodes = { &chm_apps }, +}; + +static struct qcom_icc_bcm bcm_sn0 = { + .name = "SN0", + .keepalive = true, + .num_nodes = 1, + .nodes = { &qns_gemnoc_sf }, +}; + +static struct qcom_icc_bcm bcm_sn2 = { + .name = "SN2", + .num_nodes = 1, + .nodes = { &qns_gemnoc_gc }, +}; + +static struct qcom_icc_bcm bcm_sn3 = { + .name = "SN3", + .num_nodes = 1, + .nodes = { &qxs_pimem }, +}; + +static struct qcom_icc_bcm bcm_sn4 = { + .name = "SN4", + .num_nodes = 1, + .nodes = { &xs_qdss_stm }, +}; + +static struct qcom_icc_bcm bcm_sn5 = { + .name = "SN5", + .num_nodes = 1, + .nodes = { &xm_pcie3_0 }, +}; + +static struct qcom_icc_bcm bcm_sn6 = { + .name = "SN6", + .num_nodes = 1, + .nodes = { &xm_pcie3_1 }, +}; + +static struct qcom_icc_bcm bcm_sn7 = { + .name = "SN7", + .num_nodes = 1, + .nodes = { &qnm_aggre1_noc }, +}; + +static struct qcom_icc_bcm bcm_sn8 = { + .name = "SN8", + .num_nodes = 1, + .nodes = { &qnm_aggre2_noc }, +}; + +static struct qcom_icc_bcm bcm_sn14 = { + .name = "SN14", + .num_nodes = 1, + .nodes = { &qns_pcie_mem_noc }, +}; + +static struct qcom_icc_bcm *aggre1_noc_bcms[] = { + &bcm_sn5, + &bcm_sn6, + &bcm_sn14, +}; + +static struct qcom_icc_node *aggre1_noc_nodes[] = { + [MASTER_QSPI_0] = &qhm_qspi, + [MASTER_QUP_0] = &qhm_qup0, + [MASTER_QUP_1] = &qhm_qup1, + [MASTER_A1NOC_CFG] = &qnm_a1noc_cfg, + [MASTER_PCIE_0] = &xm_pcie3_0, + [MASTER_PCIE_1] = &xm_pcie3_1, + [MASTER_SDCC_1] = &xm_sdc1, + [MASTER_SDCC_2] = &xm_sdc2, + [MASTER_SDCC_4] = &xm_sdc4, + [MASTER_UFS_MEM] = &xm_ufs_mem, + [MASTER_USB2] = &xm_usb2, + [MASTER_USB3_0] = &xm_usb3_0, + [SLAVE_A1NOC_SNOC] = &qns_a1noc_snoc, + [SLAVE_ANOC_PCIE_GEM_NOC] = &qns_pcie_mem_noc, + [SLAVE_SERVICE_A1NOC] = &srvc_aggre1_noc, +}; + +static struct qcom_icc_desc sc7280_aggre1_noc = { + .nodes = aggre1_noc_nodes, + .num_nodes = ARRAY_SIZE(aggre1_noc_nodes), + .bcms = aggre1_noc_bcms, + .num_bcms = ARRAY_SIZE(aggre1_noc_bcms), +}; + +static struct qcom_icc_bcm *aggre2_noc_bcms[] = { + &bcm_ce0, +}; + +static struct qcom_icc_node *aggre2_noc_nodes[] = { + [MASTER_QDSS_BAM] = &qhm_qdss_bam, + [MASTER_A2NOC_CFG] = &qnm_a2noc_cfg, + [MASTER_CNOC_A2NOC] = &qnm_cnoc_datapath, + [MASTER_CRYPTO] = &qxm_crypto, + [MASTER_IPA] = &qxm_ipa, + [MASTER_QDSS_ETR] = &xm_qdss_etr, + [SLAVE_A2NOC_SNOC] = &qns_a2noc_snoc, + [SLAVE_SERVICE_A2NOC] = &srvc_aggre2_noc, +}; + +static struct qcom_icc_desc sc7280_aggre2_noc = { + .nodes = aggre2_noc_nodes, + .num_nodes = ARRAY_SIZE(aggre2_noc_nodes), + .bcms = aggre2_noc_bcms, + .num_bcms = ARRAY_SIZE(aggre2_noc_bcms), +}; + +static struct qcom_icc_bcm *clk_virt_bcms[] = { + &bcm_qup0, + &bcm_qup1, +}; + +static struct qcom_icc_node *clk_virt_nodes[] = { + [MASTER_QUP_CORE_0] = &qup0_core_master, + [MASTER_QUP_CORE_1] = &qup1_core_master, + [SLAVE_QUP_CORE_0] = &qup0_core_slave, + [SLAVE_QUP_CORE_1] = &qup1_core_slave, +}; + +static struct qcom_icc_desc sc7280_clk_virt = { + .nodes = clk_virt_nodes, + .num_nodes = ARRAY_SIZE(clk_virt_nodes), + .bcms = clk_virt_bcms, + .num_bcms = ARRAY_SIZE(clk_virt_bcms), +}; + +static struct qcom_icc_bcm *cnoc2_bcms[] = { + &bcm_cn1, + &bcm_cn2, +}; + +static struct qcom_icc_node *cnoc2_nodes[] = { + [MASTER_CNOC3_CNOC2] = &qnm_cnoc3_cnoc2, + [MASTER_QDSS_DAP] = &xm_qdss_dap, + [SLAVE_AHB2PHY_SOUTH] = &qhs_ahb2phy0, + [SLAVE_AHB2PHY_NORTH] = &qhs_ahb2phy1, + [SLAVE_CAMERA_CFG] = &qhs_camera_cfg, + [SLAVE_CLK_CTL] = &qhs_clk_ctl, + [SLAVE_CDSP_CFG] = &qhs_compute_cfg, + [SLAVE_RBCPR_CX_CFG] = &qhs_cpr_cx, + [SLAVE_RBCPR_MX_CFG] = &qhs_cpr_mx, + [SLAVE_CRYPTO_0_CFG] = &qhs_crypto0_cfg, + [SLAVE_CX_RDPM] = &qhs_cx_rdpm, + [SLAVE_DCC_CFG] = &qhs_dcc_cfg, + [SLAVE_DISPLAY_CFG] = &qhs_display_cfg, + [SLAVE_GFX3D_CFG] = &qhs_gpuss_cfg, + [SLAVE_HWKM] = &qhs_hwkm, + [SLAVE_IMEM_CFG] = &qhs_imem_cfg, + [SLAVE_IPA_CFG] = &qhs_ipa, + [SLAVE_IPC_ROUTER_CFG] = &qhs_ipc_router, + [SLAVE_LPASS] = &qhs_lpass_cfg, + [SLAVE_CNOC_MSS] = &qhs_mss_cfg, + [SLAVE_MX_RDPM] = &qhs_mx_rdpm, + [SLAVE_PCIE_0_CFG] = &qhs_pcie0_cfg, + [SLAVE_PCIE_1_CFG] = &qhs_pcie1_cfg, + [SLAVE_PDM] = &qhs_pdm, + [SLAVE_PIMEM_CFG] = &qhs_pimem_cfg, + [SLAVE_PKA_WRAPPER_CFG] = &qhs_pka_wrapper_cfg, + [SLAVE_PMU_WRAPPER_CFG] = &qhs_pmu_wrapper_cfg, + [SLAVE_QDSS_CFG] = &qhs_qdss_cfg, + [SLAVE_QSPI_0] = &qhs_qspi, + [SLAVE_QUP_0] = &qhs_qup0, + [SLAVE_QUP_1] = &qhs_qup1, + [SLAVE_SDCC_1] = &qhs_sdc1, + [SLAVE_SDCC_2] = &qhs_sdc2, + [SLAVE_SDCC_4] = &qhs_sdc4, + [SLAVE_SECURITY] = &qhs_security, + [SLAVE_TCSR] = &qhs_tcsr, + [SLAVE_TLMM] = &qhs_tlmm, + [SLAVE_UFS_MEM_CFG] = &qhs_ufs_mem_cfg, + [SLAVE_USB2] = &qhs_usb2, + [SLAVE_USB3_0] = &qhs_usb3_0, + [SLAVE_VENUS_CFG] = &qhs_venus_cfg, + [SLAVE_VSENSE_CTRL_CFG] = &qhs_vsense_ctrl_cfg, + [SLAVE_A1NOC_CFG] = &qns_a1_noc_cfg, + [SLAVE_A2NOC_CFG] = &qns_a2_noc_cfg, + [SLAVE_CNOC2_CNOC3] = &qns_cnoc2_cnoc3, + [SLAVE_CNOC_MNOC_CFG] = &qns_mnoc_cfg, + [SLAVE_SNOC_CFG] = &qns_snoc_cfg, +}; + +static struct qcom_icc_desc sc7280_cnoc2 = { + .nodes = cnoc2_nodes, + .num_nodes = ARRAY_SIZE(cnoc2_nodes), + .bcms = cnoc2_bcms, + .num_bcms = ARRAY_SIZE(cnoc2_bcms), +}; + +static struct qcom_icc_bcm *cnoc3_bcms[] = { + &bcm_cn0, + &bcm_cn1, + &bcm_sn3, + &bcm_sn4, +}; + +static struct qcom_icc_node *cnoc3_nodes[] = { + [MASTER_CNOC2_CNOC3] = &qnm_cnoc2_cnoc3, + [MASTER_GEM_NOC_CNOC] = &qnm_gemnoc_cnoc, + [MASTER_GEM_NOC_PCIE_SNOC] = &qnm_gemnoc_pcie, + [SLAVE_AOSS] = &qhs_aoss, + [SLAVE_APPSS] = &qhs_apss, + [SLAVE_CNOC3_CNOC2] = &qns_cnoc3_cnoc2, + [SLAVE_CNOC_A2NOC] = &qns_cnoc_a2noc, + [SLAVE_DDRSS_CFG] = &qns_ddrss_cfg, + [SLAVE_BOOT_IMEM] = &qxs_boot_imem, + [SLAVE_IMEM] = &qxs_imem, + [SLAVE_PIMEM] = &qxs_pimem, + [SLAVE_PCIE_0] = &xs_pcie_0, + [SLAVE_PCIE_1] = &xs_pcie_1, + [SLAVE_QDSS_STM] = &xs_qdss_stm, + [SLAVE_TCU] = &xs_sys_tcu_cfg, +}; + +static struct qcom_icc_desc sc7280_cnoc3 = { + .nodes = cnoc3_nodes, + .num_nodes = ARRAY_SIZE(cnoc3_nodes), + .bcms = cnoc3_bcms, + .num_bcms = ARRAY_SIZE(cnoc3_bcms), +}; + +static struct qcom_icc_bcm *dc_noc_bcms[] = { +}; + +static struct qcom_icc_node *dc_noc_nodes[] = { + [MASTER_CNOC_DC_NOC] = &qnm_cnoc_dc_noc, + [SLAVE_LLCC_CFG] = &qhs_llcc, + [SLAVE_GEM_NOC_CFG] = &qns_gemnoc, +}; + +static struct qcom_icc_desc sc7280_dc_noc = { + .nodes = dc_noc_nodes, + .num_nodes = ARRAY_SIZE(dc_noc_nodes), + .bcms = dc_noc_bcms, + .num_bcms = ARRAY_SIZE(dc_noc_bcms), +}; + +static struct qcom_icc_bcm *gem_noc_bcms[] = { + &bcm_sh0, + &bcm_sh2, + &bcm_sh3, + &bcm_sh4, +}; + +static struct qcom_icc_node *gem_noc_nodes[] = { + [MASTER_GPU_TCU] = &alm_gpu_tcu, + [MASTER_SYS_TCU] = &alm_sys_tcu, + [MASTER_APPSS_PROC] = &chm_apps, + [MASTER_COMPUTE_NOC] = &qnm_cmpnoc, + [MASTER_GEM_NOC_CFG] = &qnm_gemnoc_cfg, + [MASTER_GFX3D] = &qnm_gpu, + [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf, + [MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf, + [MASTER_ANOC_PCIE_GEM_NOC] = &qnm_pcie, + [MASTER_SNOC_GC_MEM_NOC] = &qnm_snoc_gc, + [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf, + [SLAVE_MSS_PROC_MS_MPU_CFG] = &qhs_mdsp_ms_mpu_cfg, + [SLAVE_MCDMA_MS_MPU_CFG] = &qhs_modem_ms_mpu_cfg, + [SLAVE_GEM_NOC_CNOC] = &qns_gem_noc_cnoc, + [SLAVE_LLCC] = &qns_llcc, + [SLAVE_MEM_NOC_PCIE_SNOC] = &qns_pcie, + [SLAVE_SERVICE_GEM_NOC_1] = &srvc_even_gemnoc, + [SLAVE_SERVICE_GEM_NOC_2] = &srvc_odd_gemnoc, + [SLAVE_SERVICE_GEM_NOC] = &srvc_sys_gemnoc, +}; + +static struct qcom_icc_desc sc7280_gem_noc = { + .nodes = gem_noc_nodes, + .num_nodes = ARRAY_SIZE(gem_noc_nodes), + .bcms = gem_noc_bcms, + .num_bcms = ARRAY_SIZE(gem_noc_bcms), +}; + +static struct qcom_icc_bcm *lpass_ag_noc_bcms[] = { +}; + +static struct qcom_icc_node *lpass_ag_noc_nodes[] = { + [MASTER_CNOC_LPASS_AG_NOC] = &qhm_config_noc, + [SLAVE_LPASS_CORE_CFG] = &qhs_lpass_core, + [SLAVE_LPASS_LPI_CFG] = &qhs_lpass_lpi, + [SLAVE_LPASS_MPU_CFG] = &qhs_lpass_mpu, + [SLAVE_LPASS_TOP_CFG] = &qhs_lpass_top, + [SLAVE_SERVICES_LPASS_AML_NOC] = &srvc_niu_aml_noc, + [SLAVE_SERVICE_LPASS_AG_NOC] = &srvc_niu_lpass_agnoc, +}; + +static struct qcom_icc_desc sc7280_lpass_ag_noc = { + .nodes = lpass_ag_noc_nodes, + .num_nodes = ARRAY_SIZE(lpass_ag_noc_nodes), + .bcms = lpass_ag_noc_bcms, + .num_bcms = ARRAY_SIZE(lpass_ag_noc_bcms), +}; + +static struct qcom_icc_bcm *mc_virt_bcms[] = { + &bcm_acv, + &bcm_mc0, +}; + +static struct qcom_icc_node *mc_virt_nodes[] = { + [MASTER_LLCC] = &llcc_mc, + [SLAVE_EBI1] = &ebi, +}; + +static struct qcom_icc_desc sc7280_mc_virt = { + .nodes = mc_virt_nodes, + .num_nodes = ARRAY_SIZE(mc_virt_nodes), + .bcms = mc_virt_bcms, + .num_bcms = ARRAY_SIZE(mc_virt_bcms), +}; + +static struct qcom_icc_bcm *mmss_noc_bcms[] = { + &bcm_mm0, + &bcm_mm1, + &bcm_mm4, + &bcm_mm5, +}; + +static struct qcom_icc_node *mmss_noc_nodes[] = { + [MASTER_CNOC_MNOC_CFG] = &qnm_mnoc_cfg, + [MASTER_VIDEO_P0] = &qnm_video0, + [MASTER_VIDEO_PROC] = &qnm_video_cpu, + [MASTER_CAMNOC_HF] = &qxm_camnoc_hf, + [MASTER_CAMNOC_ICP] = &qxm_camnoc_icp, + [MASTER_CAMNOC_SF] = &qxm_camnoc_sf, + [MASTER_MDP0] = &qxm_mdp0, + [SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf, + [SLAVE_MNOC_SF_MEM_NOC] = &qns_mem_noc_sf, + [SLAVE_SERVICE_MNOC] = &srvc_mnoc, +}; + +static struct qcom_icc_desc sc7280_mmss_noc = { + .nodes = mmss_noc_nodes, + .num_nodes = ARRAY_SIZE(mmss_noc_nodes), + .bcms = mmss_noc_bcms, + .num_bcms = ARRAY_SIZE(mmss_noc_bcms), +}; + +static struct qcom_icc_bcm *nsp_noc_bcms[] = { + &bcm_co0, + &bcm_co3, +}; + +static struct qcom_icc_node *nsp_noc_nodes[] = { + [MASTER_CDSP_NOC_CFG] = &qhm_nsp_noc_config, + [MASTER_CDSP_PROC] = &qxm_nsp, + [SLAVE_CDSP_MEM_NOC] = &qns_nsp_gemnoc, + [SLAVE_SERVICE_NSP_NOC] = &service_nsp_noc, +}; + +static struct qcom_icc_desc sc7280_nsp_noc = { + .nodes = nsp_noc_nodes, + .num_nodes = ARRAY_SIZE(nsp_noc_nodes), + .bcms = nsp_noc_bcms, + .num_bcms = ARRAY_SIZE(nsp_noc_bcms), +}; + +static struct qcom_icc_bcm *system_noc_bcms[] = { + &bcm_sn0, + &bcm_sn2, + &bcm_sn7, + &bcm_sn8, +}; + +static struct qcom_icc_node *system_noc_nodes[] = { + [MASTER_A1NOC_SNOC] = &qnm_aggre1_noc, + [MASTER_A2NOC_SNOC] = &qnm_aggre2_noc, + [MASTER_SNOC_CFG] = &qnm_snoc_cfg, + [MASTER_PIMEM] = &qxm_pimem, + [MASTER_GIC] = &xm_gic, + [SLAVE_SNOC_GEM_NOC_GC] = &qns_gemnoc_gc, + [SLAVE_SNOC_GEM_NOC_SF] = &qns_gemnoc_sf, + [SLAVE_SERVICE_SNOC] = &srvc_snoc, +}; + +static struct qcom_icc_desc sc7280_system_noc = { + .nodes = system_noc_nodes, + .num_nodes = ARRAY_SIZE(system_noc_nodes), + .bcms = system_noc_bcms, + .num_bcms = ARRAY_SIZE(system_noc_bcms), +}; + +static int qnoc_probe(struct platform_device *pdev) +{ + const struct qcom_icc_desc *desc; + struct icc_onecell_data *data; + struct icc_provider *provider; + struct qcom_icc_node **qnodes; + struct qcom_icc_provider *qp; + struct icc_node *node; + size_t num_nodes, i; + int ret; + + desc = device_get_match_data(&pdev->dev); + if (!desc) + return -EINVAL; + + qnodes = desc->nodes; + num_nodes = desc->num_nodes; + + qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL); + if (!qp) + return -ENOMEM; + + data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL); + if (!data) + return -ENOMEM; + + provider = &qp->provider; + provider->dev = &pdev->dev; + provider->set = qcom_icc_set; + provider->pre_aggregate = qcom_icc_pre_aggregate; + provider->aggregate = qcom_icc_aggregate; + provider->xlate_extended = qcom_icc_xlate_extended; + INIT_LIST_HEAD(&provider->nodes); + provider->data = data; + + qp->dev = &pdev->dev; + qp->bcms = desc->bcms; + qp->num_bcms = desc->num_bcms; + + qp->voter = of_bcm_voter_get(qp->dev, NULL); + if (IS_ERR(qp->voter)) + return PTR_ERR(qp->voter); + + ret = icc_provider_add(provider); + if (ret) { + dev_err(&pdev->dev, "error adding interconnect provider\n"); + return ret; + } + + for (i = 0; i < qp->num_bcms; i++) + qcom_icc_bcm_init(qp->bcms[i], &pdev->dev); + + for (i = 0; i < num_nodes; i++) { + size_t j; + + if (!qnodes[i]) + continue; + + node = icc_node_create(qnodes[i]->id); + if (IS_ERR(node)) { + ret = PTR_ERR(node); + goto err; + } + + node->name = qnodes[i]->name; + node->data = qnodes[i]; + icc_node_add(node, provider); + + for (j = 0; j < qnodes[i]->num_links; j++) + icc_link_create(node, qnodes[i]->links[j]); + + data->nodes[i] = node; + } + data->num_nodes = num_nodes; + + platform_set_drvdata(pdev, qp); + + return 0; +err: + icc_nodes_remove(provider); + icc_provider_del(provider); + return ret; +} + +static int qnoc_remove(struct platform_device *pdev) +{ + struct qcom_icc_provider *qp = platform_get_drvdata(pdev); + + icc_nodes_remove(&qp->provider); + return icc_provider_del(&qp->provider); +} + +static const struct of_device_id qnoc_of_match[] = { + { .compatible = "qcom,sc7280-aggre1-noc", + .data = &sc7280_aggre1_noc}, + { .compatible = "qcom,sc7280-aggre2-noc", + .data = &sc7280_aggre2_noc}, + { .compatible = "qcom,sc7280-clk-virt", + .data = &sc7280_clk_virt}, + { .compatible = "qcom,sc7280-cnoc2", + .data = &sc7280_cnoc2}, + { .compatible = "qcom,sc7280-cnoc3", + .data = &sc7280_cnoc3}, + { .compatible = "qcom,sc7280-dc-noc", + .data = &sc7280_dc_noc}, + { .compatible = "qcom,sc7280-gem-noc", + .data = &sc7280_gem_noc}, + { .compatible = "qcom,sc7280-lpass-ag-noc", + .data = &sc7280_lpass_ag_noc}, + { .compatible = "qcom,sc7280-mc-virt", + .data = &sc7280_mc_virt}, + { .compatible = "qcom,sc7280-mmss-noc", + .data = &sc7280_mmss_noc}, + { .compatible = "qcom,sc7280-nsp-noc", + .data = &sc7280_nsp_noc}, + { .compatible = "qcom,sc7280-system-noc", + .data = &sc7280_system_noc}, + { } +}; +MODULE_DEVICE_TABLE(of, qnoc_of_match); + +static struct platform_driver qnoc_driver = { + .probe = qnoc_probe, + .remove = qnoc_remove, + .driver = { + .name = "qnoc-sc7280", + .of_match_table = qnoc_of_match, + .sync_state = icc_sync_state, + }, +}; +module_platform_driver(qnoc_driver); + +MODULE_DESCRIPTION("SC7280 NoC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/interconnect/qcom/sc7280.h b/drivers/interconnect/qcom/sc7280.h new file mode 100644 index 000000000000..175e400305c5 --- /dev/null +++ b/drivers/interconnect/qcom/sc7280.h @@ -0,0 +1,154 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Qualcomm #define SC7280 interconnect IDs + * + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#ifndef __DRIVERS_INTERCONNECT_QCOM_SC7280_H +#define __DRIVERS_INTERCONNECT_QCOM_SC7280_H + +#define SC7280_MASTER_GPU_TCU 0 +#define SC7280_MASTER_SYS_TCU 1 +#define SC7280_MASTER_APPSS_PROC 2 +#define SC7280_MASTER_LLCC 3 +#define SC7280_MASTER_CNOC_LPASS_AG_NOC 4 +#define SC7280_MASTER_CDSP_NOC_CFG 5 +#define SC7280_MASTER_QDSS_BAM 6 +#define SC7280_MASTER_QSPI_0 7 +#define SC7280_MASTER_QUP_0 8 +#define SC7280_MASTER_QUP_1 9 +#define SC7280_MASTER_A1NOC_CFG 10 +#define SC7280_MASTER_A2NOC_CFG 11 +#define SC7280_MASTER_A1NOC_SNOC 12 +#define SC7280_MASTER_A2NOC_SNOC 13 +#define SC7280_MASTER_COMPUTE_NOC 14 +#define SC7280_MASTER_CNOC2_CNOC3 15 +#define SC7280_MASTER_CNOC3_CNOC2 16 +#define SC7280_MASTER_CNOC_A2NOC 17 +#define SC7280_MASTER_CNOC_DC_NOC 18 +#define SC7280_MASTER_GEM_NOC_CFG 19 +#define SC7280_MASTER_GEM_NOC_CNOC 20 +#define SC7280_MASTER_GEM_NOC_PCIE_SNOC 21 +#define SC7280_MASTER_GFX3D 22 +#define SC7280_MASTER_CNOC_MNOC_CFG 23 +#define SC7280_MASTER_MNOC_HF_MEM_NOC 24 +#define SC7280_MASTER_MNOC_SF_MEM_NOC 25 +#define SC7280_MASTER_ANOC_PCIE_GEM_NOC 26 +#define SC7280_MASTER_SNOC_CFG 27 +#define SC7280_MASTER_SNOC_GC_MEM_NOC 28 +#define SC7280_MASTER_SNOC_SF_MEM_NOC 29 +#define SC7280_MASTER_VIDEO_P0 30 +#define SC7280_MASTER_VIDEO_PROC 31 +#define SC7280_MASTER_QUP_CORE_0 32 +#define SC7280_MASTER_QUP_CORE_1 33 +#define SC7280_MASTER_CAMNOC_HF 34 +#define SC7280_MASTER_CAMNOC_ICP 35 +#define SC7280_MASTER_CAMNOC_SF 36 +#define SC7280_MASTER_CRYPTO 37 +#define SC7280_MASTER_IPA 38 +#define SC7280_MASTER_MDP0 39 +#define SC7280_MASTER_CDSP_PROC 40 +#define SC7280_MASTER_PIMEM 41 +#define SC7280_MASTER_GIC 42 +#define SC7280_MASTER_PCIE_0 43 +#define SC7280_MASTER_PCIE_1 44 +#define SC7280_MASTER_QDSS_DAP 45 +#define SC7280_MASTER_QDSS_ETR 46 +#define SC7280_MASTER_SDCC_1 47 +#define SC7280_MASTER_SDCC_2 48 +#define SC7280_MASTER_SDCC_4 49 +#define SC7280_MASTER_UFS_MEM 50 +#define SC7280_MASTER_USB2 51 +#define SC7280_MASTER_USB3_0 52 +#define SC7280_SLAVE_EBI1 53 +#define SC7280_SLAVE_AHB2PHY_SOUTH 54 +#define SC7280_SLAVE_AHB2PHY_NORTH 55 +#define SC7280_SLAVE_AOSS 56 +#define SC7280_SLAVE_APPSS 57 +#define SC7280_SLAVE_CAMERA_CFG 58 +#define SC7280_SLAVE_CLK_CTL 59 +#define SC7280_SLAVE_CDSP_CFG 60 +#define SC7280_SLAVE_RBCPR_CX_CFG 61 +#define SC7280_SLAVE_RBCPR_MX_CFG 62 +#define SC7280_SLAVE_CRYPTO_0_CFG 63 +#define SC7280_SLAVE_CX_RDPM 64 +#define SC7280_SLAVE_DCC_CFG 65 +#define SC7280_SLAVE_DISPLAY_CFG 66 +#define SC7280_SLAVE_GFX3D_CFG 67 +#define SC7280_SLAVE_HWKM 68 +#define SC7280_SLAVE_IMEM_CFG 69 +#define SC7280_SLAVE_IPA_CFG 70 +#define SC7280_SLAVE_IPC_ROUTER_CFG 71 +#define SC7280_SLAVE_LLCC_CFG 72 +#define SC7280_SLAVE_LPASS 73 +#define SC7280_SLAVE_LPASS_CORE_CFG 74 +#define SC7280_SLAVE_LPASS_LPI_CFG 75 +#define SC7280_SLAVE_LPASS_MPU_CFG 76 +#define SC7280_SLAVE_LPASS_TOP_CFG 77 +#define SC7280_SLAVE_MSS_PROC_MS_MPU_CFG 78 +#define SC7280_SLAVE_MCDMA_MS_MPU_CFG 79 +#define SC7280_SLAVE_CNOC_MSS 80 +#define SC7280_SLAVE_MX_RDPM 81 +#define SC7280_SLAVE_PCIE_0_CFG 82 +#define SC7280_SLAVE_PCIE_1_CFG 83 +#define SC7280_SLAVE_PDM 84 +#define SC7280_SLAVE_PIMEM_CFG 85 +#define SC7280_SLAVE_PKA_WRAPPER_CFG 86 +#define SC7280_SLAVE_PMU_WRAPPER_CFG 87 +#define SC7280_SLAVE_QDSS_CFG 88 +#define SC7280_SLAVE_QSPI_0 89 +#define SC7280_SLAVE_QUP_0 90 +#define SC7280_SLAVE_QUP_1 91 +#define SC7280_SLAVE_SDCC_1 92 +#define SC7280_SLAVE_SDCC_2 93 +#define SC7280_SLAVE_SDCC_4 94 +#define SC7280_SLAVE_SECURITY 95 +#define SC7280_SLAVE_TCSR 96 +#define SC7280_SLAVE_TLMM 97 +#define SC7280_SLAVE_UFS_MEM_CFG 98 +#define SC7280_SLAVE_USB2 99 +#define SC7280_SLAVE_USB3_0 100 +#define SC7280_SLAVE_VENUS_CFG 101 +#define SC7280_SLAVE_VSENSE_CTRL_CFG 102 +#define SC7280_SLAVE_A1NOC_CFG 103 +#define SC7280_SLAVE_A1NOC_SNOC 104 +#define SC7280_SLAVE_A2NOC_CFG 105 +#define SC7280_SLAVE_A2NOC_SNOC 106 +#define SC7280_SLAVE_CNOC2_CNOC3 107 +#define SC7280_SLAVE_CNOC3_CNOC2 108 +#define SC7280_SLAVE_CNOC_A2NOC 109 +#define SC7280_SLAVE_DDRSS_CFG 110 +#define SC7280_SLAVE_GEM_NOC_CNOC 111 +#define SC7280_SLAVE_GEM_NOC_CFG 112 +#define SC7280_SLAVE_SNOC_GEM_NOC_GC 113 +#define SC7280_SLAVE_SNOC_GEM_NOC_SF 114 +#define SC7280_SLAVE_LLCC 115 +#define SC7280_SLAVE_MNOC_HF_MEM_NOC 116 +#define SC7280_SLAVE_MNOC_SF_MEM_NOC 117 +#define SC7280_SLAVE_CNOC_MNOC_CFG 118 +#define SC7280_SLAVE_CDSP_MEM_NOC 119 +#define SC7280_SLAVE_MEM_NOC_PCIE_SNOC 120 +#define SC7280_SLAVE_ANOC_PCIE_GEM_NOC 121 +#define SC7280_SLAVE_SNOC_CFG 122 +#define SC7280_SLAVE_QUP_CORE_0 123 +#define SC7280_SLAVE_QUP_CORE_1 124 +#define SC7280_SLAVE_BOOT_IMEM 125 +#define SC7280_SLAVE_IMEM 126 +#define SC7280_SLAVE_PIMEM 127 +#define SC7280_SLAVE_SERVICE_NSP_NOC 128 +#define SC7280_SLAVE_SERVICE_A1NOC 129 +#define SC7280_SLAVE_SERVICE_A2NOC 130 +#define SC7280_SLAVE_SERVICE_GEM_NOC_1 131 +#define SC7280_SLAVE_SERVICE_MNOC 132 +#define SC7280_SLAVE_SERVICES_LPASS_AML_NOC 133 +#define SC7280_SLAVE_SERVICE_LPASS_AG_NOC 134 +#define SC7280_SLAVE_SERVICE_GEM_NOC_2 135 +#define SC7280_SLAVE_SERVICE_SNOC 136 +#define SC7280_SLAVE_SERVICE_GEM_NOC 137 +#define SC7280_SLAVE_PCIE_0 138 +#define SC7280_SLAVE_PCIE_1 139 +#define SC7280_SLAVE_QDSS_STM 140 +#define SC7280_SLAVE_TCU 141 + +#endif diff --git a/drivers/ipack/carriers/tpci200.c b/drivers/ipack/carriers/tpci200.c index ec71063fff76..3461b0a7dc62 100644 --- a/drivers/ipack/carriers/tpci200.c +++ b/drivers/ipack/carriers/tpci200.c @@ -1,7 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/** - * tpci200.c - * +/* * driver for the TEWS TPCI-200 device * * Copyright (C) 2009-2012 CERN (www.cern.ch) @@ -596,8 +594,11 @@ static int tpci200_pci_probe(struct pci_dev *pdev, out_err_bus_register: tpci200_uninstall(tpci200); + /* tpci200->info->cfg_regs is unmapped in tpci200_uninstall */ + tpci200->info->cfg_regs = NULL; out_err_install: - iounmap(tpci200->info->cfg_regs); + if (tpci200->info->cfg_regs) + iounmap(tpci200->info->cfg_regs); out_err_ioremap: pci_release_region(pdev, TPCI200_CFG_MEM_BAR); out_err_pci_request: diff --git a/drivers/ipack/carriers/tpci200.h b/drivers/ipack/carriers/tpci200.h index 2619f827e33f..e79ac64abcff 100644 --- a/drivers/ipack/carriers/tpci200.h +++ b/drivers/ipack/carriers/tpci200.h @@ -1,7 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/** - * tpci200.h - * +/* * driver for the carrier TEWS TPCI-200 * * Copyright (C) 2009-2012 CERN (www.cern.ch) diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index 3940714e4397..20fa02c81070 100644 --- a/drivers/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c @@ -1,7 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/** - * ipoctal.c - * +/* * driver for the GE IP-OCTAL boards * * Copyright (C) 2009-2012 CERN (www.cern.ch) @@ -460,14 +458,14 @@ static int ipoctal_write_tty(struct tty_struct *tty, return char_copied; } -static int ipoctal_write_room(struct tty_struct *tty) +static unsigned int ipoctal_write_room(struct tty_struct *tty) { struct ipoctal_channel *channel = tty->driver_data; return PAGE_SIZE - channel->nb_bytes; } -static int ipoctal_chars_in_buffer(struct tty_struct *tty) +static unsigned int ipoctal_chars_in_buffer(struct tty_struct *tty) { struct ipoctal_channel *channel = tty->driver_data; diff --git a/drivers/ipack/devices/ipoctal.h b/drivers/ipack/devices/ipoctal.h index 75f83ba774a4..773dc41bd667 100644 --- a/drivers/ipack/devices/ipoctal.h +++ b/drivers/ipack/devices/ipoctal.h @@ -1,9 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/** - * ipoctal.h - * +/* * driver for the IPOCTAL boards - + * * Copyright (C) 2009-2012 CERN (www.cern.ch) * Author: Nicolas Serafini, EIC2 SA * Author: Samuel Iglesias Gonsalvez <siglesias@igalia.com> diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index fdf87acccd06..d5f9261fa879 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -1158,8 +1158,6 @@ static void capinc_tty_flush_chars(struct tty_struct *tty) struct capiminor *mp = tty->driver_data; struct sk_buff *skb; - pr_debug("capinc_tty_flush_chars\n"); - spin_lock_bh(&mp->outlock); skb = mp->outskb; if (skb) { @@ -1175,18 +1173,18 @@ static void capinc_tty_flush_chars(struct tty_struct *tty) handle_minor_recv(mp); } -static int capinc_tty_write_room(struct tty_struct *tty) +static unsigned int capinc_tty_write_room(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; - int room; + unsigned int room; room = CAPINC_MAX_SENDQUEUE-skb_queue_len(&mp->outqueue); room *= CAPI_MAX_BLKSIZE; - pr_debug("capinc_tty_write_room = %d\n", room); + pr_debug("capinc_tty_write_room = %u\n", room); return room; } -static int capinc_tty_chars_in_buffer(struct tty_struct *tty) +static unsigned int capinc_tty_chars_in_buffer(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; @@ -1197,15 +1195,9 @@ static int capinc_tty_chars_in_buffer(struct tty_struct *tty) return mp->outbytes; } -static void capinc_tty_set_termios(struct tty_struct *tty, struct ktermios *old) -{ - pr_debug("capinc_tty_set_termios\n"); -} - static void capinc_tty_throttle(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; - pr_debug("capinc_tty_throttle\n"); mp->ttyinstop = 1; } @@ -1213,7 +1205,6 @@ static void capinc_tty_unthrottle(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; - pr_debug("capinc_tty_unthrottle\n"); mp->ttyinstop = 0; handle_minor_recv(mp); } @@ -1222,7 +1213,6 @@ static void capinc_tty_stop(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; - pr_debug("capinc_tty_stop\n"); mp->ttyoutstop = 1; } @@ -1230,7 +1220,6 @@ static void capinc_tty_start(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; - pr_debug("capinc_tty_start\n"); mp->ttyoutstop = 0; handle_minor_send(mp); } @@ -1239,26 +1228,9 @@ static void capinc_tty_hangup(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; - pr_debug("capinc_tty_hangup\n"); tty_port_hangup(&mp->port); } -static int capinc_tty_break_ctl(struct tty_struct *tty, int state) -{ - pr_debug("capinc_tty_break_ctl(%d)\n", state); - return 0; -} - -static void capinc_tty_flush_buffer(struct tty_struct *tty) -{ - pr_debug("capinc_tty_flush_buffer\n"); -} - -static void capinc_tty_set_ldisc(struct tty_struct *tty) -{ - pr_debug("capinc_tty_set_ldisc\n"); -} - static void capinc_tty_send_xchar(struct tty_struct *tty, char ch) { pr_debug("capinc_tty_send_xchar(%d)\n", ch); @@ -1272,15 +1244,11 @@ static const struct tty_operations capinc_ops = { .flush_chars = capinc_tty_flush_chars, .write_room = capinc_tty_write_room, .chars_in_buffer = capinc_tty_chars_in_buffer, - .set_termios = capinc_tty_set_termios, .throttle = capinc_tty_throttle, .unthrottle = capinc_tty_unthrottle, .stop = capinc_tty_stop, .start = capinc_tty_start, .hangup = capinc_tty_hangup, - .break_ctl = capinc_tty_break_ctl, - .flush_buffer = capinc_tty_flush_buffer, - .set_ldisc = capinc_tty_set_ldisc, .send_xchar = capinc_tty_send_xchar, .install = capinc_tty_install, .cleanup = capinc_tty_cleanup, diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 49d99cb084db..bdf16180f5ff 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -199,6 +199,7 @@ config LEDS_LM3530 config LEDS_LM3532 tristate "LCD Backlight driver for LM3532" + select REGMAP_I2C depends on LEDS_CLASS depends on I2C help @@ -616,7 +617,6 @@ config LEDS_LT3593 tristate "LED driver for LT3593 controllers" depends on LEDS_CLASS depends on GPIOLIB || COMPILE_TEST - depends on OF help This option enables support for LEDs driven by a Linear Technology LT3593 controller. This controller uses a special one-wire pulse diff --git a/drivers/leds/blink/leds-lgm-sso.c b/drivers/leds/blink/leds-lgm-sso.c index 6a63846d10b5..7eb2f44f16be 100644 --- a/drivers/leds/blink/leds-lgm-sso.c +++ b/drivers/leds/blink/leds-lgm-sso.c @@ -7,7 +7,8 @@ #include <linux/bitfield.h> #include <linux/clk.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> +#include <linux/gpio/driver.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/leds.h> @@ -132,8 +133,7 @@ struct sso_led_priv { struct regmap *mmap; struct device *dev; struct platform_device *pdev; - struct clk *gclk; - struct clk *fpid_clk; + struct clk_bulk_data clocks[2]; u32 fpid_clkrate; u32 gptc_clkrate; u32 freq[MAX_FREQ_RANK]; @@ -259,7 +259,7 @@ static void sso_led_brightness_set(struct led_classdev *led_cdev, 1 << desc->pin); } - if (!desc->hw_trig && led->gpiod) + if (!desc->hw_trig) gpiod_set_value(led->gpiod, val); } @@ -423,7 +423,7 @@ static void sso_gpio_free(struct gpio_chip *chip, unsigned int offset) static int sso_gpio_get_dir(struct gpio_chip *chip, unsigned int offset) { - return GPIOF_DIR_OUT; + return GPIO_LINE_DIRECTION_OUT; } static int @@ -763,12 +763,11 @@ static int sso_probe_gpios(struct sso_led_priv *priv) return sso_gpio_gc_init(dev, priv); } -static void sso_clk_disable(void *data) +static void sso_clock_disable_unprepare(void *data) { struct sso_led_priv *priv = data; - clk_disable_unprepare(priv->fpid_clk); - clk_disable_unprepare(priv->gclk); + clk_bulk_disable_unprepare(ARRAY_SIZE(priv->clocks), priv->clocks); } static int intel_sso_led_probe(struct platform_device *pdev) @@ -785,36 +784,30 @@ static int intel_sso_led_probe(struct platform_device *pdev) priv->dev = dev; /* gate clock */ - priv->gclk = devm_clk_get(dev, "sso"); - if (IS_ERR(priv->gclk)) { - dev_err(dev, "get sso gate clock failed!\n"); - return PTR_ERR(priv->gclk); - } + priv->clocks[0].id = "sso"; + + /* fpid clock */ + priv->clocks[1].id = "fpid"; - ret = clk_prepare_enable(priv->gclk); + ret = devm_clk_bulk_get(dev, ARRAY_SIZE(priv->clocks), priv->clocks); if (ret) { - dev_err(dev, "Failed to prepare/enable sso gate clock!\n"); + dev_err(dev, "Getting clocks failed!\n"); return ret; } - priv->fpid_clk = devm_clk_get(dev, "fpid"); - if (IS_ERR(priv->fpid_clk)) { - dev_err(dev, "Failed to get fpid clock!\n"); - return PTR_ERR(priv->fpid_clk); - } - - ret = clk_prepare_enable(priv->fpid_clk); + ret = clk_bulk_prepare_enable(ARRAY_SIZE(priv->clocks), priv->clocks); if (ret) { - dev_err(dev, "Failed to prepare/enable fpid clock!\n"); + dev_err(dev, "Failed to prepare and enable clocks!\n"); return ret; } - priv->fpid_clkrate = clk_get_rate(priv->fpid_clk); - ret = devm_add_action_or_reset(dev, sso_clk_disable, priv); - if (ret) { - dev_err(dev, "Failed to devm_add_action_or_reset, %d\n", ret); + ret = devm_add_action_or_reset(dev, sso_clock_disable_unprepare, priv); + if (ret) return ret; - } + + priv->fpid_clkrate = clk_get_rate(priv->clocks[1].clk); + + priv->mmap = syscon_node_to_regmap(dev->of_node); priv->mmap = syscon_node_to_regmap(dev->of_node); if (IS_ERR(priv->mmap)) { @@ -859,8 +852,6 @@ static int intel_sso_led_remove(struct platform_device *pdev) sso_led_shutdown(led); } - clk_disable_unprepare(priv->fpid_clk); - clk_disable_unprepare(priv->gclk); regmap_exit(priv->mmap); return 0; @@ -878,7 +869,7 @@ static struct platform_driver intel_sso_led_driver = { .remove = intel_sso_led_remove, .driver = { .name = "lgm-ssoled", - .of_match_table = of_match_ptr(of_sso_led_match), + .of_match_table = of_sso_led_match, }, }; diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 2e495ff67856..f704391d57a8 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -285,10 +285,6 @@ struct led_classdev *__must_check devm_of_led_get(struct device *dev, if (!dev) return ERR_PTR(-EINVAL); - /* Not using device tree? */ - if (!IS_ENABLED(CONFIG_OF) || !dev->of_node) - return ERR_PTR(-ENOTSUPP); - led = of_led_get(dev->of_node, index); if (IS_ERR(led)) return led; @@ -513,7 +509,7 @@ static int devm_led_classdev_match(struct device *dev, void *res, void *data) /** * devm_led_classdev_unregister() - resource managed led_classdev_unregister() - * @parent: The device to unregister. + * @dev: The device to unregister. * @led_cdev: the led_classdev structure for this device. */ void devm_led_classdev_unregister(struct device *dev, diff --git a/drivers/leds/leds-as3645a.c b/drivers/leds/leds-as3645a.c index e8922fa03379..aa3f82be0a9c 100644 --- a/drivers/leds/leds-as3645a.c +++ b/drivers/leds/leds-as3645a.c @@ -185,7 +185,7 @@ static int as3645a_read(struct as3645a *flash, u8 addr) */ /** - * as3645a_set_config - Set flash configuration registers + * as3645a_set_current - Set flash configuration registers * @flash: The flash * * Configure the hardware with flash, assist and indicator currents, as well as @@ -545,6 +545,7 @@ static int as3645a_parse_node(struct as3645a *flash, if (!flash->indicator_node) { dev_warn(&flash->client->dev, "can't find indicator node\n"); + rval = -ENODEV; goto out_err; } diff --git a/drivers/leds/leds-bcm6328.c b/drivers/leds/leds-bcm6328.c index 226d17d253ed..2d4d87957a30 100644 --- a/drivers/leds/leds-bcm6328.c +++ b/drivers/leds/leds-bcm6328.c @@ -93,7 +93,7 @@ static unsigned long bcm6328_led_read(void __iomem *reg) #endif } -/** +/* * LEDMode 64 bits / 24 LEDs * bits [31:0] -> LEDs 8-23 * bits [47:32] -> LEDs 0-7 diff --git a/drivers/leds/leds-blinkm.c b/drivers/leds/leds-blinkm.c index b4e1fdff4186..bd7d0d5cf3b6 100644 --- a/drivers/leds/leds-blinkm.c +++ b/drivers/leds/leds-blinkm.c @@ -480,9 +480,8 @@ static int blinkm_led_blue_set(struct led_classdev *led_cdev, static void blinkm_init_hw(struct i2c_client *client) { - int ret; - ret = blinkm_transfer_hw(client, BLM_STOP_SCRIPT); - ret = blinkm_transfer_hw(client, BLM_GO_RGB); + blinkm_transfer_hw(client, BLM_STOP_SCRIPT); + blinkm_transfer_hw(client, BLM_GO_RGB); } static int blinkm_test_run(struct i2c_client *client) diff --git a/drivers/leds/leds-el15203000.c b/drivers/leds/leds-el15203000.c index 6ca47f2a2004..76b455e87574 100644 --- a/drivers/leds/leds-el15203000.c +++ b/drivers/leds/leds-el15203000.c @@ -68,8 +68,8 @@ enum el15203000_command { }; struct el15203000_led { - struct el15203000 *priv; struct led_classdev ldev; + struct el15203000 *priv; u32 reg; }; @@ -82,6 +82,8 @@ struct el15203000 { struct el15203000_led leds[]; }; +#define to_el15203000_led(d) container_of(d, struct el15203000_led, ldev) + static int el15203000_cmd(struct el15203000_led *led, u8 brightness) { int ret; @@ -128,9 +130,7 @@ static int el15203000_cmd(struct el15203000_led *led, u8 brightness) static int el15203000_set_blocking(struct led_classdev *ldev, enum led_brightness brightness) { - struct el15203000_led *led = container_of(ldev, - struct el15203000_led, - ldev); + struct el15203000_led *led = to_el15203000_led(ldev); return el15203000_cmd(led, brightness == LED_OFF ? EL_OFF : EL_ON); } @@ -139,9 +139,7 @@ static int el15203000_pattern_set_S(struct led_classdev *ldev, struct led_pattern *pattern, u32 len, int repeat) { - struct el15203000_led *led = container_of(ldev, - struct el15203000_led, - ldev); + struct el15203000_led *led = to_el15203000_led(ldev); if (repeat > 0 || len != 2 || pattern[0].delta_t != 4000 || pattern[0].brightness != 0 || @@ -192,10 +190,8 @@ static int el15203000_pattern_set_P(struct led_classdev *ldev, struct led_pattern *pattern, u32 len, int repeat) { + struct el15203000_led *led = to_el15203000_led(ldev); u8 cmd; - struct el15203000_led *led = container_of(ldev, - struct el15203000_led, - ldev); if (repeat > 0) return -EINVAL; @@ -232,9 +228,7 @@ static int el15203000_pattern_set_P(struct led_classdev *ldev, static int el15203000_pattern_clear(struct led_classdev *ldev) { - struct el15203000_led *led = container_of(ldev, - struct el15203000_led, - ldev); + struct el15203000_led *led = to_el15203000_led(ldev); return el15203000_cmd(led, EL_OFF); } @@ -251,16 +245,13 @@ static int el15203000_probe_dt(struct el15203000 *priv) ret = fwnode_property_read_u32(child, "reg", &led->reg); if (ret) { dev_err(priv->dev, "LED without ID number"); - fwnode_handle_put(child); - - break; + goto err_child_out; } if (led->reg > U8_MAX) { dev_err(priv->dev, "LED value %d is invalid", led->reg); - fwnode_handle_put(child); - - return -EINVAL; + ret = -EINVAL; + goto err_child_out; } led->priv = priv; @@ -282,14 +273,16 @@ static int el15203000_probe_dt(struct el15203000 *priv) dev_err(priv->dev, "failed to register LED device %s, err %d", led->ldev.name, ret); - fwnode_handle_put(child); - - break; + goto err_child_out; } led++; } + return 0; + +err_child_out: + fwnode_handle_put(child); return ret; } diff --git a/drivers/leds/leds-gpio-register.c b/drivers/leds/leds-gpio-register.c index b9187e71e0cf..de3f12c2b80d 100644 --- a/drivers/leds/leds-gpio-register.c +++ b/drivers/leds/leds-gpio-register.c @@ -11,6 +11,7 @@ /** * gpio_led_register_device - register a gpio-led device * @pdata: the platform data used for the new device + * @id: platform ID * * Makes a copy of pdata and pdata->leds and registers a new leds-gpio device * with the result. This allows to have pdata and pdata-leds in .init.rodata diff --git a/drivers/leds/leds-is31fl32xx.c b/drivers/leds/leds-is31fl32xx.c index 2180255ad339..3b55af9a8c58 100644 --- a/drivers/leds/leds-is31fl32xx.c +++ b/drivers/leds/leds-is31fl32xx.c @@ -58,7 +58,8 @@ struct is31fl32xx_priv { * @pwm_registers_reversed: : true if PWM registers count down instead of up * @led_control_register_base : address of first LED control register (optional) * @enable_bits_per_led_control_register: number of LEDs enable bits in each - * @reset_func: : pointer to reset function + * @reset_func : pointer to reset function + * @sw_shutdown_func : pointer to software shutdown function * * For all optional register addresses, the sentinel value %IS31FL32XX_REG_NONE * indicates that this chip has no such register. diff --git a/drivers/leds/leds-ktd2692.c b/drivers/leds/leds-ktd2692.c index 632f10db4b3f..f341da1503a4 100644 --- a/drivers/leds/leds-ktd2692.c +++ b/drivers/leds/leds-ktd2692.c @@ -256,6 +256,17 @@ static void ktd2692_setup(struct ktd2692_context *led) | KTD2692_REG_FLASH_CURRENT_BASE); } +static void regulator_disable_action(void *_data) +{ + struct device *dev = _data; + struct ktd2692_context *led = dev_get_drvdata(dev); + int ret; + + ret = regulator_disable(led->regulator); + if (ret) + dev_err(dev, "Failed to disable supply: %d\n", ret); +} + static int ktd2692_parse_dt(struct ktd2692_context *led, struct device *dev, struct ktd2692_led_config_data *cfg) { @@ -286,8 +297,14 @@ static int ktd2692_parse_dt(struct ktd2692_context *led, struct device *dev, if (led->regulator) { ret = regulator_enable(led->regulator); - if (ret) + if (ret) { dev_err(dev, "Failed to enable supply: %d\n", ret); + } else { + ret = devm_add_action_or_reset(dev, + regulator_disable_action, dev); + if (ret) + return ret; + } } child_node = of_get_next_available_child(np, NULL); @@ -377,17 +394,9 @@ static int ktd2692_probe(struct platform_device *pdev) static int ktd2692_remove(struct platform_device *pdev) { struct ktd2692_context *led = platform_get_drvdata(pdev); - int ret; led_classdev_flash_unregister(&led->fled_cdev); - if (led->regulator) { - ret = regulator_disable(led->regulator); - if (ret) - dev_err(&pdev->dev, - "Failed to disable supply: %d\n", ret); - } - mutex_destroy(&led->lock); return 0; diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c index 2db455efd4b1..e72393534b72 100644 --- a/drivers/leds/leds-lm3530.c +++ b/drivers/leds/leds-lm3530.c @@ -99,7 +99,7 @@ static struct lm3530_mode_map mode_map[] = { * @pdata: LM3530 platform data * @mode: mode of operation - manual, ALS, PWM * @regulator: regulator - * @brighness: previous brightness value + * @brightness: previous brightness value * @enable: regulator is enabled */ struct lm3530_data { diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c index 0bf25bdde02f..beb53040e09e 100644 --- a/drivers/leds/leds-lm3532.c +++ b/drivers/leds/leds-lm3532.c @@ -586,7 +586,6 @@ static int lm3532_parse_node(struct lm3532_data *priv) ret = fwnode_property_read_u32(child, "reg", &control_bank); if (ret) { dev_err(&priv->client->dev, "reg property missing\n"); - fwnode_handle_put(child); goto child_out; } @@ -601,7 +600,6 @@ static int lm3532_parse_node(struct lm3532_data *priv) &led->mode); if (ret) { dev_err(&priv->client->dev, "ti,led-mode property missing\n"); - fwnode_handle_put(child); goto child_out; } @@ -636,7 +634,6 @@ static int lm3532_parse_node(struct lm3532_data *priv) led->num_leds); if (ret) { dev_err(&priv->client->dev, "led-sources property missing\n"); - fwnode_handle_put(child); goto child_out; } @@ -647,7 +644,6 @@ static int lm3532_parse_node(struct lm3532_data *priv) if (ret) { dev_err(&priv->client->dev, "led register err: %d\n", ret); - fwnode_handle_put(child); goto child_out; } @@ -655,14 +651,15 @@ static int lm3532_parse_node(struct lm3532_data *priv) if (ret) { dev_err(&priv->client->dev, "register init err: %d\n", ret); - fwnode_handle_put(child); goto child_out; } i++; } + return 0; child_out: + fwnode_handle_put(child); return ret; } diff --git a/drivers/leds/leds-lm36274.c b/drivers/leds/leds-lm36274.c index aadb03468a40..e009b6d17915 100644 --- a/drivers/leds/leds-lm36274.c +++ b/drivers/leds/leds-lm36274.c @@ -7,9 +7,10 @@ #include <linux/err.h> #include <linux/leds.h> #include <linux/leds-ti-lmu-common.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/platform_device.h> +#include <linux/property.h> #include <linux/mfd/ti-lmu.h> #include <linux/mfd/ti-lmu-register.h> @@ -127,6 +128,7 @@ static int lm36274_probe(struct platform_device *pdev) ret = lm36274_init(chip); if (ret) { + fwnode_handle_put(init_data.fwnode); dev_err(chip->dev, "Failed to init the device\n"); return ret; } diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c index e945de45388c..a02756d7ed8f 100644 --- a/drivers/leds/leds-lm3692x.c +++ b/drivers/leds/leds-lm3692x.c @@ -96,15 +96,15 @@ #define LM3692X_FAULT_FLAG_OPEN BIT(4) /** - * struct lm3692x_led - - * @lock - Lock for reading/writing the device - * @client - Pointer to the I2C client - * @led_dev - LED class device pointer - * @regmap - Devices register map - * @enable_gpio - VDDIO/EN gpio to enable communication interface - * @regulator - LED supply regulator pointer - * @led_enable - LED sync to be enabled - * @model_id - Current device model ID enumerated + * struct lm3692x_led + * @lock: Lock for reading/writing the device + * @client: Pointer to the I2C client + * @led_dev: LED class device pointer + * @regmap: Devices register map + * @enable_gpio: VDDIO/EN gpio to enable communication interface + * @regulator: LED supply regulator pointer + * @led_enable: LED sync to be enabled + * @model_id: Current device model ID enumerated */ struct lm3692x_led { struct mutex lock; @@ -435,6 +435,7 @@ static int lm3692x_probe_dt(struct lm3692x_led *led) ret = fwnode_property_read_u32(child, "reg", &led->led_enable); if (ret) { + fwnode_handle_put(child); dev_err(&led->client->dev, "reg DT property missing\n"); return ret; } @@ -449,12 +450,11 @@ static int lm3692x_probe_dt(struct lm3692x_led *led) ret = devm_led_classdev_register_ext(&led->client->dev, &led->led_dev, &init_data); - if (ret) { + if (ret) dev_err(&led->client->dev, "led register err: %d\n", ret); - return ret; - } - return 0; + fwnode_handle_put(init_data.fwnode); + return ret; } static int lm3692x_probe(struct i2c_client *client, diff --git a/drivers/leds/leds-lm3697.c b/drivers/leds/leds-lm3697.c index 7d216cdb91a8..970a4f34791b 100644 --- a/drivers/leds/leds-lm3697.c +++ b/drivers/leds/leds-lm3697.c @@ -47,6 +47,8 @@ * @lmu_data: Register and setting values for common code * @control_bank: Control bank the LED is associated to. 0 is control bank A * 1 is control bank B + * @enabled: LED brightness level (or LED_OFF) + * @num_leds: Number of LEDs available */ struct lm3697_led { u32 hvled_strings[LM3697_MAX_LED_STRINGS]; @@ -68,6 +70,8 @@ struct lm3697_led { * @dev: Pointer to the devices device struct * @lock: Lock for reading/writing the device * @leds: Array of LED strings + * @bank_cfg: OUTPUT_CONFIG register values + * @num_banks: Number of control banks */ struct lm3697 { struct gpio_desc *enable_gpio; @@ -203,11 +207,9 @@ static int lm3697_probe_dt(struct lm3697 *priv) priv->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW); - if (IS_ERR(priv->enable_gpio)) { - ret = PTR_ERR(priv->enable_gpio); - dev_err(dev, "Failed to get enable gpio: %d\n", ret); - return ret; - } + if (IS_ERR(priv->enable_gpio)) + return dev_err_probe(dev, PTR_ERR(priv->enable_gpio), + "Failed to get enable GPIO\n"); priv->regulator = devm_regulator_get(dev, "vled"); if (IS_ERR(priv->regulator)) diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c index 838e6f19d37e..437c711b2a27 100644 --- a/drivers/leds/leds-lp3944.c +++ b/drivers/leds/leds-lp3944.c @@ -92,7 +92,7 @@ static int lp3944_reg_write(struct i2c_client *client, u8 reg, u8 value) } /** - * Set the period for DIM status + * lp3944_dim_set_period() - Set the period for DIM status * * @client: the i2c client * @dim: either LP3944_DIM0 or LP3944_DIM1 @@ -123,7 +123,7 @@ static int lp3944_dim_set_period(struct i2c_client *client, u8 dim, u16 period) } /** - * Set the duty cycle for DIM status + * lp3944_dim_set_dutycycle - Set the duty cycle for DIM status * * @client: the i2c client * @dim: either LP3944_DIM0 or LP3944_DIM1 @@ -155,7 +155,7 @@ static int lp3944_dim_set_dutycycle(struct i2c_client *client, u8 dim, } /** - * Set the led status + * lp3944_led_set() - Set the led status * * @led: a lp3944_led_data structure * @status: one of LP3944_LED_STATUS_OFF diff --git a/drivers/leds/leds-lp50xx.c b/drivers/leds/leds-lp50xx.c index 06230614fdc5..401df1e2e05d 100644 --- a/drivers/leds/leds-lp50xx.c +++ b/drivers/leds/leds-lp50xx.c @@ -490,6 +490,7 @@ static int lp50xx_probe_dt(struct lp50xx *priv) ret = fwnode_property_read_u32(led_node, "color", &color_id); if (ret) { + fwnode_handle_put(led_node); dev_err(priv->dev, "Cannot read color\n"); goto child_out; } @@ -512,7 +513,6 @@ static int lp50xx_probe_dt(struct lp50xx *priv) goto child_out; } i++; - fwnode_handle_put(child); } return 0; diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c index 81de1346bf5d..d1657c46ee2f 100644 --- a/drivers/leds/leds-lp55xx-common.c +++ b/drivers/leds/leds-lp55xx-common.c @@ -694,7 +694,7 @@ struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev, of_property_read_u8(np, "clock-mode", &pdata->clock_mode); pdata->enable_gpiod = devm_gpiod_get_optional(dev, "enable", - GPIOD_ASIS); + GPIOD_OUT_LOW); if (IS_ERR(pdata->enable_gpiod)) return ERR_CAST(pdata->enable_gpiod); diff --git a/drivers/leds/leds-lp8860.c b/drivers/leds/leds-lp8860.c index f0533a337bc1..3c693d5e3b44 100644 --- a/drivers/leds/leds-lp8860.c +++ b/drivers/leds/leds-lp8860.c @@ -85,14 +85,14 @@ #define LP8860_NAME "lp8860" /** - * struct lp8860_led - - * @lock - Lock for reading/writing the device - * @client - Pointer to the I2C client - * @led_dev - led class device pointer - * @regmap - Devices register map - * @eeprom_regmap - EEPROM register map - * @enable_gpio - VDDIO/EN gpio to enable communication interface - * @regulator - LED supply regulator pointer + * struct lp8860_led + * @lock: Lock for reading/writing the device + * @client: Pointer to the I2C client + * @led_dev: led class device pointer + * @regmap: Devices register map + * @eeprom_regmap: EEPROM register map + * @enable_gpio: VDDIO/EN gpio to enable communication interface + * @regulator: LED supply regulator pointer */ struct lp8860_led { struct mutex lock; diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c index 68e06434ac08..3bb52d3165d9 100644 --- a/drivers/leds/leds-lt3593.c +++ b/drivers/leds/leds-lt3593.c @@ -7,8 +7,9 @@ #include <linux/delay.h> #include <linux/gpio/consumer.h> #include <linux/slab.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of.h> +#include <linux/property.h> #define LED_LT3593_NAME "lt3593" @@ -68,9 +69,6 @@ static int lt3593_led_probe(struct platform_device *pdev) struct led_init_data init_data = {}; const char *tmp; - if (!dev_of_node(dev)) - return -ENODEV; - led_data = devm_kzalloc(dev, sizeof(*led_data), GFP_KERNEL); if (!led_data) return -ENOMEM; @@ -119,7 +117,7 @@ static struct platform_driver lt3593_led_driver = { .probe = lt3593_led_probe, .driver = { .name = "leds-lt3593", - .of_match_table = of_match_ptr(of_lt3593_leds_match), + .of_match_table = of_lt3593_leds_match, }, }; diff --git a/drivers/leds/leds-mlxcpld.c b/drivers/leds/leds-mlxcpld.c index f4721f8065f0..1355c84a2919 100644 --- a/drivers/leds/leds-mlxcpld.c +++ b/drivers/leds/leds-mlxcpld.c @@ -64,10 +64,10 @@ #define MLXCPLD_LED_BLINK_6HZ 83 /* ~83 msec off/on */ /** - * mlxcpld_param - LED access parameters: - * @offset - offset for LED access in CPLD device - * @mask - mask for LED access in CPLD device - * @base_color - base color code for LED + * struct mlxcpld_param - LED access parameters: + * @offset: offset for LED access in CPLD device + * @mask: mask for LED access in CPLD device + * @base_color: base color code for LED **/ struct mlxcpld_param { u8 offset; @@ -76,9 +76,9 @@ struct mlxcpld_param { }; /** - * mlxcpld_led_priv - LED private data: - * @cled - LED class device instance - * @param - LED CPLD access parameters + * struct mlxcpld_led_priv - LED private data: + * @cled: LED class device instance + * @param: LED CPLD access parameters **/ struct mlxcpld_led_priv { struct led_classdev cdev; @@ -88,12 +88,12 @@ struct mlxcpld_led_priv { #define cdev_to_priv(c) container_of(c, struct mlxcpld_led_priv, cdev) /** - * mlxcpld_led_profile - system LED profile (defined per system class): - * @offset - offset for LED access in CPLD device - * @mask - mask for LED access in CPLD device - * @base_color - base color code - * @brightness - default brightness setting (on/off) - * @name - LED name + * struct mlxcpld_led_profile - system LED profile (defined per system class): + * @offset: offset for LED access in CPLD device + * @mask: mask for LED access in CPLD device + * @base_color: base color code + * @brightness: default brightness setting (on/off) + * @name: LED name **/ struct mlxcpld_led_profile { u8 offset; @@ -104,12 +104,12 @@ struct mlxcpld_led_profile { }; /** - * mlxcpld_led_pdata - system LED private data - * @pdev - platform device pointer - * @pled - LED class device instance - * @profile - system configuration profile - * @num_led_instances - number of LED instances - * @lock - device access lock + * struct mlxcpld_led_pdata - system LED private data + * @pdev: platform device pointer + * @pled: LED class device instance + * @profile: system configuration profile + * @num_led_instances: number of LED instances + * @lock: device access lock **/ struct mlxcpld_led_pdata { struct platform_device *pdev; diff --git a/drivers/leds/leds-mlxreg.c b/drivers/leds/leds-mlxreg.c index 82aea1cd0c12..b7855c93bd72 100644 --- a/drivers/leds/leds-mlxreg.c +++ b/drivers/leds/leds-mlxreg.c @@ -28,10 +28,11 @@ * struct mlxreg_led_data - led control data: * * @data: led configuration data; - * @led_classdev: led class data; + * @led_cdev: led class data; * @base_color: base led color (other colors have constant offset from base); * @led_data: led data; * @data_parent: pointer to private device control data of parent; + * @led_cdev_name: class device name */ struct mlxreg_led_data { struct mlxreg_core_data *data; diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index f53f9309ca6c..d71e9fa5c8de 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -101,7 +101,7 @@ static int led_pwm_create_fwnode(struct device *dev, struct led_pwm_priv *priv) { struct fwnode_handle *fwnode; struct led_pwm led; - int ret = 0; + int ret; memset(&led, 0, sizeof(led)); @@ -111,8 +111,8 @@ static int led_pwm_create_fwnode(struct device *dev, struct led_pwm_priv *priv) led.name = to_of_node(fwnode)->name; if (!led.name) { - fwnode_handle_put(fwnode); - return -EINVAL; + ret = EINVAL; + goto err_child_out; } led.active_low = fwnode_property_read_bool(fwnode, @@ -121,12 +121,14 @@ static int led_pwm_create_fwnode(struct device *dev, struct led_pwm_priv *priv) &led.max_brightness); ret = led_pwm_add(dev, priv, &led, fwnode); - if (ret) { - fwnode_handle_put(fwnode); - break; - } + if (ret) + goto err_child_out; } + return 0; + +err_child_out: + fwnode_handle_put(fwnode); return ret; } diff --git a/drivers/leds/leds-tlc591xx.c b/drivers/leds/leds-tlc591xx.c index 5b9dfdf743ec..cb7bd1353f9f 100644 --- a/drivers/leds/leds-tlc591xx.c +++ b/drivers/leds/leds-tlc591xx.c @@ -148,16 +148,20 @@ static int tlc591xx_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct device_node *np = dev_of_node(&client->dev), *child; + struct device_node *np, *child; struct device *dev = &client->dev; const struct tlc591xx *tlc591xx; struct tlc591xx_priv *priv; int err, count, reg; - tlc591xx = device_get_match_data(dev); + np = dev_of_node(dev); if (!np) return -ENODEV; + tlc591xx = device_get_match_data(dev); + if (!tlc591xx) + return -ENODEV; + count = of_get_available_child_count(np); if (!count || count > tlc591xx->max_leds) return -EINVAL; diff --git a/drivers/leds/leds-turris-omnia.c b/drivers/leds/leds-turris-omnia.c index 2f9a289ab245..1adfed1c0619 100644 --- a/drivers/leds/leds-turris-omnia.c +++ b/drivers/leds/leds-turris-omnia.c @@ -274,6 +274,7 @@ static const struct i2c_device_id omnia_id[] = { { "omnia", 0 }, { } }; +MODULE_DEVICE_TABLE(i2c, omnia_id); static struct i2c_driver omnia_leds_driver = { .probe = omnia_leds_probe, diff --git a/drivers/leds/trigger/ledtrig-cpu.c b/drivers/leds/trigger/ledtrig-cpu.c index fca62d503590..8af4f9bb9cde 100644 --- a/drivers/leds/trigger/ledtrig-cpu.c +++ b/drivers/leds/trigger/ledtrig-cpu.c @@ -43,7 +43,7 @@ static atomic_t num_active_cpus = ATOMIC_INIT(0); /** * ledtrig_cpu - emit a CPU event as a trigger - * @evt: CPU event to be emitted + * @ledevt: CPU event to be emitted * * Emit a CPU event on a CPU core, which will trigger a * bound LED to turn on or turn off. diff --git a/drivers/mcb/mcb-lpc.c b/drivers/mcb/mcb-lpc.c index 506676754538..53decd89876e 100644 --- a/drivers/mcb/mcb-lpc.c +++ b/drivers/mcb/mcb-lpc.c @@ -105,17 +105,8 @@ out_put: return ret; } -static struct resource sc24_fpga_resource = { - .start = 0xe000e000, - .end = 0xe000e000 + CHAM_HEADER_SIZE, - .flags = IORESOURCE_MEM, -}; - -static struct resource sc31_fpga_resource = { - .start = 0xf000e000, - .end = 0xf000e000 + CHAM_HEADER_SIZE, - .flags = IORESOURCE_MEM, -}; +static struct resource sc24_fpga_resource = DEFINE_RES_MEM(0xe000e000, CHAM_HEADER_SIZE); +static struct resource sc31_fpga_resource = DEFINE_RES_MEM(0xf000e000, CHAM_HEADER_SIZE); static struct platform_driver mcb_lpc_driver = { .driver = { diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c index 1b24f5bfc4af..e55e411038f4 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.c +++ b/drivers/media/platform/exynos4-is/fimc-is.c @@ -436,7 +436,7 @@ done: static int fimc_is_request_firmware(struct fimc_is *is, const char *fw_name) { return request_firmware_nowait(THIS_MODULE, - FW_ACTION_HOTPLUG, fw_name, &is->pdev->dev, + FW_ACTION_UEVENT, fw_name, &is->pdev->dev, GFP_KERNEL, is, fimc_is_load_firmware); } diff --git a/drivers/memory/pl353-smc.c b/drivers/memory/pl353-smc.c index 9c0a28416777..925d856663ac 100644 --- a/drivers/memory/pl353-smc.c +++ b/drivers/memory/pl353-smc.c @@ -8,263 +8,22 @@ */ #include <linux/clk.h> -#include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/of_platform.h> #include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/pl353-smc.h> #include <linux/amba/bus.h> -/* Register definitions */ -#define PL353_SMC_MEMC_STATUS_OFFS 0 /* Controller status reg, RO */ -#define PL353_SMC_CFG_CLR_OFFS 0xC /* Clear config reg, WO */ -#define PL353_SMC_DIRECT_CMD_OFFS 0x10 /* Direct command reg, WO */ -#define PL353_SMC_SET_CYCLES_OFFS 0x14 /* Set cycles register, WO */ -#define PL353_SMC_SET_OPMODE_OFFS 0x18 /* Set opmode register, WO */ -#define PL353_SMC_ECC_STATUS_OFFS 0x400 /* ECC status register */ -#define PL353_SMC_ECC_MEMCFG_OFFS 0x404 /* ECC mem config reg */ -#define PL353_SMC_ECC_MEMCMD1_OFFS 0x408 /* ECC mem cmd1 reg */ -#define PL353_SMC_ECC_MEMCMD2_OFFS 0x40C /* ECC mem cmd2 reg */ -#define PL353_SMC_ECC_VALUE0_OFFS 0x418 /* ECC value 0 reg */ - -/* Controller status register specific constants */ -#define PL353_SMC_MEMC_STATUS_RAW_INT_1_SHIFT 6 - -/* Clear configuration register specific constants */ -#define PL353_SMC_CFG_CLR_INT_CLR_1 0x10 -#define PL353_SMC_CFG_CLR_ECC_INT_DIS_1 0x40 -#define PL353_SMC_CFG_CLR_INT_DIS_1 0x2 -#define PL353_SMC_CFG_CLR_DEFAULT_MASK (PL353_SMC_CFG_CLR_INT_CLR_1 | \ - PL353_SMC_CFG_CLR_ECC_INT_DIS_1 | \ - PL353_SMC_CFG_CLR_INT_DIS_1) - -/* Set cycles register specific constants */ -#define PL353_SMC_SET_CYCLES_T0_MASK 0xF -#define PL353_SMC_SET_CYCLES_T0_SHIFT 0 -#define PL353_SMC_SET_CYCLES_T1_MASK 0xF -#define PL353_SMC_SET_CYCLES_T1_SHIFT 4 -#define PL353_SMC_SET_CYCLES_T2_MASK 0x7 -#define PL353_SMC_SET_CYCLES_T2_SHIFT 8 -#define PL353_SMC_SET_CYCLES_T3_MASK 0x7 -#define PL353_SMC_SET_CYCLES_T3_SHIFT 11 -#define PL353_SMC_SET_CYCLES_T4_MASK 0x7 -#define PL353_SMC_SET_CYCLES_T4_SHIFT 14 -#define PL353_SMC_SET_CYCLES_T5_MASK 0x7 -#define PL353_SMC_SET_CYCLES_T5_SHIFT 17 -#define PL353_SMC_SET_CYCLES_T6_MASK 0xF -#define PL353_SMC_SET_CYCLES_T6_SHIFT 20 - -/* ECC status register specific constants */ -#define PL353_SMC_ECC_STATUS_BUSY BIT(6) -#define PL353_SMC_ECC_REG_SIZE_OFFS 4 - -/* ECC memory config register specific constants */ -#define PL353_SMC_ECC_MEMCFG_MODE_MASK 0xC -#define PL353_SMC_ECC_MEMCFG_MODE_SHIFT 2 -#define PL353_SMC_ECC_MEMCFG_PGSIZE_MASK 0x3 - -#define PL353_SMC_DC_UPT_NAND_REGS ((4 << 23) | /* CS: NAND chip */ \ - (2 << 21)) /* UpdateRegs operation */ - -#define PL353_NAND_ECC_CMD1 ((0x80) | /* Write command */ \ - (0 << 8) | /* Read command */ \ - (0x30 << 16) | /* Read End command */ \ - (1 << 24)) /* Read End command calid */ - -#define PL353_NAND_ECC_CMD2 ((0x85) | /* Write col change cmd */ \ - (5 << 8) | /* Read col change cmd */ \ - (0xE0 << 16) | /* Read col change end cmd */ \ - (1 << 24)) /* Read col change end cmd valid */ -#define PL353_NAND_ECC_BUSY_TIMEOUT (1 * HZ) /** * struct pl353_smc_data - Private smc driver structure * @memclk: Pointer to the peripheral clock - * @aclk: Pointer to the APER clock + * @aclk: Pointer to the AXI peripheral clock */ struct pl353_smc_data { struct clk *memclk; struct clk *aclk; }; -/* SMC virtual register base */ -static void __iomem *pl353_smc_base; - -/** - * pl353_smc_set_buswidth - Set memory buswidth - * @bw: Memory buswidth (8 | 16) - * Return: 0 on success or negative errno. - */ -int pl353_smc_set_buswidth(unsigned int bw) -{ - if (bw != PL353_SMC_MEM_WIDTH_8 && bw != PL353_SMC_MEM_WIDTH_16) - return -EINVAL; - - writel(bw, pl353_smc_base + PL353_SMC_SET_OPMODE_OFFS); - writel(PL353_SMC_DC_UPT_NAND_REGS, pl353_smc_base + - PL353_SMC_DIRECT_CMD_OFFS); - - return 0; -} -EXPORT_SYMBOL_GPL(pl353_smc_set_buswidth); - -/** - * pl353_smc_set_cycles - Set memory timing parameters - * @timings: NAND controller timing parameters - * - * Sets NAND chip specific timing parameters. - */ -void pl353_smc_set_cycles(u32 timings[]) -{ - /* - * Set write pulse timing. This one is easy to extract: - * - * NWE_PULSE = tWP - */ - timings[0] &= PL353_SMC_SET_CYCLES_T0_MASK; - timings[1] = (timings[1] & PL353_SMC_SET_CYCLES_T1_MASK) << - PL353_SMC_SET_CYCLES_T1_SHIFT; - timings[2] = (timings[2] & PL353_SMC_SET_CYCLES_T2_MASK) << - PL353_SMC_SET_CYCLES_T2_SHIFT; - timings[3] = (timings[3] & PL353_SMC_SET_CYCLES_T3_MASK) << - PL353_SMC_SET_CYCLES_T3_SHIFT; - timings[4] = (timings[4] & PL353_SMC_SET_CYCLES_T4_MASK) << - PL353_SMC_SET_CYCLES_T4_SHIFT; - timings[5] = (timings[5] & PL353_SMC_SET_CYCLES_T5_MASK) << - PL353_SMC_SET_CYCLES_T5_SHIFT; - timings[6] = (timings[6] & PL353_SMC_SET_CYCLES_T6_MASK) << - PL353_SMC_SET_CYCLES_T6_SHIFT; - timings[0] |= timings[1] | timings[2] | timings[3] | - timings[4] | timings[5] | timings[6]; - - writel(timings[0], pl353_smc_base + PL353_SMC_SET_CYCLES_OFFS); - writel(PL353_SMC_DC_UPT_NAND_REGS, pl353_smc_base + - PL353_SMC_DIRECT_CMD_OFFS); -} -EXPORT_SYMBOL_GPL(pl353_smc_set_cycles); - -/** - * pl353_smc_ecc_is_busy - Read ecc busy flag - * Return: the ecc_status bit from the ecc_status register. 1 = busy, 0 = idle - */ -bool pl353_smc_ecc_is_busy(void) -{ - return ((readl(pl353_smc_base + PL353_SMC_ECC_STATUS_OFFS) & - PL353_SMC_ECC_STATUS_BUSY) == PL353_SMC_ECC_STATUS_BUSY); -} -EXPORT_SYMBOL_GPL(pl353_smc_ecc_is_busy); - -/** - * pl353_smc_get_ecc_val - Read ecc_valueN registers - * @ecc_reg: Index of the ecc_value reg (0..3) - * Return: the content of the requested ecc_value register. - * - * There are four valid ecc_value registers. The argument is truncated to stay - * within this valid boundary. - */ -u32 pl353_smc_get_ecc_val(int ecc_reg) -{ - u32 addr, reg; - - addr = PL353_SMC_ECC_VALUE0_OFFS + - (ecc_reg * PL353_SMC_ECC_REG_SIZE_OFFS); - reg = readl(pl353_smc_base + addr); - - return reg; -} -EXPORT_SYMBOL_GPL(pl353_smc_get_ecc_val); - -/** - * pl353_smc_get_nand_int_status_raw - Get NAND interrupt status bit - * Return: the raw_int_status1 bit from the memc_status register - */ -int pl353_smc_get_nand_int_status_raw(void) -{ - u32 reg; - - reg = readl(pl353_smc_base + PL353_SMC_MEMC_STATUS_OFFS); - reg >>= PL353_SMC_MEMC_STATUS_RAW_INT_1_SHIFT; - reg &= 1; - - return reg; -} -EXPORT_SYMBOL_GPL(pl353_smc_get_nand_int_status_raw); - -/** - * pl353_smc_clr_nand_int - Clear NAND interrupt - */ -void pl353_smc_clr_nand_int(void) -{ - writel(PL353_SMC_CFG_CLR_INT_CLR_1, - pl353_smc_base + PL353_SMC_CFG_CLR_OFFS); -} -EXPORT_SYMBOL_GPL(pl353_smc_clr_nand_int); - -/** - * pl353_smc_set_ecc_mode - Set SMC ECC mode - * @mode: ECC mode (BYPASS, APB, MEM) - * Return: 0 on success or negative errno. - */ -int pl353_smc_set_ecc_mode(enum pl353_smc_ecc_mode mode) -{ - u32 reg; - int ret = 0; - - switch (mode) { - case PL353_SMC_ECCMODE_BYPASS: - case PL353_SMC_ECCMODE_APB: - case PL353_SMC_ECCMODE_MEM: - - reg = readl(pl353_smc_base + PL353_SMC_ECC_MEMCFG_OFFS); - reg &= ~PL353_SMC_ECC_MEMCFG_MODE_MASK; - reg |= mode << PL353_SMC_ECC_MEMCFG_MODE_SHIFT; - writel(reg, pl353_smc_base + PL353_SMC_ECC_MEMCFG_OFFS); - - break; - default: - ret = -EINVAL; - } - - return ret; -} -EXPORT_SYMBOL_GPL(pl353_smc_set_ecc_mode); - -/** - * pl353_smc_set_ecc_pg_size - Set SMC ECC page size - * @pg_sz: ECC page size - * Return: 0 on success or negative errno. - */ -int pl353_smc_set_ecc_pg_size(unsigned int pg_sz) -{ - u32 reg, sz; - - switch (pg_sz) { - case 0: - sz = 0; - break; - case SZ_512: - sz = 1; - break; - case SZ_1K: - sz = 2; - break; - case SZ_2K: - sz = 3; - break; - default: - return -EINVAL; - } - - reg = readl(pl353_smc_base + PL353_SMC_ECC_MEMCFG_OFFS); - reg &= ~PL353_SMC_ECC_MEMCFG_PGSIZE_MASK; - reg |= sz; - writel(reg, pl353_smc_base + PL353_SMC_ECC_MEMCFG_OFFS); - - return 0; -} -EXPORT_SYMBOL_GPL(pl353_smc_set_ecc_pg_size); - static int __maybe_unused pl353_smc_suspend(struct device *dev) { struct pl353_smc_data *pl353_smc = dev_get_drvdata(dev); @@ -277,8 +36,8 @@ static int __maybe_unused pl353_smc_suspend(struct device *dev) static int __maybe_unused pl353_smc_resume(struct device *dev) { - int ret; struct pl353_smc_data *pl353_smc = dev_get_drvdata(dev); + int ret; ret = clk_enable(pl353_smc->aclk); if (ret) { @@ -296,77 +55,31 @@ static int __maybe_unused pl353_smc_resume(struct device *dev) return ret; } -static struct amba_driver pl353_smc_driver; - static SIMPLE_DEV_PM_OPS(pl353_smc_dev_pm_ops, pl353_smc_suspend, pl353_smc_resume); -/** - * pl353_smc_init_nand_interface - Initialize the NAND interface - * @adev: Pointer to the amba_device struct - * @nand_node: Pointer to the pl353_nand device_node struct - */ -static void pl353_smc_init_nand_interface(struct amba_device *adev, - struct device_node *nand_node) -{ - unsigned long timeout; - - pl353_smc_set_buswidth(PL353_SMC_MEM_WIDTH_8); - writel(PL353_SMC_CFG_CLR_INT_CLR_1, - pl353_smc_base + PL353_SMC_CFG_CLR_OFFS); - writel(PL353_SMC_DC_UPT_NAND_REGS, pl353_smc_base + - PL353_SMC_DIRECT_CMD_OFFS); - - timeout = jiffies + PL353_NAND_ECC_BUSY_TIMEOUT; - /* Wait till the ECC operation is complete */ - do { - if (pl353_smc_ecc_is_busy()) - cpu_relax(); - else - break; - } while (!time_after_eq(jiffies, timeout)); - - if (time_after_eq(jiffies, timeout)) - return; - - writel(PL353_NAND_ECC_CMD1, - pl353_smc_base + PL353_SMC_ECC_MEMCMD1_OFFS); - writel(PL353_NAND_ECC_CMD2, - pl353_smc_base + PL353_SMC_ECC_MEMCMD2_OFFS); -} - static const struct of_device_id pl353_smc_supported_children[] = { { .compatible = "cfi-flash" }, { .compatible = "arm,pl353-nand-r2p1", - .data = pl353_smc_init_nand_interface }, {} }; static int pl353_smc_probe(struct amba_device *adev, const struct amba_id *id) { + struct device_node *of_node = adev->dev.of_node; + const struct of_device_id *match = NULL; struct pl353_smc_data *pl353_smc; struct device_node *child; - struct resource *res; int err; - struct device_node *of_node = adev->dev.of_node; - static void (*init)(struct amba_device *adev, - struct device_node *nand_node); - const struct of_device_id *match = NULL; pl353_smc = devm_kzalloc(&adev->dev, sizeof(*pl353_smc), GFP_KERNEL); if (!pl353_smc) return -ENOMEM; - /* Get the NAND controller virtual address */ - res = &adev->res; - pl353_smc_base = devm_ioremap_resource(&adev->dev, res); - if (IS_ERR(pl353_smc_base)) - return PTR_ERR(pl353_smc_base); - pl353_smc->aclk = devm_clk_get(&adev->dev, "apb_pclk"); if (IS_ERR(pl353_smc->aclk)) { dev_err(&adev->dev, "aclk clock not found.\n"); @@ -388,15 +101,11 @@ static int pl353_smc_probe(struct amba_device *adev, const struct amba_id *id) err = clk_prepare_enable(pl353_smc->memclk); if (err) { dev_err(&adev->dev, "Unable to enable memory clock.\n"); - goto out_clk_dis_aper; + goto disable_axi_clk; } amba_set_drvdata(adev, pl353_smc); - /* clear interrupts */ - writel(PL353_SMC_CFG_CLR_DEFAULT_MASK, - pl353_smc_base + PL353_SMC_CFG_CLR_OFFS); - /* Find compatible children. Only a single child is supported */ for_each_available_child_of_node(of_node, child) { match = of_match_node(pl353_smc_supported_children, child); @@ -408,19 +117,16 @@ static int pl353_smc_probe(struct amba_device *adev, const struct amba_id *id) } if (!match) { dev_err(&adev->dev, "no matching children\n"); - goto out_clk_disable; + goto disable_mem_clk; } - init = match->data; - if (init) - init(adev, child); of_platform_device_create(child, NULL, &adev->dev); return 0; -out_clk_disable: +disable_mem_clk: clk_disable_unprepare(pl353_smc->memclk); -out_clk_dis_aper: +disable_axi_clk: clk_disable_unprepare(pl353_smc->aclk); return err; @@ -436,8 +142,8 @@ static void pl353_smc_remove(struct amba_device *adev) static const struct amba_id pl353_ids[] = { { - .id = 0x00041353, - .mask = 0x000fffff, + .id = 0x00041353, + .mask = 0x000fffff, }, { 0, 0 }, }; diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index c7f964996a91..eaf9845633b4 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -122,12 +122,7 @@ static const struct i2c_device_id pm80x_id_table[] = { MODULE_DEVICE_TABLE(i2c, pm80x_id_table); static const struct resource rtc_resources[] = { - { - .name = "88pm80x-rtc", - .start = PM800_IRQ_RTC, - .end = PM800_IRQ_RTC, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(PM800_IRQ_RTC, "88pm80x-rtc"), }; static struct mfd_cell rtc_devs[] = { @@ -140,12 +135,7 @@ static struct mfd_cell rtc_devs[] = { }; static struct resource onkey_resources[] = { - { - .name = "88pm80x-onkey", - .start = PM800_IRQ_ONKEY, - .end = PM800_IRQ_ONKEY, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(PM800_IRQ_ONKEY, "88pm80x-onkey"), }; static const struct mfd_cell onkey_devs[] = { diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c index 39f2302e137b..ada6c513302b 100644 --- a/drivers/mfd/88pm805.c +++ b/drivers/mfd/88pm805.c @@ -54,27 +54,14 @@ enum { }; static struct resource codec_resources[] = { - { - /* Headset microphone insertion or removal */ - .name = "micin", - .start = PM805_IRQ_MIC_DET, - .end = PM805_IRQ_MIC_DET, - .flags = IORESOURCE_IRQ, - }, - { - /* Audio short HP1 */ - .name = "audio-short1", - .start = PM805_IRQ_HP1_SHRT, - .end = PM805_IRQ_HP1_SHRT, - .flags = IORESOURCE_IRQ, - }, - { - /* Audio short HP2 */ - .name = "audio-short2", - .start = PM805_IRQ_HP2_SHRT, - .end = PM805_IRQ_HP2_SHRT, - .flags = IORESOURCE_IRQ, - }, + /* Headset microphone insertion or removal */ + DEFINE_RES_IRQ_NAMED(PM805_IRQ_MIC_DET, "micin"), + + /* Audio short HP1 */ + DEFINE_RES_IRQ_NAMED(PM805_IRQ_HP1_SHRT, "audio-short1"), + + /* Audio short HP2 */ + DEFINE_RES_IRQ_NAMED(PM805_IRQ_HP2_SHRT, "audio-short2"), }; static const struct mfd_cell codec_devs[] = { diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 99c4e1a80ae0..6a3fd2d75f96 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -465,6 +465,7 @@ config MFD_MP2629 tristate "Monolithic Power Systems MP2629 ADC and Battery charger" depends on I2C select REGMAP_I2C + select MFD_CORE help Select this option to enable support for Monolithic Power Systems battery charger. This provides ADC, thermal and battery charger power @@ -902,6 +903,7 @@ config MFD_MT6360 select MFD_CORE select REGMAP_I2C select REGMAP_IRQ + select CRC8 depends on I2C help Say Y here to enable MT6360 PMU/PMIC/LDO functional support. @@ -1076,6 +1078,16 @@ config MFD_RDC321X southbridge which provides access to GPIOs and Watchdog using the southbridge PCI device configuration space. +config MFD_RT4831 + tristate "Richtek RT4831 four channel WLED and Display Bias Voltage" + depends on I2C + select MFD_CORE + select REGMAP_I2C + help + This enables support for the Richtek RT4831 that includes 4 channel + WLED driving and Display Bias Voltage. It's commonly used to provide + power to the LCD display and LCD backlight. + config MFD_RT5033 tristate "Richtek RT5033 Power Management IC" depends on I2C @@ -1133,6 +1145,7 @@ config MFD_RN5T618 config MFD_SEC_CORE tristate "Samsung Electronics PMIC Series Support" depends on I2C=y + depends on OF || COMPILE_TEST select MFD_CORE select REGMAP_I2C select REGMAP_IRQ @@ -1770,7 +1783,7 @@ config MFD_ARIZONA select REGMAP select REGMAP_IRQ select MFD_CORE - bool + tristate config MFD_ARIZONA_I2C tristate "Cirrus Logic/Wolfson Microelectronics Arizona platform with I2C" @@ -2087,6 +2100,20 @@ config MFD_ACER_A500_EC The controller itself is ENE KB930, it is running firmware customized for the specific needs of the Acer A500 hardware. +config MFD_QCOM_PM8008 + tristate "QCOM PM8008 Power Management IC" + depends on I2C && OF + select REGMAP_I2C + select REGMAP_IRQ + help + Select this option to get support for the Qualcomm Technologies, Inc. + PM8008 PMIC chip. PM8008 is a dedicated camera PMIC that integrates + all the necessary power management, housekeeping, and interface + support functions into a single IC. This driver provides common + support for accessing the device by instantiating all the child nodes + under it in the device tree. Additional drivers must be enabled in + order to use the functionality of the device. + menu "Multimedia Capabilities Port drivers" depends on ARCH_SA1100 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 8b322d89a0c5..8116c19d5fd4 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -41,24 +41,24 @@ obj-$(CONFIG_MFD_TQMX86) += tqmx86.o obj-$(CONFIG_MFD_LOCHNAGAR) += lochnagar-i2c.o -obj-$(CONFIG_MFD_ARIZONA) += arizona-core.o -obj-$(CONFIG_MFD_ARIZONA) += arizona-irq.o +arizona-objs := arizona-core.o arizona-irq.o +obj-$(CONFIG_MFD_ARIZONA) += arizona.o obj-$(CONFIG_MFD_ARIZONA_I2C) += arizona-i2c.o obj-$(CONFIG_MFD_ARIZONA_SPI) += arizona-spi.o ifeq ($(CONFIG_MFD_WM5102),y) -obj-$(CONFIG_MFD_ARIZONA) += wm5102-tables.o +arizona-objs += wm5102-tables.o endif ifeq ($(CONFIG_MFD_WM5110),y) -obj-$(CONFIG_MFD_ARIZONA) += wm5110-tables.o +arizona-objs += wm5110-tables.o endif ifeq ($(CONFIG_MFD_WM8997),y) -obj-$(CONFIG_MFD_ARIZONA) += wm8997-tables.o +arizona-objs += wm8997-tables.o endif ifeq ($(CONFIG_MFD_WM8998),y) -obj-$(CONFIG_MFD_ARIZONA) += wm8998-tables.o +arizona-objs += wm8998-tables.o endif ifeq ($(CONFIG_MFD_CS47L24),y) -obj-$(CONFIG_MFD_ARIZONA) += cs47l24-tables.o +arizona-objs += cs47l24-tables.o endif obj-$(CONFIG_MFD_WCD934X) += wcd934x.o obj-$(CONFIG_MFD_WM8400) += wm8400-core.o @@ -233,6 +233,7 @@ obj-$(CONFIG_MFD_MENF21BMC) += menf21bmc.o obj-$(CONFIG_MFD_HI6421_PMIC) += hi6421-pmic-core.o obj-$(CONFIG_MFD_HI655X_PMIC) += hi655x-pmic.o obj-$(CONFIG_MFD_DLN2) += dln2.o +obj-$(CONFIG_MFD_RT4831) += rt4831.o obj-$(CONFIG_MFD_RT5033) += rt5033.o obj-$(CONFIG_MFD_SKY81452) += sky81452.o @@ -263,6 +264,7 @@ obj-$(CONFIG_MFD_ROHM_BD957XMUF) += rohm-bd9576.o obj-$(CONFIG_MFD_STMFX) += stmfx.o obj-$(CONFIG_MFD_KHADAS_MCU) += khadas-mcu.o obj-$(CONFIG_MFD_ACER_A500_EC) += acer-ec-a500.o +obj-$(CONFIG_MFD_QCOM_PM8008) += qcom-pm8008.o obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o obj-$(CONFIG_MFD_SIMPLE_MFD_I2C) += simple-mfd-i2c.o diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index c2ba498ad302..30489670ea52 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -827,8 +827,8 @@ static const struct mfd_cell ab8540_cut2_devs[] = { }, }; -static ssize_t show_chip_id(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t chip_id_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct ab8500 *ab8500; @@ -848,8 +848,8 @@ static ssize_t show_chip_id(struct device *dev, * 0x40 Power on key 1 pressed longer than 10 seconds * 0x80 DB8500 thermal shutdown */ -static ssize_t show_switch_off_status(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t switch_off_status_show(struct device *dev, + struct device_attribute *attr, char *buf) { int ret; u8 value; @@ -883,8 +883,8 @@ void ab8500_override_turn_on_stat(u8 mask, u8 set) * 0x40 UsbIDDetect * 0x80 Reserved */ -static ssize_t show_turn_on_status(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t turn_on_status_show(struct device *dev, + struct device_attribute *attr, char *buf) { int ret; u8 value; @@ -912,8 +912,8 @@ static ssize_t show_turn_on_status(struct device *dev, return sprintf(buf, "%#x\n", value); } -static ssize_t show_turn_on_status_2(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t turn_on_status_2_show(struct device *dev, + struct device_attribute *attr, char *buf) { int ret; u8 value; @@ -927,8 +927,8 @@ static ssize_t show_turn_on_status_2(struct device *dev, return sprintf(buf, "%#x\n", (value & 0x1)); } -static ssize_t show_ab9540_dbbrstn(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t dbbrstn_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct ab8500 *ab8500; int ret; @@ -945,7 +945,7 @@ static ssize_t show_ab9540_dbbrstn(struct device *dev, (value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0); } -static ssize_t store_ab9540_dbbrstn(struct device *dev, +static ssize_t dbbrstn_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct ab8500 *ab8500; @@ -980,12 +980,11 @@ exit: return ret; } -static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL); -static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL); -static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL); -static DEVICE_ATTR(turn_on_status_2, S_IRUGO, show_turn_on_status_2, NULL); -static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR, - show_ab9540_dbbrstn, store_ab9540_dbbrstn); +static DEVICE_ATTR_RO(chip_id); +static DEVICE_ATTR_RO(switch_off_status); +static DEVICE_ATTR_RO(turn_on_status); +static DEVICE_ATTR_RO(turn_on_status_2); +static DEVICE_ATTR_RW(dbbrstn); static struct attribute *ab8500_sysfs_entries[] = { &dev_attr_chip_id.attr, diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index ce6fe6de34f8..9323b1e3a69e 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -1447,3 +1447,5 @@ int arizona_dev_exit(struct arizona *arizona) return 0; } EXPORT_SYMBOL_GPL(arizona_dev_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/as3722.c b/drivers/mfd/as3722.c index 59dfeff71592..38665efae4f0 100644 --- a/drivers/mfd/as3722.c +++ b/drivers/mfd/as3722.c @@ -24,21 +24,11 @@ #define AS3722_DEVICE_ID 0x0C static const struct resource as3722_rtc_resource[] = { - { - .name = "as3722-rtc-alarm", - .start = AS3722_IRQ_RTC_ALARM, - .end = AS3722_IRQ_RTC_ALARM, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(AS3722_IRQ_RTC_ALARM, "as3722-rtc-alarm"), }; static const struct resource as3722_adc_resource[] = { - { - .name = "as3722-adc", - .start = AS3722_IRQ_ADC, - .end = AS3722_IRQ_ADC, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(AS3722_IRQ_ADC, "as3722-adc"), }; static const struct mfd_cell as3722_devs[] = { diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index a6bd2134cea2..8d58c8df46cf 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -723,16 +723,8 @@ static struct tmio_mmc_data asic3_mmc_data = { }; static struct resource asic3_mmc_resources[] = { - { - .start = ASIC3_SD_CTRL_BASE, - .end = ASIC3_SD_CTRL_BASE + 0x3ff, - .flags = IORESOURCE_MEM, - }, - { - .start = 0, - .end = 0, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_MEM(ASIC3_SD_CTRL_BASE, 0x400), + DEFINE_RES_IRQ(0) }; static int asic3_mmc_enable(struct platform_device *pdev) diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index 3eae04e24ac8..4145a38b3890 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -884,8 +884,13 @@ int axp20x_match_device(struct axp20x_dev *axp20x) axp20x->regmap_irq_chip = &axp803_regmap_irq_chip; break; case AXP806_ID: + /* + * Don't register the power key part if in slave mode or + * if there is no interrupt line. + */ if (of_property_read_bool(axp20x->dev->of_node, - "x-powers,self-working-mode")) { + "x-powers,self-working-mode") && + axp20x->irq > 0) { axp20x->nr_cells = ARRAY_SIZE(axp806_self_working_cells); axp20x->cells = axp806_self_working_cells; } else { @@ -959,12 +964,17 @@ int axp20x_device_probe(struct axp20x_dev *axp20x) AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE); } - ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq, - IRQF_ONESHOT | IRQF_SHARED | axp20x->irq_flags, - -1, axp20x->regmap_irq_chip, &axp20x->regmap_irqc); - if (ret) { - dev_err(axp20x->dev, "failed to add irq chip: %d\n", ret); - return ret; + /* Only if there is an interrupt line connected towards the CPU. */ + if (axp20x->irq > 0) { + ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq, + IRQF_ONESHOT | IRQF_SHARED | axp20x->irq_flags, + -1, axp20x->regmap_irq_chip, + &axp20x->regmap_irqc); + if (ret) { + dev_err(axp20x->dev, "failed to add irq chip: %d\n", + ret); + return ret; + } } ret = mfd_add_devices(axp20x->dev, -1, axp20x->cells, diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index d07b43d7c761..8c08d1c55726 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c @@ -5,6 +5,7 @@ * Copyright (C) 2014 Google, Inc. */ +#include <linux/dmi.h> #include <linux/kconfig.h> #include <linux/mfd/core.h> #include <linux/module.h> @@ -112,8 +113,12 @@ static const struct cros_feature_to_cells cros_subdevices[] = { static const struct mfd_cell cros_ec_platform_cells[] = { { .name = "cros-ec-chardev", }, { .name = "cros-ec-debugfs", }, - { .name = "cros-ec-lightbar", }, { .name = "cros-ec-sysfs", }, + { .name = "cros-ec-pchg", }, +}; + +static const struct mfd_cell cros_ec_lightbar_cells[] = { + { .name = "cros-ec-lightbar", } }; static const struct mfd_cell cros_ec_vbc_cells[] = { @@ -207,6 +212,20 @@ static int ec_device_probe(struct platform_device *pdev) } /* + * Lightbar is a special case. Newer devices support autodetection, + * but older ones do not. + */ + if (cros_ec_check_features(ec, EC_FEATURE_LIGHTBAR) || + dmi_match(DMI_PRODUCT_NAME, "Link")) { + retval = mfd_add_hotplug_devices(ec->dev, + cros_ec_lightbar_cells, + ARRAY_SIZE(cros_ec_lightbar_cells)); + if (retval) + dev_warn(ec->dev, "failed to add lightbar: %d\n", + retval); + } + + /* * The PD notifier driver cell is separate since it only needs to be * explicitly added on platforms that don't have the PD notifier ACPI * device entry defined. diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c index 47556d2d9abe..8de93db35f3a 100644 --- a/drivers/mfd/da9052-i2c.c +++ b/drivers/mfd/da9052-i2c.c @@ -113,6 +113,7 @@ static const struct i2c_device_id da9052_i2c_id[] = { {"da9053-bc", DA9053_BC}, {} }; +MODULE_DEVICE_TABLE(i2c, da9052_i2c_id); #ifdef CONFIG_OF static const struct of_device_id dialog_dt_ids[] = { @@ -154,13 +155,8 @@ static int da9052_i2c_probe(struct i2c_client *client, return ret; #ifdef CONFIG_OF - if (!id) { - struct device_node *np = client->dev.of_node; - const struct of_device_id *deviceid; - - deviceid = of_match_node(dialog_dt_ids, np); - id = deviceid->data; - } + if (!id) + id = of_device_get_match_data(&client->dev); #endif if (!id) { diff --git a/drivers/mfd/da9055-core.c b/drivers/mfd/da9055-core.c index d074d213e661..c3bcbd8905c6 100644 --- a/drivers/mfd/da9055-core.c +++ b/drivers/mfd/da9055-core.c @@ -254,41 +254,19 @@ const struct regmap_config da9055_regmap_config = { }; EXPORT_SYMBOL_GPL(da9055_regmap_config); -static const struct resource da9055_onkey_resource = { - .name = "ONKEY", - .start = DA9055_IRQ_NONKEY, - .end = DA9055_IRQ_NONKEY, - .flags = IORESOURCE_IRQ, -}; +static const struct resource da9055_onkey_resource = + DEFINE_RES_IRQ_NAMED(DA9055_IRQ_NONKEY, "ONKEY"); static const struct resource da9055_rtc_resource[] = { - { - .name = "ALM", - .start = DA9055_IRQ_ALARM, - .end = DA9055_IRQ_ALARM, - .flags = IORESOURCE_IRQ, - }, - { - .name = "TICK", - .start = DA9055_IRQ_TICK, - .end = DA9055_IRQ_TICK, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(DA9055_IRQ_ALARM, "ALM"), + DEFINE_RES_IRQ_NAMED(DA9055_IRQ_TICK, "TICK"), }; -static const struct resource da9055_hwmon_resource = { - .name = "HWMON", - .start = DA9055_IRQ_HWMON, - .end = DA9055_IRQ_HWMON, - .flags = IORESOURCE_IRQ, -}; +static const struct resource da9055_hwmon_resource = + DEFINE_RES_IRQ_NAMED(DA9055_IRQ_HWMON, "HWMON"); -static const struct resource da9055_ld05_6_resource = { - .name = "REGULATOR", - .start = DA9055_IRQ_REGULATOR, - .end = DA9055_IRQ_REGULATOR, - .flags = IORESOURCE_IRQ, -}; +static const struct resource da9055_ld05_6_resource = + DEFINE_RES_IRQ_NAMED(DA9055_IRQ_REGULATOR, "REGULATOR"); static const struct mfd_cell da9055_devs[] = { { diff --git a/drivers/mfd/da9062-core.c b/drivers/mfd/da9062-core.c index 8d913375152d..01f8e10dfa55 100644 --- a/drivers/mfd/da9062-core.c +++ b/drivers/mfd/da9062-core.c @@ -9,6 +9,7 @@ #include <linux/init.h> #include <linux/device.h> #include <linux/interrupt.h> +#include <linux/of_device.h> #include <linux/regmap.h> #include <linux/irq.h> #include <linux/mfd/core.h> @@ -622,7 +623,6 @@ static int da9062_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct da9062 *chip; - const struct of_device_id *match; unsigned int irq_base; const struct mfd_cell *cell; const struct regmap_irq_chip *irq_chip; @@ -635,15 +635,10 @@ static int da9062_i2c_probe(struct i2c_client *i2c, if (!chip) return -ENOMEM; - if (i2c->dev.of_node) { - match = of_match_node(da9062_dt_ids, i2c->dev.of_node); - if (!match) - return -EINVAL; - - chip->chip_type = (uintptr_t)match->data; - } else { + if (i2c->dev.of_node) + chip->chip_type = (uintptr_t)of_device_get_match_data(&i2c->dev); + else chip->chip_type = id->driver_data; - } i2c_set_clientdata(i2c, chip); chip->dev = &i2c->dev; diff --git a/drivers/mfd/da9063-i2c.c b/drivers/mfd/da9063-i2c.c index 783a14af18e2..4b7f707b7952 100644 --- a/drivers/mfd/da9063-i2c.c +++ b/drivers/mfd/da9063-i2c.c @@ -448,7 +448,7 @@ static int da9063_i2c_probe(struct i2c_client *i2c, DA9063_TWOWIRE_TO); if (ret < 0) { dev_err(da9063->dev, "Failed to set Two-Wire Bus Mode.\n"); - return -EIO; + return ret; } } diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 167faac9b75b..3bde7fda755f 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -616,7 +616,7 @@ enum romcode_read prcmu_get_rc_p2a(void) } /** - * prcmu_get_current_mode - Return the current XP70 power mode + * prcmu_get_xp70_current_state - Return the current XP70 power mode * Returns: Returns the current AP(ARM) power mode: init, * apBoot, apExecute, apDeepSleep, apSleep, apIdle, apReset */ @@ -898,7 +898,7 @@ unlock_and_return: } /** - * db8500_set_ape_opp - set the appropriate APE OPP + * db8500_prcmu_set_ape_opp - set the appropriate APE OPP * @opp: The new APE operating point to which transition is to be made * Returns: 0 on success, non-zero on failure * @@ -2297,7 +2297,7 @@ u16 db8500_prcmu_get_reset_code(void) } /** - * db8500_prcmu_reset_modem - ask the PRCMU to reset modem + * db8500_prcmu_modem_reset - ask the PRCMU to reset modem */ void db8500_prcmu_modem_reset(void) { diff --git a/drivers/mfd/hi655x-pmic.c b/drivers/mfd/hi655x-pmic.c index d3c86a7a3805..6909d075d017 100644 --- a/drivers/mfd/hi655x-pmic.c +++ b/drivers/mfd/hi655x-pmic.c @@ -2,7 +2,7 @@ /* * Device driver for MFD hi655x PMIC * - * Copyright (c) 2016 Hisilicon. + * Copyright (c) 2016 HiSilicon Ltd. * * Authors: * Chen Feng <puck.chen@hisilicon.com> diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c index 79c53617489c..c54d19fb184c 100644 --- a/drivers/mfd/intel-lpss-pci.c +++ b/drivers/mfd/intel-lpss-pci.c @@ -310,6 +310,19 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x51ea), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x51eb), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x51fb), (kernel_ulong_t)&bxt_info }, + /* ADL-M */ + { PCI_VDEVICE(INTEL, 0x54a8), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x54a9), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x54aa), (kernel_ulong_t)&bxt_info }, + { PCI_VDEVICE(INTEL, 0x54ab), (kernel_ulong_t)&bxt_info }, + { PCI_VDEVICE(INTEL, 0x54c5), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x54c6), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x54c7), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x54e8), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x54e9), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x54ea), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x54eb), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x54fb), (kernel_ulong_t)&bxt_info }, /* APL */ { PCI_VDEVICE(INTEL, 0x5aac), (kernel_ulong_t)&apl_i2c_info }, { PCI_VDEVICE(INTEL, 0x5aae), (kernel_ulong_t)&apl_i2c_info }, diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c b/drivers/mfd/intel_soc_pmic_bxtwc.c index 47d0d3a69a58..bc069c4daa60 100644 --- a/drivers/mfd/intel_soc_pmic_bxtwc.c +++ b/drivers/mfd/intel_soc_pmic_bxtwc.c @@ -330,14 +330,14 @@ static int regmap_ipc_byte_reg_write(void *context, unsigned int reg, /* sysfs interfaces to r/w PMIC registers, required by initial script */ static unsigned long bxtwc_reg_addr; -static ssize_t bxtwc_reg_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t addr_show(struct device *dev, + struct device_attribute *attr, char *buf) { return sprintf(buf, "0x%lx\n", bxtwc_reg_addr); } -static ssize_t bxtwc_reg_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t addr_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { if (kstrtoul(buf, 0, &bxtwc_reg_addr)) { dev_err(dev, "Invalid register address\n"); @@ -346,8 +346,8 @@ static ssize_t bxtwc_reg_store(struct device *dev, return (ssize_t)count; } -static ssize_t bxtwc_val_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t val_show(struct device *dev, + struct device_attribute *attr, char *buf) { int ret; unsigned int val; @@ -362,8 +362,8 @@ static ssize_t bxtwc_val_show(struct device *dev, return sprintf(buf, "0x%02x\n", val); } -static ssize_t bxtwc_val_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t val_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { int ret; unsigned int val; @@ -382,8 +382,8 @@ static ssize_t bxtwc_val_store(struct device *dev, return count; } -static DEVICE_ATTR(addr, S_IWUSR | S_IRUSR, bxtwc_reg_show, bxtwc_reg_store); -static DEVICE_ATTR(val, S_IWUSR | S_IRUSR, bxtwc_val_show, bxtwc_val_store); +static DEVICE_ATTR_ADMIN_RW(addr); +static DEVICE_ATTR_ADMIN_RW(val); static struct attribute *bxtwc_attrs[] = { &dev_attr_addr.attr, &dev_attr_val.attr, diff --git a/drivers/mfd/iqs62x.c b/drivers/mfd/iqs62x.c index d1fc38a78acb..9805cf191245 100644 --- a/drivers/mfd/iqs62x.c +++ b/drivers/mfd/iqs62x.c @@ -998,7 +998,7 @@ static int iqs62x_probe(struct i2c_client *client) device_property_read_string(&client->dev, "firmware-name", &fw_name); - ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, + ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, fw_name ? : iqs62x->dev_desc->fw_name, &client->dev, GFP_KERNEL, iqs62x, iqs62x_firmware_load); diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c index 3df4e9a2998f..70eba4ce496f 100644 --- a/drivers/mfd/janz-cmodio.c +++ b/drivers/mfd/janz-cmodio.c @@ -149,15 +149,15 @@ static int cmodio_probe_submodules(struct cmodio_device *priv) * SYSFS Attributes */ -static ssize_t mbus_show(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t modulbus_number_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct cmodio_device *priv = dev_get_drvdata(dev); return snprintf(buf, PAGE_SIZE, "%x\n", priv->hex); } -static DEVICE_ATTR(modulbus_number, S_IRUGO, mbus_show, NULL); +static DEVICE_ATTR_RO(modulbus_number); static struct attribute *cmodio_sysfs_attrs[] = { &dev_attr_modulbus_number.attr, diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c index 9166075c1f32..bb26241c73bd 100644 --- a/drivers/mfd/kempld-core.c +++ b/drivers/mfd/kempld-core.c @@ -344,16 +344,16 @@ static const char *kempld_get_type_string(struct kempld_device_data *pld) return version_type; } -static ssize_t kempld_version_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t pld_version_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct kempld_device_data *pld = dev_get_drvdata(dev); return scnprintf(buf, PAGE_SIZE, "%s\n", pld->info.version); } -static ssize_t kempld_specification_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t pld_specification_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct kempld_device_data *pld = dev_get_drvdata(dev); @@ -361,18 +361,17 @@ static ssize_t kempld_specification_show(struct device *dev, pld->info.spec_minor); } -static ssize_t kempld_type_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t pld_type_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct kempld_device_data *pld = dev_get_drvdata(dev); return scnprintf(buf, PAGE_SIZE, "%s\n", kempld_get_type_string(pld)); } -static DEVICE_ATTR(pld_version, S_IRUGO, kempld_version_show, NULL); -static DEVICE_ATTR(pld_specification, S_IRUGO, kempld_specification_show, - NULL); -static DEVICE_ATTR(pld_type, S_IRUGO, kempld_type_show, NULL); +static DEVICE_ATTR_RO(pld_version); +static DEVICE_ATTR_RO(pld_specification); +static DEVICE_ATTR_RO(pld_type); static struct attribute *pld_attributes[] = { &dev_attr_pld_version.attr, diff --git a/drivers/mfd/lp87565.c b/drivers/mfd/lp87565.c index 9c21483d9653..a52ab76febb3 100644 --- a/drivers/mfd/lp87565.c +++ b/drivers/mfd/lp87565.c @@ -5,6 +5,7 @@ * Author: Keerthy <j-keerthy@ti.com> */ +#include <linux/gpio/consumer.h> #include <linux/interrupt.h> #include <linux/mfd/core.h> #include <linux/module.h> @@ -64,6 +65,24 @@ static int lp87565_probe(struct i2c_client *client, return ret; } + lp87565->reset_gpio = devm_gpiod_get_optional(lp87565->dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(lp87565->reset_gpio)) { + ret = PTR_ERR(lp87565->reset_gpio); + if (ret == -EPROBE_DEFER) + return ret; + } + + if (lp87565->reset_gpio) { + gpiod_set_value_cansleep(lp87565->reset_gpio, 1); + /* The minimum assertion time is undocumented, just guess */ + usleep_range(2000, 4000); + + gpiod_set_value_cansleep(lp87565->reset_gpio, 0); + /* Min 1.2 ms before first I2C transaction */ + usleep_range(1500, 3000); + } + ret = regmap_read(lp87565->regmap, LP87565_REG_OTP_REV, &otpid); if (ret) { dev_err(lp87565->dev, "Failed to read OTP ID\n"); @@ -83,6 +102,13 @@ static int lp87565_probe(struct i2c_client *client, NULL, 0, NULL); } +static void lp87565_shutdown(struct i2c_client *client) +{ + struct lp87565 *lp87565 = i2c_get_clientdata(client); + + gpiod_set_value_cansleep(lp87565->reset_gpio, 1); +} + static const struct i2c_device_id lp87565_id_table[] = { { "lp87565-q1", 0 }, { }, @@ -95,6 +121,7 @@ static struct i2c_driver lp87565_driver = { .of_match_table = of_lp87565_match_table, }, .probe = lp87565_probe, + .shutdown = lp87565_shutdown, .id_table = lp87565_id_table, }; module_i2c_driver(lp87565_driver); diff --git a/drivers/mfd/max8907.c b/drivers/mfd/max8907.c index d44baafd9d14..41f566e6a096 100644 --- a/drivers/mfd/max8907.c +++ b/drivers/mfd/max8907.c @@ -228,11 +228,9 @@ static int max8907_i2c_probe(struct i2c_client *i2c, goto err_regmap_rtc; } - irq_set_status_flags(max8907->i2c_gen->irq, IRQ_NOAUTOEN); - ret = regmap_add_irq_chip(max8907->regmap_gen, max8907->i2c_gen->irq, - IRQF_ONESHOT | IRQF_SHARED, -1, - &max8907_chg_irq_chip, + IRQF_ONESHOT | IRQF_SHARED, + -1, &max8907_chg_irq_chip, &max8907->irqc_chg); if (ret != 0) { dev_err(&i2c->dev, "failed to add chg irq chip: %d\n", ret); @@ -255,8 +253,6 @@ static int max8907_i2c_probe(struct i2c_client *i2c, goto err_irqc_rtc; } - enable_irq(max8907->i2c_gen->irq); - ret = mfd_add_devices(max8907->dev, -1, max8907_cells, ARRAY_SIZE(max8907_cells), NULL, 0, NULL); if (ret != 0) { diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index 68d8f2b95287..2141de78115d 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -11,6 +11,7 @@ #include <linux/slab.h> #include <linux/i2c.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/interrupt.h> #include <linux/pm_runtime.h> @@ -145,11 +146,9 @@ static struct max8997_platform_data *max8997_i2c_parse_dt_pdata( static inline unsigned long max8997_i2c_get_driver_data(struct i2c_client *i2c, const struct i2c_device_id *id) { - if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) { - const struct of_device_id *match; - match = of_match_node(max8997_pmic_dt_match, i2c->dev.of_node); - return (unsigned long)match->data; - } + if (i2c->dev.of_node) + return (unsigned long)of_device_get_match_data(&i2c->dev); + return id->driver_data; } diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c index 785f8e9841b7..0eb15e611b67 100644 --- a/drivers/mfd/max8998.c +++ b/drivers/mfd/max8998.c @@ -12,6 +12,7 @@ #include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/pm_runtime.h> #include <linux/mutex.h> @@ -155,11 +156,8 @@ static struct max8998_platform_data *max8998_i2c_parse_dt_pdata( static inline unsigned long max8998_i2c_get_driver_data(struct i2c_client *i2c, const struct i2c_device_id *id) { - if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) { - const struct of_device_id *match; - match = of_match_node(max8998_dt_match, i2c->dev.of_node); - return (unsigned long)match->data; - } + if (i2c->dev.of_node) + return (unsigned long)of_device_get_match_data(&i2c->dev); return id->driver_data; } diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 6f02b8022c6d..79f5c6a18815 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -266,18 +266,18 @@ static int mfd_add_device(struct device *parent, int id, if (has_acpi_companion(&pdev->dev)) { ret = acpi_check_resource_conflict(&res[r]); if (ret) - goto fail_of_entry; + goto fail_res_conflict; } } } ret = platform_device_add_resources(pdev, res, cell->num_resources); if (ret) - goto fail_of_entry; + goto fail_res_conflict; ret = platform_device_add(pdev); if (ret) - goto fail_of_entry; + goto fail_res_conflict; if (cell->pm_runtime_no_callbacks) pm_runtime_no_callbacks(&pdev->dev); @@ -286,13 +286,15 @@ static int mfd_add_device(struct device *parent, int id, return 0; +fail_res_conflict: + if (cell->swnode) + device_remove_software_node(&pdev->dev); fail_of_entry: list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list) if (of_entry->dev == &pdev->dev) { list_del(&of_entry->list); kfree(of_entry); } - device_remove_software_node(&pdev->dev); fail_alias: regulator_bulk_unregister_supply_alias(&pdev->dev, cell->parent_supplies, @@ -358,11 +360,12 @@ static int mfd_remove_devices_fn(struct device *dev, void *data) if (level && cell->level > *level) return 0; + if (cell->swnode) + device_remove_software_node(&pdev->dev); + regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies, cell->num_parent_supplies); - device_remove_software_node(&pdev->dev); - platform_device_unregister(pdev); return 0; } diff --git a/drivers/mfd/motorola-cpcap.c b/drivers/mfd/motorola-cpcap.c index 30d82bfe5b02..6fb206da2729 100644 --- a/drivers/mfd/motorola-cpcap.c +++ b/drivers/mfd/motorola-cpcap.c @@ -327,6 +327,10 @@ static int cpcap_probe(struct spi_device *spi) if (ret) return ret; + /* Parent SPI controller uses DMA, CPCAP and child devices do not */ + spi->dev.coherent_dma_mask = 0; + spi->dev.dma_mask = &spi->dev.coherent_dma_mask; + return devm_mfd_add_devices(&spi->dev, 0, cpcap_mfd_devices, ARRAY_SIZE(cpcap_mfd_devices), NULL, 0, NULL); } diff --git a/drivers/mfd/mt6360-core.c b/drivers/mfd/mt6360-core.c index 480722acf706..e628953548ce 100644 --- a/drivers/mfd/mt6360-core.c +++ b/drivers/mfd/mt6360-core.c @@ -5,121 +5,180 @@ * Author: Gene Chen <gene_chen@richtek.com> */ +#include <linux/crc8.h> #include <linux/i2c.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/mfd/core.h> #include <linux/module.h> -#include <linux/of_irq.h> -#include <linux/of_platform.h> +#include <linux/regmap.h> +#include <linux/slab.h> + +enum { + MT6360_SLAVE_TCPC = 0, + MT6360_SLAVE_PMIC, + MT6360_SLAVE_LDO, + MT6360_SLAVE_PMU, + MT6360_SLAVE_MAX, +}; + +struct mt6360_ddata { + struct i2c_client *i2c[MT6360_SLAVE_MAX]; + struct device *dev; + struct regmap *regmap; + struct regmap_irq_chip_data *irq_data; + unsigned int chip_rev; + u8 crc8_tbl[CRC8_TABLE_SIZE]; +}; -#include <linux/mfd/mt6360.h> +#define MT6360_TCPC_SLAVEID 0x4E +#define MT6360_PMIC_SLAVEID 0x1A +#define MT6360_LDO_SLAVEID 0x64 +#define MT6360_PMU_SLAVEID 0x34 + +#define MT6360_REG_TCPCSTART 0x00 +#define MT6360_REG_TCPCEND 0xFF +#define MT6360_REG_PMICSTART 0x100 +#define MT6360_REG_PMICEND 0x13B +#define MT6360_REG_LDOSTART 0x200 +#define MT6360_REG_LDOEND 0x21C +#define MT6360_REG_PMUSTART 0x300 +#define MT6360_PMU_DEV_INFO 0x300 +#define MT6360_PMU_CHG_IRQ1 0x3D0 +#define MT6360_PMU_CHG_MASK1 0x3F0 +#define MT6360_REG_PMUEND 0x3FF + +#define MT6360_PMU_IRQ_REGNUM 16 + +#define CHIP_VEN_MASK 0xF0 +#define CHIP_VEN_MT6360 0x50 +#define CHIP_REV_MASK 0x0F + +#define MT6360_ADDRESS_MASK 0x3F +#define MT6360_DATA_SIZE_1_BYTE 0x00 +#define MT6360_DATA_SIZE_2_BYTES 0x40 +#define MT6360_DATA_SIZE_3_BYTES 0x80 +#define MT6360_DATA_SIZE_4_BYTES 0xC0 + +#define MT6360_CRC8_POLYNOMIAL 0x7 + +#define MT6360_CRC_I2C_ADDR_SIZE 1 +#define MT6360_CRC_REG_ADDR_SIZE 1 +/* prealloca read size = i2c device addr + i2c reg addr + val ... + crc8 */ +#define MT6360_ALLOC_READ_SIZE(_size) (_size + 3) +/* prealloca write size = i2c device addr + i2c reg addr + val ... + crc8 + dummy byte */ +#define MT6360_ALLOC_WRITE_SIZE(_size) (_size + 4) +#define MT6360_CRC_PREDATA_OFFSET (MT6360_CRC_I2C_ADDR_SIZE + MT6360_CRC_REG_ADDR_SIZE) +#define MT6360_CRC_CRC8_SIZE 1 +#define MT6360_CRC_DUMMY_BYTE_SIZE 1 +#define MT6360_REGMAP_REG_BYTE_SIZE 2 +#define I2C_ADDR_XLATE_8BIT(_addr, _rw) (((_addr & 0x7F) << 1) + _rw) /* reg 0 -> 0 ~ 7 */ -#define MT6360_CHG_TREG_EVT (4) -#define MT6360_CHG_AICR_EVT (5) -#define MT6360_CHG_MIVR_EVT (6) -#define MT6360_PWR_RDY_EVT (7) +#define MT6360_CHG_TREG_EVT 4 +#define MT6360_CHG_AICR_EVT 5 +#define MT6360_CHG_MIVR_EVT 6 +#define MT6360_PWR_RDY_EVT 7 /* REG 1 -> 8 ~ 15 */ -#define MT6360_CHG_BATSYSUV_EVT (9) -#define MT6360_FLED_CHG_VINOVP_EVT (11) -#define MT6360_CHG_VSYSUV_EVT (12) -#define MT6360_CHG_VSYSOV_EVT (13) -#define MT6360_CHG_VBATOV_EVT (14) -#define MT6360_CHG_VBUSOV_EVT (15) +#define MT6360_CHG_BATSYSUV_EVT 9 +#define MT6360_FLED_CHG_VINOVP_EVT 11 +#define MT6360_CHG_VSYSUV_EVT 12 +#define MT6360_CHG_VSYSOV_EVT 13 +#define MT6360_CHG_VBATOV_EVT 14 +#define MT6360_CHG_VBUSOV_EVT 15 /* REG 2 -> 16 ~ 23 */ /* REG 3 -> 24 ~ 31 */ -#define MT6360_WD_PMU_DET (25) -#define MT6360_WD_PMU_DONE (26) -#define MT6360_CHG_TMRI (27) -#define MT6360_CHG_ADPBADI (29) -#define MT6360_CHG_RVPI (30) -#define MT6360_OTPI (31) +#define MT6360_WD_PMU_DET 25 +#define MT6360_WD_PMU_DONE 26 +#define MT6360_CHG_TMRI 27 +#define MT6360_CHG_ADPBADI 29 +#define MT6360_CHG_RVPI 30 +#define MT6360_OTPI 31 /* REG 4 -> 32 ~ 39 */ -#define MT6360_CHG_AICCMEASL (32) -#define MT6360_CHGDET_DONEI (34) -#define MT6360_WDTMRI (35) -#define MT6360_SSFINISHI (36) -#define MT6360_CHG_RECHGI (37) -#define MT6360_CHG_TERMI (38) -#define MT6360_CHG_IEOCI (39) +#define MT6360_CHG_AICCMEASL 32 +#define MT6360_CHGDET_DONEI 34 +#define MT6360_WDTMRI 35 +#define MT6360_SSFINISHI 36 +#define MT6360_CHG_RECHGI 37 +#define MT6360_CHG_TERMI 38 +#define MT6360_CHG_IEOCI 39 /* REG 5 -> 40 ~ 47 */ -#define MT6360_PUMPX_DONEI (40) -#define MT6360_BAT_OVP_ADC_EVT (41) -#define MT6360_TYPEC_OTP_EVT (42) -#define MT6360_ADC_WAKEUP_EVT (43) -#define MT6360_ADC_DONEI (44) -#define MT6360_BST_BATUVI (45) -#define MT6360_BST_VBUSOVI (46) -#define MT6360_BST_OLPI (47) +#define MT6360_PUMPX_DONEI 40 +#define MT6360_BAT_OVP_ADC_EVT 41 +#define MT6360_TYPEC_OTP_EVT 42 +#define MT6360_ADC_WAKEUP_EVT 43 +#define MT6360_ADC_DONEI 44 +#define MT6360_BST_BATUVI 45 +#define MT6360_BST_VBUSOVI 46 +#define MT6360_BST_OLPI 47 /* REG 6 -> 48 ~ 55 */ -#define MT6360_ATTACH_I (48) -#define MT6360_DETACH_I (49) -#define MT6360_QC30_STPDONE (51) -#define MT6360_QC_VBUSDET_DONE (52) -#define MT6360_HVDCP_DET (53) -#define MT6360_CHGDETI (54) -#define MT6360_DCDTI (55) +#define MT6360_ATTACH_I 48 +#define MT6360_DETACH_I 49 +#define MT6360_QC30_STPDONE 51 +#define MT6360_QC_VBUSDET_DONE 52 +#define MT6360_HVDCP_DET 53 +#define MT6360_CHGDETI 54 +#define MT6360_DCDTI 55 /* REG 7 -> 56 ~ 63 */ -#define MT6360_FOD_DONE_EVT (56) -#define MT6360_FOD_OV_EVT (57) -#define MT6360_CHRDET_UVP_EVT (58) -#define MT6360_CHRDET_OVP_EVT (59) -#define MT6360_CHRDET_EXT_EVT (60) -#define MT6360_FOD_LR_EVT (61) -#define MT6360_FOD_HR_EVT (62) -#define MT6360_FOD_DISCHG_FAIL_EVT (63) +#define MT6360_FOD_DONE_EVT 56 +#define MT6360_FOD_OV_EVT 57 +#define MT6360_CHRDET_UVP_EVT 58 +#define MT6360_CHRDET_OVP_EVT 59 +#define MT6360_CHRDET_EXT_EVT 60 +#define MT6360_FOD_LR_EVT 61 +#define MT6360_FOD_HR_EVT 62 +#define MT6360_FOD_DISCHG_FAIL_EVT 63 /* REG 8 -> 64 ~ 71 */ -#define MT6360_USBID_EVT (64) -#define MT6360_APWDTRST_EVT (65) -#define MT6360_EN_EVT (66) -#define MT6360_QONB_RST_EVT (67) -#define MT6360_MRSTB_EVT (68) -#define MT6360_OTP_EVT (69) -#define MT6360_VDDAOV_EVT (70) -#define MT6360_SYSUV_EVT (71) +#define MT6360_USBID_EVT 64 +#define MT6360_APWDTRST_EVT 65 +#define MT6360_EN_EVT 66 +#define MT6360_QONB_RST_EVT 67 +#define MT6360_MRSTB_EVT 68 +#define MT6360_OTP_EVT 69 +#define MT6360_VDDAOV_EVT 70 +#define MT6360_SYSUV_EVT 71 /* REG 9 -> 72 ~ 79 */ -#define MT6360_FLED_STRBPIN_EVT (72) -#define MT6360_FLED_TORPIN_EVT (73) -#define MT6360_FLED_TX_EVT (74) -#define MT6360_FLED_LVF_EVT (75) -#define MT6360_FLED2_SHORT_EVT (78) -#define MT6360_FLED1_SHORT_EVT (79) +#define MT6360_FLED_STRBPIN_EVT 72 +#define MT6360_FLED_TORPIN_EVT 73 +#define MT6360_FLED_TX_EVT 74 +#define MT6360_FLED_LVF_EVT 75 +#define MT6360_FLED2_SHORT_EVT 78 +#define MT6360_FLED1_SHORT_EVT 79 /* REG 10 -> 80 ~ 87 */ -#define MT6360_FLED2_STRB_EVT (80) -#define MT6360_FLED1_STRB_EVT (81) -#define MT6360_FLED2_STRB_TO_EVT (82) -#define MT6360_FLED1_STRB_TO_EVT (83) -#define MT6360_FLED2_TOR_EVT (84) -#define MT6360_FLED1_TOR_EVT (85) +#define MT6360_FLED2_STRB_EVT 80 +#define MT6360_FLED1_STRB_EVT 81 +#define MT6360_FLED2_STRB_TO_EVT 82 +#define MT6360_FLED1_STRB_TO_EVT 83 +#define MT6360_FLED2_TOR_EVT 84 +#define MT6360_FLED1_TOR_EVT 85 /* REG 11 -> 88 ~ 95 */ /* REG 12 -> 96 ~ 103 */ -#define MT6360_BUCK1_PGB_EVT (96) -#define MT6360_BUCK1_OC_EVT (100) -#define MT6360_BUCK1_OV_EVT (101) -#define MT6360_BUCK1_UV_EVT (102) +#define MT6360_BUCK1_PGB_EVT 96 +#define MT6360_BUCK1_OC_EVT 100 +#define MT6360_BUCK1_OV_EVT 101 +#define MT6360_BUCK1_UV_EVT 102 /* REG 13 -> 104 ~ 111 */ -#define MT6360_BUCK2_PGB_EVT (104) -#define MT6360_BUCK2_OC_EVT (108) -#define MT6360_BUCK2_OV_EVT (109) -#define MT6360_BUCK2_UV_EVT (110) +#define MT6360_BUCK2_PGB_EVT 104 +#define MT6360_BUCK2_OC_EVT 108 +#define MT6360_BUCK2_OV_EVT 109 +#define MT6360_BUCK2_UV_EVT 110 /* REG 14 -> 112 ~ 119 */ -#define MT6360_LDO1_OC_EVT (113) -#define MT6360_LDO2_OC_EVT (114) -#define MT6360_LDO3_OC_EVT (115) -#define MT6360_LDO5_OC_EVT (117) -#define MT6360_LDO6_OC_EVT (118) -#define MT6360_LDO7_OC_EVT (119) +#define MT6360_LDO1_OC_EVT 113 +#define MT6360_LDO2_OC_EVT 114 +#define MT6360_LDO3_OC_EVT 115 +#define MT6360_LDO5_OC_EVT 117 +#define MT6360_LDO6_OC_EVT 118 +#define MT6360_LDO7_OC_EVT 119 /* REG 15 -> 120 ~ 127 */ -#define MT6360_LDO1_PGB_EVT (121) -#define MT6360_LDO2_PGB_EVT (122) -#define MT6360_LDO3_PGB_EVT (123) -#define MT6360_LDO5_PGB_EVT (125) -#define MT6360_LDO6_PGB_EVT (126) -#define MT6360_LDO7_PGB_EVT (127) - -static const struct regmap_irq mt6360_pmu_irqs[] = { +#define MT6360_LDO1_PGB_EVT 121 +#define MT6360_LDO2_PGB_EVT 122 +#define MT6360_LDO3_PGB_EVT 123 +#define MT6360_LDO5_PGB_EVT 125 +#define MT6360_LDO6_PGB_EVT 126 +#define MT6360_LDO7_PGB_EVT 127 + +static const struct regmap_irq mt6360_irqs[] = { REGMAP_IRQ_REG_LINE(MT6360_CHG_TREG_EVT, 8), REGMAP_IRQ_REG_LINE(MT6360_CHG_AICR_EVT, 8), REGMAP_IRQ_REG_LINE(MT6360_CHG_MIVR_EVT, 8), @@ -208,30 +267,16 @@ static const struct regmap_irq mt6360_pmu_irqs[] = { REGMAP_IRQ_REG_LINE(MT6360_LDO7_PGB_EVT, 8), }; -static int mt6360_pmu_handle_post_irq(void *irq_drv_data) -{ - struct mt6360_pmu_data *mpd = irq_drv_data; - - return regmap_update_bits(mpd->regmap, - MT6360_PMU_IRQ_SET, MT6360_IRQ_RETRIG, MT6360_IRQ_RETRIG); -} - -static struct regmap_irq_chip mt6360_pmu_irq_chip = { - .irqs = mt6360_pmu_irqs, - .num_irqs = ARRAY_SIZE(mt6360_pmu_irqs), +static const struct regmap_irq_chip mt6360_irq_chip = { + .name = "mt6360_irqs", + .irqs = mt6360_irqs, + .num_irqs = ARRAY_SIZE(mt6360_irqs), .num_regs = MT6360_PMU_IRQ_REGNUM, .mask_base = MT6360_PMU_CHG_MASK1, .status_base = MT6360_PMU_CHG_IRQ1, .ack_base = MT6360_PMU_CHG_IRQ1, .init_ack_masked = true, .use_ack = true, - .handle_post_irq = mt6360_pmu_handle_post_irq, -}; - -static const struct regmap_config mt6360_pmu_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .max_register = MT6360_PMU_MAXREG, }; static const struct resource mt6360_adc_resources[] = { @@ -265,7 +310,7 @@ static const struct resource mt6360_led_resources[] = { DEFINE_RES_IRQ_NAMED(MT6360_FLED1_STRB_TO_EVT, "fled1_strb_to_evt"), }; -static const struct resource mt6360_pmic_resources[] = { +static const struct resource mt6360_regulator_resources[] = { DEFINE_RES_IRQ_NAMED(MT6360_BUCK1_PGB_EVT, "buck1_pgb_evt"), DEFINE_RES_IRQ_NAMED(MT6360_BUCK1_OC_EVT, "buck1_oc_evt"), DEFINE_RES_IRQ_NAMED(MT6360_BUCK1_OV_EVT, "buck1_ov_evt"), @@ -278,9 +323,6 @@ static const struct resource mt6360_pmic_resources[] = { DEFINE_RES_IRQ_NAMED(MT6360_LDO7_OC_EVT, "ldo7_oc_evt"), DEFINE_RES_IRQ_NAMED(MT6360_LDO6_PGB_EVT, "ldo6_pgb_evt"), DEFINE_RES_IRQ_NAMED(MT6360_LDO7_PGB_EVT, "ldo7_pgb_evt"), -}; - -static const struct resource mt6360_ldo_resources[] = { DEFINE_RES_IRQ_NAMED(MT6360_LDO1_OC_EVT, "ldo1_oc_evt"), DEFINE_RES_IRQ_NAMED(MT6360_LDO2_OC_EVT, "ldo2_oc_evt"), DEFINE_RES_IRQ_NAMED(MT6360_LDO3_OC_EVT, "ldo3_oc_evt"), @@ -292,84 +334,241 @@ static const struct resource mt6360_ldo_resources[] = { }; static const struct mfd_cell mt6360_devs[] = { - MFD_CELL_OF("mt6360_adc", mt6360_adc_resources, - NULL, 0, 0, "mediatek,mt6360_adc"), - MFD_CELL_OF("mt6360_chg", mt6360_chg_resources, - NULL, 0, 0, "mediatek,mt6360_chg"), - MFD_CELL_OF("mt6360_led", mt6360_led_resources, - NULL, 0, 0, "mediatek,mt6360_led"), - MFD_CELL_OF("mt6360_pmic", mt6360_pmic_resources, - NULL, 0, 0, "mediatek,mt6360_pmic"), - MFD_CELL_OF("mt6360_ldo", mt6360_ldo_resources, - NULL, 0, 0, "mediatek,mt6360_ldo"), - MFD_CELL_OF("mt6360_tcpc", NULL, - NULL, 0, 0, "mediatek,mt6360_tcpc"), + MFD_CELL_OF("mt6360-adc", mt6360_adc_resources, + NULL, 0, 0, "mediatek,mt6360-adc"), + MFD_CELL_OF("mt6360-chg", mt6360_chg_resources, + NULL, 0, 0, "mediatek,mt6360-chg"), + MFD_CELL_OF("mt6360-led", mt6360_led_resources, + NULL, 0, 0, "mediatek,mt6360-led"), + MFD_CELL_RES("mt6360-regulator", mt6360_regulator_resources), + MFD_CELL_OF("mt6360-tcpc", NULL, + NULL, 0, 0, "mediatek,mt6360-tcpc"), }; +static int mt6360_check_vendor_info(struct mt6360_ddata *ddata) +{ + u32 info; + int ret; + + ret = regmap_read(ddata->regmap, MT6360_PMU_DEV_INFO, &info); + if (ret < 0) + return ret; + + if ((info & CHIP_VEN_MASK) != CHIP_VEN_MT6360) { + dev_err(ddata->dev, "Device not supported\n"); + return -ENODEV; + } + + ddata->chip_rev = info & CHIP_REV_MASK; + + return 0; +} + static const unsigned short mt6360_slave_addr[MT6360_SLAVE_MAX] = { - MT6360_PMU_SLAVEID, + MT6360_TCPC_SLAVEID, MT6360_PMIC_SLAVEID, MT6360_LDO_SLAVEID, - MT6360_TCPC_SLAVEID, + MT6360_PMU_SLAVEID, }; -static int mt6360_pmu_probe(struct i2c_client *client) +static int mt6360_xlate_pmicldo_addr(u8 *addr, int rw_size) { - struct mt6360_pmu_data *mpd; - unsigned int reg_data; - int i, ret; + /* Address is already in encoded [5:0] */ + *addr &= MT6360_ADDRESS_MASK; + + switch (rw_size) { + case 1: + *addr |= MT6360_DATA_SIZE_1_BYTE; + break; + case 2: + *addr |= MT6360_DATA_SIZE_2_BYTES; + break; + case 3: + *addr |= MT6360_DATA_SIZE_3_BYTES; + break; + case 4: + *addr |= MT6360_DATA_SIZE_4_BYTES; + break; + default: + return -EINVAL; + } - mpd = devm_kzalloc(&client->dev, sizeof(*mpd), GFP_KERNEL); - if (!mpd) + return 0; +} + +static int mt6360_regmap_read(void *context, const void *reg, size_t reg_size, + void *val, size_t val_size) +{ + struct mt6360_ddata *ddata = context; + u8 bank = *(u8 *)reg; + u8 reg_addr = *(u8 *)(reg + 1); + struct i2c_client *i2c = ddata->i2c[bank]; + bool crc_needed = false; + u8 *buf; + int buf_len = MT6360_ALLOC_READ_SIZE(val_size); + int read_size = val_size; + u8 crc; + int ret; + + if (bank == MT6360_SLAVE_PMIC || bank == MT6360_SLAVE_LDO) { + crc_needed = true; + ret = mt6360_xlate_pmicldo_addr(®_addr, val_size); + if (ret < 0) + return ret; + read_size += MT6360_CRC_CRC8_SIZE; + } + + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) return -ENOMEM; - mpd->dev = &client->dev; - i2c_set_clientdata(client, mpd); + buf[0] = I2C_ADDR_XLATE_8BIT(i2c->addr, I2C_SMBUS_READ); + buf[1] = reg_addr; - mpd->regmap = devm_regmap_init_i2c(client, &mt6360_pmu_regmap_config); - if (IS_ERR(mpd->regmap)) { - dev_err(&client->dev, "Failed to register regmap\n"); - return PTR_ERR(mpd->regmap); + ret = i2c_smbus_read_i2c_block_data(i2c, reg_addr, read_size, + buf + MT6360_CRC_PREDATA_OFFSET); + if (ret < 0) + goto out; + else if (ret != read_size) { + ret = -EIO; + goto out; } - ret = regmap_read(mpd->regmap, MT6360_PMU_DEV_INFO, ®_data); - if (ret) { - dev_err(&client->dev, "Device not found\n"); - return ret; + if (crc_needed) { + crc = crc8(ddata->crc8_tbl, buf, val_size + MT6360_CRC_PREDATA_OFFSET, 0); + if (crc != buf[val_size + MT6360_CRC_PREDATA_OFFSET]) { + ret = -EIO; + goto out; + } } - mpd->chip_rev = reg_data & CHIP_REV_MASK; - if (mpd->chip_rev != CHIP_VEN_MT6360) { - dev_err(&client->dev, "Device not supported\n"); - return -ENODEV; + memcpy(val, buf + MT6360_CRC_PREDATA_OFFSET, val_size); +out: + kfree(buf); + return (ret < 0) ? ret : 0; +} + +static int mt6360_regmap_write(void *context, const void *val, size_t val_size) +{ + struct mt6360_ddata *ddata = context; + u8 bank = *(u8 *)val; + u8 reg_addr = *(u8 *)(val + 1); + struct i2c_client *i2c = ddata->i2c[bank]; + bool crc_needed = false; + u8 *buf; + int buf_len = MT6360_ALLOC_WRITE_SIZE(val_size); + int write_size = val_size - MT6360_REGMAP_REG_BYTE_SIZE; + int ret; + + if (bank == MT6360_SLAVE_PMIC || bank == MT6360_SLAVE_LDO) { + crc_needed = true; + ret = mt6360_xlate_pmicldo_addr(®_addr, val_size - MT6360_REGMAP_REG_BYTE_SIZE); + if (ret < 0) + return ret; } - mt6360_pmu_irq_chip.irq_drv_data = mpd; - ret = devm_regmap_add_irq_chip(&client->dev, mpd->regmap, client->irq, - IRQF_TRIGGER_FALLING, 0, - &mt6360_pmu_irq_chip, &mpd->irq_data); - if (ret) { - dev_err(&client->dev, "Failed to add Regmap IRQ Chip\n"); - return ret; + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + buf[0] = I2C_ADDR_XLATE_8BIT(i2c->addr, I2C_SMBUS_WRITE); + buf[1] = reg_addr; + memcpy(buf + MT6360_CRC_PREDATA_OFFSET, val + MT6360_REGMAP_REG_BYTE_SIZE, write_size); + + if (crc_needed) { + buf[val_size] = crc8(ddata->crc8_tbl, buf, val_size, 0); + write_size += (MT6360_CRC_CRC8_SIZE + MT6360_CRC_DUMMY_BYTE_SIZE); } - mpd->i2c[0] = client; - for (i = 1; i < MT6360_SLAVE_MAX; i++) { - mpd->i2c[i] = devm_i2c_new_dummy_device(&client->dev, - client->adapter, - mt6360_slave_addr[i]); - if (IS_ERR(mpd->i2c[i])) { + ret = i2c_smbus_write_i2c_block_data(i2c, reg_addr, write_size, + buf + MT6360_CRC_PREDATA_OFFSET); + + kfree(buf); + return ret; +} + +static const struct regmap_bus mt6360_regmap_bus = { + .read = mt6360_regmap_read, + .write = mt6360_regmap_write, + + /* Due to PMIC and LDO CRC access size limit */ + .max_raw_read = 4, + .max_raw_write = 4, +}; + +static bool mt6360_is_readwrite_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MT6360_REG_TCPCSTART ... MT6360_REG_TCPCEND: + fallthrough; + case MT6360_REG_PMICSTART ... MT6360_REG_PMICEND: + fallthrough; + case MT6360_REG_LDOSTART ... MT6360_REG_LDOEND: + fallthrough; + case MT6360_REG_PMUSTART ... MT6360_REG_PMUEND: + return true; + } + + return false; +} + +static const struct regmap_config mt6360_regmap_config = { + .reg_bits = 16, + .val_bits = 8, + .reg_format_endian = REGMAP_ENDIAN_BIG, + .max_register = MT6360_REG_PMUEND, + .writeable_reg = mt6360_is_readwrite_reg, + .readable_reg = mt6360_is_readwrite_reg, +}; + +static int mt6360_probe(struct i2c_client *client) +{ + struct mt6360_ddata *ddata; + int i, ret; + + ddata = devm_kzalloc(&client->dev, sizeof(*ddata), GFP_KERNEL); + if (!ddata) + return -ENOMEM; + + ddata->dev = &client->dev; + i2c_set_clientdata(client, ddata); + + for (i = 0; i < MT6360_SLAVE_MAX - 1; i++) { + ddata->i2c[i] = devm_i2c_new_dummy_device(&client->dev, + client->adapter, + mt6360_slave_addr[i]); + if (IS_ERR(ddata->i2c[i])) { dev_err(&client->dev, "Failed to get new dummy I2C device for address 0x%x", mt6360_slave_addr[i]); - return PTR_ERR(mpd->i2c[i]); + return PTR_ERR(ddata->i2c[i]); } - i2c_set_clientdata(mpd->i2c[i], mpd); + } + ddata->i2c[MT6360_SLAVE_MAX - 1] = client; + + crc8_populate_msb(ddata->crc8_tbl, MT6360_CRC8_POLYNOMIAL); + ddata->regmap = devm_regmap_init(ddata->dev, &mt6360_regmap_bus, ddata, + &mt6360_regmap_config); + if (IS_ERR(ddata->regmap)) { + dev_err(&client->dev, "Failed to register regmap\n"); + return PTR_ERR(ddata->regmap); + } + + ret = mt6360_check_vendor_info(ddata); + if (ret) + return ret; + + ret = devm_regmap_add_irq_chip(&client->dev, ddata->regmap, client->irq, + 0, 0, &mt6360_irq_chip, + &ddata->irq_data); + if (ret) { + dev_err(&client->dev, "Failed to add Regmap IRQ Chip\n"); + return ret; } ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_AUTO, mt6360_devs, ARRAY_SIZE(mt6360_devs), NULL, - 0, regmap_irq_get_domain(mpd->irq_data)); + 0, regmap_irq_get_domain(ddata->irq_data)); if (ret) { dev_err(&client->dev, "Failed to register subordinate devices\n"); @@ -379,7 +578,7 @@ static int mt6360_pmu_probe(struct i2c_client *client) return 0; } -static int __maybe_unused mt6360_pmu_suspend(struct device *dev) +static int __maybe_unused mt6360_suspend(struct device *dev) { struct i2c_client *i2c = to_i2c_client(dev); @@ -389,7 +588,7 @@ static int __maybe_unused mt6360_pmu_suspend(struct device *dev) return 0; } -static int __maybe_unused mt6360_pmu_resume(struct device *dev) +static int __maybe_unused mt6360_resume(struct device *dev) { struct i2c_client *i2c = to_i2c_client(dev); @@ -400,25 +599,24 @@ static int __maybe_unused mt6360_pmu_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(mt6360_pmu_pm_ops, - mt6360_pmu_suspend, mt6360_pmu_resume); +static SIMPLE_DEV_PM_OPS(mt6360_pm_ops, mt6360_suspend, mt6360_resume); -static const struct of_device_id __maybe_unused mt6360_pmu_of_id[] = { - { .compatible = "mediatek,mt6360_pmu", }, +static const struct of_device_id __maybe_unused mt6360_of_id[] = { + { .compatible = "mediatek,mt6360", }, {}, }; -MODULE_DEVICE_TABLE(of, mt6360_pmu_of_id); +MODULE_DEVICE_TABLE(of, mt6360_of_id); -static struct i2c_driver mt6360_pmu_driver = { +static struct i2c_driver mt6360_driver = { .driver = { - .name = "mt6360_pmu", - .pm = &mt6360_pmu_pm_ops, - .of_match_table = of_match_ptr(mt6360_pmu_of_id), + .name = "mt6360", + .pm = &mt6360_pm_ops, + .of_match_table = of_match_ptr(mt6360_of_id), }, - .probe_new = mt6360_pmu_probe, + .probe_new = mt6360_probe, }; -module_i2c_driver(mt6360_pmu_driver); +module_i2c_driver(mt6360_driver); MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>"); -MODULE_DESCRIPTION("MT6360 PMU I2C Driver"); +MODULE_DESCRIPTION("MT6360 I2C Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c index 9a615f75fbde..bddb40054b9e 100644 --- a/drivers/mfd/mt6397-core.c +++ b/drivers/mfd/mt6397-core.c @@ -47,14 +47,21 @@ static const struct resource mt6397_rtc_resources[] = { DEFINE_RES_IRQ(MT6397_IRQ_RTC), }; +static const struct resource mt6358_keys_resources[] = { + DEFINE_RES_IRQ_NAMED(MT6358_IRQ_PWRKEY, "powerkey"), + DEFINE_RES_IRQ_NAMED(MT6358_IRQ_HOMEKEY, "homekey"), + DEFINE_RES_IRQ_NAMED(MT6358_IRQ_PWRKEY_R, "powerkey_r"), + DEFINE_RES_IRQ_NAMED(MT6358_IRQ_HOMEKEY_R, "homekey_r"), +}; + static const struct resource mt6323_keys_resources[] = { - DEFINE_RES_IRQ(MT6323_IRQ_STATUS_PWRKEY), - DEFINE_RES_IRQ(MT6323_IRQ_STATUS_FCHRKEY), + DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_PWRKEY, "powerkey"), + DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_FCHRKEY, "homekey"), }; static const struct resource mt6397_keys_resources[] = { - DEFINE_RES_IRQ(MT6397_IRQ_PWRKEY), - DEFINE_RES_IRQ(MT6397_IRQ_HOMEKEY), + DEFINE_RES_IRQ_NAMED(MT6397_IRQ_PWRKEY, "powerkey"), + DEFINE_RES_IRQ_NAMED(MT6397_IRQ_HOMEKEY, "homekey"), }; static const struct resource mt6323_pwrc_resources[] = { @@ -98,6 +105,11 @@ static const struct mfd_cell mt6358_devs[] = { }, { .name = "mt6358-sound", .of_compatible = "mediatek,mt6358-sound" + }, { + .name = "mt6358-keys", + .num_resources = ARRAY_SIZE(mt6358_keys_resources), + .resources = mt6358_keys_resources, + .of_compatible = "mediatek,mt6358-keys" }, }; diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 2a3a240b4619..787d2ae86375 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/** +/* * omap-usb-host.c - The USBHS core driver for OMAP EHCI & OHCI * * Copyright (C) 2011-2013 Texas Instruments Incorporated - https://www.ti.com diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c index 16fad79c73f1..080d7970a377 100644 --- a/drivers/mfd/omap-usb-tll.c +++ b/drivers/mfd/omap-usb-tll.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/** +/* * omap-usb-tll.c - The USB TLL driver for OMAP EHCI & OHCI * * Copyright (C) 2012-2013 Texas Instruments Incorporated - https://www.ti.com diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 148bcd6120f4..e9c565cf0f54 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c @@ -77,8 +77,8 @@ int pcf50633_reg_clear_bits(struct pcf50633 *pcf, u8 reg, u8 val) EXPORT_SYMBOL_GPL(pcf50633_reg_clear_bits); /* sysfs attributes */ -static ssize_t show_dump_regs(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t dump_regs_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct pcf50633 *pcf = dev_get_drvdata(dev); u8 dump[16]; @@ -106,10 +106,10 @@ static ssize_t show_dump_regs(struct device *dev, struct device_attribute *attr, return buf1 - buf; } -static DEVICE_ATTR(dump_regs, 0400, show_dump_regs, NULL); +static DEVICE_ATTR_ADMIN_RO(dump_regs); -static ssize_t show_resume_reason(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t resume_reason_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct pcf50633 *pcf = dev_get_drvdata(dev); int n; @@ -123,7 +123,7 @@ static ssize_t show_resume_reason(struct device *dev, return n; } -static DEVICE_ATTR(resume_reason, 0400, show_resume_reason, NULL); +static DEVICE_ATTR_ADMIN_RO(resume_reason); static struct attribute *pcf_sysfs_entries[] = { &dev_attr_dump_regs.attr, diff --git a/drivers/mfd/qcom-pm8008.c b/drivers/mfd/qcom-pm8008.c new file mode 100644 index 000000000000..c472d7f8103c --- /dev/null +++ b/drivers/mfd/qcom-pm8008.c @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#include <linux/bitops.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/of_platform.h> +#include <linux/pinctrl/consumer.h> +#include <linux/regmap.h> +#include <linux/slab.h> + +#include <dt-bindings/mfd/qcom-pm8008.h> + +#define I2C_INTR_STATUS_BASE 0x0550 +#define INT_RT_STS_OFFSET 0x10 +#define INT_SET_TYPE_OFFSET 0x11 +#define INT_POL_HIGH_OFFSET 0x12 +#define INT_POL_LOW_OFFSET 0x13 +#define INT_LATCHED_CLR_OFFSET 0x14 +#define INT_EN_SET_OFFSET 0x15 +#define INT_EN_CLR_OFFSET 0x16 +#define INT_LATCHED_STS_OFFSET 0x18 + +enum { + PM8008_MISC, + PM8008_TEMP_ALARM, + PM8008_GPIO1, + PM8008_GPIO2, + PM8008_NUM_PERIPHS, +}; + +#define PM8008_PERIPH_0_BASE 0x900 +#define PM8008_PERIPH_1_BASE 0x2400 +#define PM8008_PERIPH_2_BASE 0xC000 +#define PM8008_PERIPH_3_BASE 0xC100 + +#define PM8008_TEMP_ALARM_ADDR PM8008_PERIPH_1_BASE +#define PM8008_GPIO1_ADDR PM8008_PERIPH_2_BASE +#define PM8008_GPIO2_ADDR PM8008_PERIPH_3_BASE + +#define PM8008_STATUS_BASE (PM8008_PERIPH_0_BASE | INT_LATCHED_STS_OFFSET) +#define PM8008_MASK_BASE (PM8008_PERIPH_0_BASE | INT_EN_SET_OFFSET) +#define PM8008_UNMASK_BASE (PM8008_PERIPH_0_BASE | INT_EN_CLR_OFFSET) +#define PM8008_TYPE_BASE (PM8008_PERIPH_0_BASE | INT_SET_TYPE_OFFSET) +#define PM8008_ACK_BASE (PM8008_PERIPH_0_BASE | INT_LATCHED_CLR_OFFSET) +#define PM8008_POLARITY_HI_BASE (PM8008_PERIPH_0_BASE | INT_POL_HIGH_OFFSET) +#define PM8008_POLARITY_LO_BASE (PM8008_PERIPH_0_BASE | INT_POL_LOW_OFFSET) + +#define PM8008_PERIPH_OFFSET(paddr) (paddr - PM8008_PERIPH_0_BASE) + +struct pm8008_data { + struct device *dev; + struct regmap *regmap; + int irq; + struct regmap_irq_chip_data *irq_data; +}; + +static unsigned int p0_offs[] = {PM8008_PERIPH_OFFSET(PM8008_PERIPH_0_BASE)}; +static unsigned int p1_offs[] = {PM8008_PERIPH_OFFSET(PM8008_PERIPH_1_BASE)}; +static unsigned int p2_offs[] = {PM8008_PERIPH_OFFSET(PM8008_PERIPH_2_BASE)}; +static unsigned int p3_offs[] = {PM8008_PERIPH_OFFSET(PM8008_PERIPH_3_BASE)}; + +static struct regmap_irq_sub_irq_map pm8008_sub_reg_offsets[] = { + REGMAP_IRQ_MAIN_REG_OFFSET(p0_offs), + REGMAP_IRQ_MAIN_REG_OFFSET(p1_offs), + REGMAP_IRQ_MAIN_REG_OFFSET(p2_offs), + REGMAP_IRQ_MAIN_REG_OFFSET(p3_offs), +}; + +static unsigned int pm8008_virt_regs[] = { + PM8008_POLARITY_HI_BASE, + PM8008_POLARITY_LO_BASE, +}; + +enum { + POLARITY_HI_INDEX, + POLARITY_LO_INDEX, + PM8008_NUM_VIRT_REGS, +}; + +static struct regmap_irq pm8008_irqs[] = { + REGMAP_IRQ_REG(PM8008_IRQ_MISC_UVLO, PM8008_MISC, BIT(0)), + REGMAP_IRQ_REG(PM8008_IRQ_MISC_OVLO, PM8008_MISC, BIT(1)), + REGMAP_IRQ_REG(PM8008_IRQ_MISC_OTST2, PM8008_MISC, BIT(2)), + REGMAP_IRQ_REG(PM8008_IRQ_MISC_OTST3, PM8008_MISC, BIT(3)), + REGMAP_IRQ_REG(PM8008_IRQ_MISC_LDO_OCP, PM8008_MISC, BIT(4)), + REGMAP_IRQ_REG(PM8008_IRQ_TEMP_ALARM, PM8008_TEMP_ALARM, BIT(0)), + REGMAP_IRQ_REG(PM8008_IRQ_GPIO1, PM8008_GPIO1, BIT(0)), + REGMAP_IRQ_REG(PM8008_IRQ_GPIO2, PM8008_GPIO2, BIT(0)), +}; + +static int pm8008_set_type_virt(unsigned int **virt_buf, + unsigned int type, unsigned long hwirq, + int reg) +{ + switch (type) { + case IRQ_TYPE_EDGE_FALLING: + case IRQ_TYPE_LEVEL_LOW: + virt_buf[POLARITY_HI_INDEX][reg] &= ~pm8008_irqs[hwirq].mask; + virt_buf[POLARITY_LO_INDEX][reg] |= pm8008_irqs[hwirq].mask; + break; + + case IRQ_TYPE_EDGE_RISING: + case IRQ_TYPE_LEVEL_HIGH: + virt_buf[POLARITY_HI_INDEX][reg] |= pm8008_irqs[hwirq].mask; + virt_buf[POLARITY_LO_INDEX][reg] &= ~pm8008_irqs[hwirq].mask; + break; + + case IRQ_TYPE_EDGE_BOTH: + virt_buf[POLARITY_HI_INDEX][reg] |= pm8008_irqs[hwirq].mask; + virt_buf[POLARITY_LO_INDEX][reg] |= pm8008_irqs[hwirq].mask; + break; + + default: + return -EINVAL; + } + + return 0; +} + +static struct regmap_irq_chip pm8008_irq_chip = { + .name = "pm8008_irq", + .main_status = I2C_INTR_STATUS_BASE, + .num_main_regs = 1, + .num_virt_regs = PM8008_NUM_VIRT_REGS, + .irqs = pm8008_irqs, + .num_irqs = ARRAY_SIZE(pm8008_irqs), + .num_regs = PM8008_NUM_PERIPHS, + .not_fixed_stride = true, + .sub_reg_offsets = pm8008_sub_reg_offsets, + .set_type_virt = pm8008_set_type_virt, + .status_base = PM8008_STATUS_BASE, + .mask_base = PM8008_MASK_BASE, + .unmask_base = PM8008_UNMASK_BASE, + .type_base = PM8008_TYPE_BASE, + .ack_base = PM8008_ACK_BASE, + .virt_reg_base = pm8008_virt_regs, + .num_type_reg = PM8008_NUM_PERIPHS, +}; + +static struct regmap_config qcom_mfd_regmap_cfg = { + .reg_bits = 16, + .val_bits = 8, + .max_register = 0xFFFF, +}; + +static int pm8008_init(struct pm8008_data *chip) +{ + int rc; + + /* + * Set TEMP_ALARM peripheral's TYPE so that the regmap-irq framework + * reads this as the default value instead of zero, the HW default. + * This is required to enable the writing of TYPE registers in + * regmap_irq_sync_unlock(). + */ + rc = regmap_write(chip->regmap, + (PM8008_TEMP_ALARM_ADDR | INT_SET_TYPE_OFFSET), + BIT(0)); + if (rc) + return rc; + + /* Do the same for GPIO1 and GPIO2 peripherals */ + rc = regmap_write(chip->regmap, + (PM8008_GPIO1_ADDR | INT_SET_TYPE_OFFSET), BIT(0)); + if (rc) + return rc; + + rc = regmap_write(chip->regmap, + (PM8008_GPIO2_ADDR | INT_SET_TYPE_OFFSET), BIT(0)); + + return rc; +} + +static int pm8008_probe_irq_peripherals(struct pm8008_data *chip, + int client_irq) +{ + int rc, i; + struct regmap_irq_type *type; + struct regmap_irq_chip_data *irq_data; + + rc = pm8008_init(chip); + if (rc) { + dev_err(chip->dev, "Init failed: %d\n", rc); + return rc; + } + + for (i = 0; i < ARRAY_SIZE(pm8008_irqs); i++) { + type = &pm8008_irqs[i].type; + + type->type_reg_offset = pm8008_irqs[i].reg_offset; + type->type_rising_val = pm8008_irqs[i].mask; + type->type_falling_val = pm8008_irqs[i].mask; + type->type_level_high_val = 0; + type->type_level_low_val = 0; + + if (type->type_reg_offset == PM8008_MISC) + type->types_supported = IRQ_TYPE_EDGE_RISING; + else + type->types_supported = (IRQ_TYPE_EDGE_BOTH | + IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW); + } + + rc = devm_regmap_add_irq_chip(chip->dev, chip->regmap, client_irq, + IRQF_SHARED, 0, &pm8008_irq_chip, &irq_data); + if (rc) { + dev_err(chip->dev, "Failed to add IRQ chip: %d\n", rc); + return rc; + } + + return 0; +} + +static int pm8008_probe(struct i2c_client *client) +{ + int rc; + struct pm8008_data *chip; + + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->dev = &client->dev; + chip->regmap = devm_regmap_init_i2c(client, &qcom_mfd_regmap_cfg); + if (!chip->regmap) + return -ENODEV; + + i2c_set_clientdata(client, chip); + + if (of_property_read_bool(chip->dev->of_node, "interrupt-controller")) { + rc = pm8008_probe_irq_peripherals(chip, client->irq); + if (rc) + dev_err(chip->dev, "Failed to probe irq periphs: %d\n", rc); + } + + return devm_of_platform_populate(chip->dev); +} + +static const struct of_device_id pm8008_match[] = { + { .compatible = "qcom,pm8008", }, + { }, +}; + +static struct i2c_driver pm8008_mfd_driver = { + .driver = { + .name = "pm8008", + .of_match_table = pm8008_match, + }, + .probe_new = pm8008_probe, +}; +module_i2c_driver(pm8008_mfd_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("i2c:qcom-pm8008"); diff --git a/drivers/mfd/rn5t618.c b/drivers/mfd/rn5t618.c index 6ed04e6dbc78..384acb459427 100644 --- a/drivers/mfd/rn5t618.c +++ b/drivers/mfd/rn5t618.c @@ -107,7 +107,7 @@ static int rn5t618_irq_init(struct rn5t618 *rn5t618) ret = devm_regmap_add_irq_chip(rn5t618->dev, rn5t618->regmap, rn5t618->irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, 0, irq_chip, &rn5t618->irq_data); if (ret) dev_err(rn5t618->dev, "Failed to register IRQ chip\n"); diff --git a/drivers/mfd/rt4831.c b/drivers/mfd/rt4831.c new file mode 100644 index 000000000000..b169781ac675 --- /dev/null +++ b/drivers/mfd/rt4831.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Richtek Technology Corp. + * + * Author: ChiYuan Huang <cy_huang@richtek.com> + */ + +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/kernel.h> +#include <linux/mfd/core.h> +#include <linux/module.h> +#include <linux/regmap.h> + +#define RT4831_REG_REVISION 0x01 +#define RT4831_REG_ENABLE 0x08 +#define RT4831_REG_I2CPROT 0x15 + +#define RICHTEK_VENDOR_ID 0x03 +#define RT4831_VID_MASK GENMASK(1, 0) +#define RT4831_RESET_MASK BIT(7) +#define RT4831_I2CSAFETMR_MASK BIT(0) + +static const struct mfd_cell rt4831_subdevs[] = { + MFD_CELL_OF("rt4831-backlight", NULL, NULL, 0, 0, "richtek,rt4831-backlight"), + MFD_CELL_NAME("rt4831-regulator") +}; + +static bool rt4831_is_accessible_reg(struct device *dev, unsigned int reg) +{ + if (reg >= RT4831_REG_REVISION && reg <= RT4831_REG_I2CPROT) + return true; + return false; +} + +static const struct regmap_config rt4831_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RT4831_REG_I2CPROT, + + .readable_reg = rt4831_is_accessible_reg, + .writeable_reg = rt4831_is_accessible_reg, +}; + +static int rt4831_probe(struct i2c_client *client) +{ + struct gpio_desc *enable_gpio; + struct regmap *regmap; + unsigned int chip_id; + int ret; + + enable_gpio = devm_gpiod_get_optional(&client->dev, "enable", GPIOD_OUT_HIGH); + if (IS_ERR(enable_gpio)) { + dev_err(&client->dev, "Failed to get 'enable' GPIO\n"); + return PTR_ERR(enable_gpio); + } + + regmap = devm_regmap_init_i2c(client, &rt4831_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "Failed to initialize regmap\n"); + return PTR_ERR(regmap); + } + + ret = regmap_read(regmap, RT4831_REG_REVISION, &chip_id); + if (ret) { + dev_err(&client->dev, "Failed to get H/W revision\n"); + return ret; + } + + if ((chip_id & RT4831_VID_MASK) != RICHTEK_VENDOR_ID) { + dev_err(&client->dev, "Chip vendor ID 0x%02x not matched\n", chip_id); + return -ENODEV; + } + + /* + * Used to prevent the abnormal shutdown. + * If SCL/SDA both keep low for one second to reset HW. + */ + ret = regmap_update_bits(regmap, RT4831_REG_I2CPROT, RT4831_I2CSAFETMR_MASK, + RT4831_I2CSAFETMR_MASK); + if (ret) { + dev_err(&client->dev, "Failed to enable I2C safety timer\n"); + return ret; + } + + return devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_AUTO, rt4831_subdevs, + ARRAY_SIZE(rt4831_subdevs), NULL, 0, NULL); +} + +static int rt4831_remove(struct i2c_client *client) +{ + struct regmap *regmap = dev_get_regmap(&client->dev, NULL); + + /* Disable WLED and DSV outputs */ + return regmap_update_bits(regmap, RT4831_REG_ENABLE, RT4831_RESET_MASK, RT4831_RESET_MASK); +} + +static const struct of_device_id __maybe_unused rt4831_of_match[] = { + { .compatible = "richtek,rt4831", }, + {} +}; +MODULE_DEVICE_TABLE(of, rt4831_of_match); + +static struct i2c_driver rt4831_driver = { + .driver = { + .name = "rt4831", + .of_match_table = rt4831_of_match, + }, + .probe_new = rt4831_probe, + .remove = rt4831_remove, +}; +module_i2c_driver(rt4831_driver); + +MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 8d55992da19e..1fb29c45f5cf 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -10,6 +10,7 @@ #include <linux/slab.h> #include <linux/i2c.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/interrupt.h> #include <linux/pm_runtime.h> @@ -93,7 +94,6 @@ static const struct mfd_cell s2mpu02_devs[] = { { .name = "s2mpu02-regulator", }, }; -#ifdef CONFIG_OF static const struct of_device_id sec_dt_match[] = { { .compatible = "samsung,s5m8767-pmic", @@ -121,7 +121,6 @@ static const struct of_device_id sec_dt_match[] = { }, }; MODULE_DEVICE_TABLE(of, sec_dt_match); -#endif static bool s2mpa01_volatile(struct device *dev, unsigned int reg) { @@ -281,7 +280,6 @@ static void sec_pmic_configure(struct sec_pmic_dev *sec_pmic) } } -#ifdef CONFIG_OF /* * Only the common platform data elements for s5m8767 are parsed here from the * device tree. Other sub-modules of s5m8767 such as pmic, rtc , charger and @@ -300,48 +298,20 @@ sec_pmic_i2c_parse_dt_pdata(struct device *dev) if (!pd) return ERR_PTR(-ENOMEM); - /* - * ToDo: the 'wakeup' member in the platform data is more of a linux - * specfic information. Hence, there is no binding for that yet and - * not parsed here. - */ - pd->manual_poweroff = of_property_read_bool(dev->of_node, "samsung,s2mps11-acokb-ground"); pd->disable_wrstbi = of_property_read_bool(dev->of_node, "samsung,s2mps11-wrstbi-ground"); return pd; } -#else -static struct sec_platform_data * -sec_pmic_i2c_parse_dt_pdata(struct device *dev) -{ - return NULL; -} -#endif - -static inline unsigned long sec_i2c_get_driver_data(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ -#ifdef CONFIG_OF - if (i2c->dev.of_node) { - const struct of_device_id *match; - - match = of_match_node(sec_dt_match, i2c->dev.of_node); - return (unsigned long)match->data; - } -#endif - return id->driver_data; -} static int sec_pmic_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { - struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev); const struct regmap_config *regmap; + struct sec_platform_data *pdata; const struct mfd_cell *sec_devs; struct sec_pmic_dev *sec_pmic; - unsigned long device_type; int ret, num_sec_devs; sec_pmic = devm_kzalloc(&i2c->dev, sizeof(struct sec_pmic_dev), @@ -353,23 +323,16 @@ static int sec_pmic_probe(struct i2c_client *i2c, sec_pmic->dev = &i2c->dev; sec_pmic->i2c = i2c; sec_pmic->irq = i2c->irq; - device_type = sec_i2c_get_driver_data(i2c, id); - - if (sec_pmic->dev->of_node) { - pdata = sec_pmic_i2c_parse_dt_pdata(sec_pmic->dev); - if (IS_ERR(pdata)) { - ret = PTR_ERR(pdata); - return ret; - } - pdata->device_type = device_type; - } - if (pdata) { - sec_pmic->device_type = pdata->device_type; - sec_pmic->irq_base = pdata->irq_base; - sec_pmic->wakeup = pdata->wakeup; - sec_pmic->pdata = pdata; + + pdata = sec_pmic_i2c_parse_dt_pdata(sec_pmic->dev); + if (IS_ERR(pdata)) { + ret = PTR_ERR(pdata); + return ret; } + sec_pmic->device_type = (unsigned long)of_device_get_match_data(sec_pmic->dev); + sec_pmic->pdata = pdata; + switch (sec_pmic->device_type) { case S2MPA01: regmap = &s2mpa01_regmap_config; @@ -408,9 +371,6 @@ static int sec_pmic_probe(struct i2c_client *i2c, return ret; } - if (pdata && pdata->cfg_pmic_irq) - pdata->cfg_pmic_irq(); - sec_irq_init(sec_pmic); pm_runtime_set_active(sec_pmic->dev); @@ -462,7 +422,6 @@ static int sec_pmic_probe(struct i2c_client *i2c, if (ret) return ret; - device_init_wakeup(sec_pmic->dev, sec_pmic->wakeup); sec_pmic_configure(sec_pmic); sec_pmic_dump_rev(sec_pmic); @@ -533,21 +492,14 @@ static int sec_pmic_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume); -static const struct i2c_device_id sec_pmic_id[] = { - { "sec_pmic", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, sec_pmic_id); - static struct i2c_driver sec_pmic_driver = { .driver = { .name = "sec_pmic", .pm = &sec_pmic_pm_ops, - .of_match_table = of_match_ptr(sec_dt_match), + .of_match_table = sec_dt_match, }, .probe = sec_pmic_probe, .shutdown = sec_pmic_shutdown, - .id_table = sec_pmic_id, }; module_i2c_driver(sec_pmic_driver); diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index a98c5d165039..e473c2fb42d5 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -444,7 +444,6 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic) if (!sec_pmic->irq) { dev_warn(sec_pmic->dev, "No interrupt specified, no interrupts\n"); - sec_pmic->irq_base = 0; return 0; } @@ -482,8 +481,7 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic) ret = devm_regmap_add_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic, sec_pmic->irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - sec_pmic->irq_base, sec_irq_chip, - &sec_pmic->irq_data); + 0, sec_irq_chip, &sec_pmic->irq_data); if (ret != 0) { dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret); return ret; diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c index d15b3e783369..f32f1fb93e37 100644 --- a/drivers/mfd/si476x-cmd.c +++ b/drivers/mfd/si476x-cmd.c @@ -390,7 +390,7 @@ static int si476x_cmd_tune_seek_freq(struct si476x_core *core, } /** - * si476x_cmd_func_info() - send 'FUNC_INFO' command to the device + * si476x_core_cmd_func_info() - send 'FUNC_INFO' command to the device * @core: device to send the command to * @info: struct si476x_func_info to fill all the information * returned by the command @@ -424,7 +424,7 @@ int si476x_core_cmd_func_info(struct si476x_core *core, EXPORT_SYMBOL_GPL(si476x_core_cmd_func_info); /** - * si476x_cmd_set_property() - send 'SET_PROPERTY' command to the device + * si476x_core_cmd_set_property() - send 'SET_PROPERTY' command to the device * @core: device to send the command to * @property: property address * @value: property value @@ -452,7 +452,7 @@ int si476x_core_cmd_set_property(struct si476x_core *core, EXPORT_SYMBOL_GPL(si476x_core_cmd_set_property); /** - * si476x_cmd_get_property() - send 'GET_PROPERTY' command to the device + * si476x_core_cmd_get_property() - send 'GET_PROPERTY' command to the device * @core: device to send the command to * @property: property address * @@ -481,7 +481,7 @@ int si476x_core_cmd_get_property(struct si476x_core *core, u16 property) EXPORT_SYMBOL_GPL(si476x_core_cmd_get_property); /** - * si476x_cmd_dig_audio_pin_cfg() - send 'DIG_AUDIO_PIN_CFG' command to + * si476x_core_cmd_dig_audio_pin_cfg() - send 'DIG_AUDIO_PIN_CFG' command to * the device * @core: device to send the command to * @dclk: DCLK pin function configuration: @@ -539,7 +539,7 @@ int si476x_core_cmd_dig_audio_pin_cfg(struct si476x_core *core, EXPORT_SYMBOL_GPL(si476x_core_cmd_dig_audio_pin_cfg); /** - * si476x_cmd_zif_pin_cfg - send 'ZIF_PIN_CFG_COMMAND' + * si476x_core_cmd_zif_pin_cfg - send 'ZIF_PIN_CFG_COMMAND' * @core: - device to send the command to * @iqclk: - IQCL pin function configuration: * SI476X_IQCLK_NOOP - do not modify the behaviour @@ -588,7 +588,7 @@ int si476x_core_cmd_zif_pin_cfg(struct si476x_core *core, EXPORT_SYMBOL_GPL(si476x_core_cmd_zif_pin_cfg); /** - * si476x_cmd_ic_link_gpo_ctl_pin_cfg - send + * si476x_core_cmd_ic_link_gpo_ctl_pin_cfg - send * 'IC_LINK_GPIO_CTL_PIN_CFG' comand to the device * @core: - device to send the command to * @icin: - ICIN pin function configuration: @@ -645,7 +645,7 @@ int si476x_core_cmd_ic_link_gpo_ctl_pin_cfg(struct si476x_core *core, EXPORT_SYMBOL_GPL(si476x_core_cmd_ic_link_gpo_ctl_pin_cfg); /** - * si476x_cmd_ana_audio_pin_cfg - send 'ANA_AUDIO_PIN_CFG' to the + * si476x_core_cmd_ana_audio_pin_cfg - send 'ANA_AUDIO_PIN_CFG' to the * device * @core: - device to send the command to * @lrout: - LROUT pin function configuration: @@ -674,7 +674,7 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_ana_audio_pin_cfg); /** - * si476x_cmd_intb_pin_cfg - send 'INTB_PIN_CFG' command to the device + * si476x_core_cmd_intb_pin_cfg_a10 - send 'INTB_PIN_CFG' command to the device * @core: - device to send the command to * @intb: - INTB pin function configuration: * SI476X_INTB_NOOP - do not modify the behaviour @@ -726,12 +726,12 @@ static int si476x_core_cmd_intb_pin_cfg_a20(struct si476x_core *core, /** - * si476x_cmd_am_rsq_status - send 'AM_RSQ_STATUS' command to the + * si476x_core_cmd_am_rsq_status - send 'AM_RSQ_STATUS' command to the * device * @core: - device to send the command to * @rsqargs: - pointer to a structure containing a group of sub-args * relevant to sending the RSQ status command - * @report: - all signal quality information retured by the command + * @report: - all signal quality information returned by the command * (if NULL then the output of the command is ignored) * * Function returns 0 on success and negative error code on failure @@ -856,7 +856,7 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_am_acf_status); /** - * si476x_cmd_fm_seek_start - send 'FM_SEEK_START' command to the + * si476x_core_cmd_fm_seek_start - send 'FM_SEEK_START' command to the * device * @core: - device to send the command to * @seekup: - if set the direction of the search is 'up' @@ -884,7 +884,7 @@ int si476x_core_cmd_fm_seek_start(struct si476x_core *core, EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_seek_start); /** - * si476x_cmd_fm_rds_status - send 'FM_RDS_STATUS' command to the + * si476x_core_cmd_fm_rds_status - send 'FM_RDS_STATUS' command to the * device * @core: - device to send the command to * @status_only: - if set the data is not removed from RDSFIFO, @@ -892,7 +892,7 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_seek_start); * rest RDS data contains the last valid info received * @mtfifo: if set the command clears RDS receive FIFO * @intack: if set the command clards the RDSINT bit. - * @report: - all signal quality information retured by the command + * @report: - all signal quality information returned by the command * (if NULL then the output of the command is ignored) * * Function returns 0 on success and negative error code on failure @@ -1032,7 +1032,7 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_phase_div_status); /** - * si476x_cmd_am_seek_start - send 'FM_SEEK_START' command to the + * si476x_core_cmd_am_seek_start - send 'FM_SEEK_START' command to the * device * @core: - device to send the command to * @seekup: - if set the direction of the search is 'up' diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c index c1d7b845244e..a2635c2d9d1a 100644 --- a/drivers/mfd/si476x-i2c.c +++ b/drivers/mfd/si476x-i2c.c @@ -350,7 +350,7 @@ static inline void si476x_core_start_rds_drainer_once(struct si476x_core *core) mutex_unlock(&core->rds_drainer_status_lock); } /** - * si476x_drain_rds_fifo() - RDS buffer drainer. + * si476x_core_drain_rds_fifo() - RDS buffer drainer. * @work: struct work_struct being ppassed to the function by the * kernel. * @@ -454,7 +454,7 @@ int si476x_core_i2c_xfer(struct si476x_core *core, EXPORT_SYMBOL_GPL(si476x_core_i2c_xfer); /** - * si476x_get_status() + * si476x_core_get_status() * @core: Core device structure * * Get the status byte of the core device by berforming one byte I2C @@ -473,7 +473,7 @@ static int si476x_core_get_status(struct si476x_core *core) } /** - * si476x_get_and_signal_status() - IRQ dispatcher + * si476x_core_get_and_signal_status() - IRQ dispatcher * @core: Core device structure * * Dispatch the arrived interrupt request based on the value of the @@ -532,7 +532,7 @@ static irqreturn_t si476x_core_interrupt(int irq, void *dev) } /** - * si476x_firmware_version_to_revision() + * si476x_core_fwver_to_revision() * @core: Core device structure * @func: Selects the boot function of the device: * *_BOOTLOADER - Boot loader @@ -603,7 +603,7 @@ unknown_revision: } /** - * si476x_get_revision_info() + * si476x_core_get_revision_info() * @core: Core device structure * * Get the firmware version number of the device. It is done in diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index 6d2f4a0a901d..bc0a2c38653e 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c @@ -1190,13 +1190,13 @@ static int sm501_register_gpio_i2c(struct sm501_devdata *sm, return 0; } -/* sm501_dbg_regs +/* dbg_regs_show * * Debug attribute to attach to parent device to show core registers */ -static ssize_t sm501_dbg_regs(struct device *dev, - struct device_attribute *attr, char *buff) +static ssize_t dbg_regs_show(struct device *dev, + struct device_attribute *attr, char *buff) { struct sm501_devdata *sm = dev_get_drvdata(dev) ; unsigned int reg; @@ -1213,7 +1213,7 @@ static ssize_t sm501_dbg_regs(struct device *dev, } -static DEVICE_ATTR(dbg_regs, 0444, sm501_dbg_regs, NULL); +static DEVICE_ATTR_RO(dbg_regs); /* sm501_init_reg * diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c index 61aa020199f5..cd2f45257dc1 100644 --- a/drivers/mfd/stmpe-i2c.c +++ b/drivers/mfd/stmpe-i2c.c @@ -109,7 +109,7 @@ static const struct i2c_device_id stmpe_i2c_id[] = { { "stmpe2403", STMPE2403 }, { } }; -MODULE_DEVICE_TABLE(i2c, stmpe_id); +MODULE_DEVICE_TABLE(i2c, stmpe_i2c_id); static struct i2c_driver stmpe_i2c_driver = { .driver = { diff --git a/drivers/mfd/sun6i-prcm.c b/drivers/mfd/sun6i-prcm.c index c31927d4bbbe..ee03db0b8485 100644 --- a/drivers/mfd/sun6i-prcm.c +++ b/drivers/mfd/sun6i-prcm.c @@ -20,43 +20,23 @@ struct prcm_data { }; static const struct resource sun6i_a31_ar100_clk_res[] = { - { - .start = 0x0, - .end = 0x3, - .flags = IORESOURCE_MEM, - }, + DEFINE_RES_MEM(0x0, 4) }; static const struct resource sun6i_a31_apb0_clk_res[] = { - { - .start = 0xc, - .end = 0xf, - .flags = IORESOURCE_MEM, - }, + DEFINE_RES_MEM(0xc, 4) }; static const struct resource sun6i_a31_apb0_gates_clk_res[] = { - { - .start = 0x28, - .end = 0x2b, - .flags = IORESOURCE_MEM, - }, + DEFINE_RES_MEM(0x28, 4) }; static const struct resource sun6i_a31_ir_clk_res[] = { - { - .start = 0x54, - .end = 0x57, - .flags = IORESOURCE_MEM, - }, + DEFINE_RES_MEM(0x54, 4) }; static const struct resource sun6i_a31_apb0_rstc_res[] = { - { - .start = 0xb0, - .end = 0xb3, - .flags = IORESOURCE_MEM, - }, + DEFINE_RES_MEM(0xb0, 4) }; static const struct resource sun8i_codec_analog_res[] = { diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c index c6f139b2e0c0..765c0210cb52 100644 --- a/drivers/mfd/syscon.c +++ b/drivers/mfd/syscon.c @@ -108,6 +108,7 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_clk) syscon_config.max_register = resource_size(&res) - reg_io_width; regmap = regmap_init_mmio(NULL, base, &syscon_config); + kfree(syscon_config.name); if (IS_ERR(regmap)) { pr_err("regmap init failed\n"); ret = PTR_ERR(regmap); @@ -144,7 +145,6 @@ err_clk: regmap_exit(regmap); err_regmap: iounmap(base); - kfree(syscon_config.name); err_map: kfree(syscon); return ERR_PTR(ret); diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c index 70da0c4ae457..5369c67e3280 100644 --- a/drivers/mfd/t7l66xb.c +++ b/drivers/mfd/t7l66xb.c @@ -37,16 +37,8 @@ enum { }; static const struct resource t7l66xb_mmc_resources[] = { - { - .start = 0x800, - .end = 0x9ff, - .flags = IORESOURCE_MEM, - }, - { - .start = IRQ_T7L66XB_MMC, - .end = IRQ_T7L66XB_MMC, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_MEM(0x800, 0x200), + DEFINE_RES_IRQ(IRQ_T7L66XB_MMC) }; #define SCR_REVID 0x08 /* b Revision ID */ diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c index faecbca6dba3..9393ee60a656 100644 --- a/drivers/mfd/timberdale.c +++ b/drivers/mfd/timberdale.c @@ -623,8 +623,8 @@ static const struct mfd_cell timberdale_cells_bar2[] = { }, }; -static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t fw_ver_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct timberdale_device *priv = dev_get_drvdata(dev); @@ -632,7 +632,7 @@ static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr, priv->fw.config); } -static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL); +static DEVICE_ATTR_RO(fw_ver); /*--------------------------------------------------------------------------*/ diff --git a/drivers/mfd/tps80031.c b/drivers/mfd/tps80031.c index 902e33548dd0..3c4e62c3406a 100644 --- a/drivers/mfd/tps80031.c +++ b/drivers/mfd/tps80031.c @@ -35,11 +35,7 @@ #include <linux/slab.h> static const struct resource tps80031_rtc_resources[] = { - { - .start = TPS80031_INT_RTC_ALARM, - .end = TPS80031_INT_RTC_ALARM, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ(TPS80031_INT_RTC_ALARM), }; /* TPS80031 sub mfd devices */ diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 20cf8cfe4f3b..289b556dede2 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -485,7 +485,7 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) EXPORT_SYMBOL(twl_i2c_read); /** - * twl_regcache_bypass - Configure the regcache bypass for the regmap associated + * twl_set_regcache_bypass - Configure the regcache bypass for the regmap associated * with the module * @mod_no: module number * @enable: Regcache bypass state diff --git a/drivers/mfd/ucb1x00-assabet.c b/drivers/mfd/ucb1x00-assabet.c index ecc9e9fc331d..6a389737c615 100644 --- a/drivers/mfd/ucb1x00-assabet.c +++ b/drivers/mfd/ucb1x00-assabet.c @@ -28,7 +28,7 @@ static ssize_t name##_show(struct device *dev, struct device_attribute *attr, \ ucb1x00_adc_disable(ucb); \ return sprintf(buf, "%d\n", val); \ } \ -static DEVICE_ATTR(name,0444,name##_show,NULL) +static DEVICE_ATTR_RO(name) UCB1X00_ATTR(vbatt, UCB_ADC_INP_AD1); UCB1X00_ATTR(vcharger, UCB_ADC_INP_AD0); diff --git a/drivers/mfd/wcd934x.c b/drivers/mfd/wcd934x.c index c274d733b656..aa19a6a4fdbf 100644 --- a/drivers/mfd/wcd934x.c +++ b/drivers/mfd/wcd934x.c @@ -17,6 +17,21 @@ #include <linux/regulator/consumer.h> #include <linux/slimbus.h> +#define WCD934X_REGMAP_IRQ_REG(_irq, _off, _mask) \ + [_irq] = { \ + .reg_offset = (_off), \ + .mask = (_mask), \ + .type = { \ + .type_reg_offset = (_off), \ + .types_supported = IRQ_TYPE_EDGE_BOTH, \ + .type_reg_mask = (_mask), \ + .type_level_low_val = (_mask), \ + .type_level_high_val = (_mask), \ + .type_falling_val = 0, \ + .type_rising_val = 0, \ + }, \ + } + static const struct mfd_cell wcd934x_devices[] = { { .name = "wcd934x-codec", @@ -30,32 +45,15 @@ static const struct mfd_cell wcd934x_devices[] = { }; static const struct regmap_irq wcd934x_irqs[] = { - [WCD934X_IRQ_SLIMBUS] = { - .reg_offset = 0, - .mask = BIT(0), - .type = { - .type_reg_offset = 0, - .types_supported = IRQ_TYPE_EDGE_BOTH, - .type_reg_mask = BIT(0), - .type_level_low_val = BIT(0), - .type_level_high_val = BIT(0), - .type_falling_val = 0, - .type_rising_val = 0, - }, - }, - [WCD934X_IRQ_SOUNDWIRE] = { - .reg_offset = 2, - .mask = BIT(4), - .type = { - .type_reg_offset = 2, - .types_supported = IRQ_TYPE_EDGE_BOTH, - .type_reg_mask = BIT(4), - .type_level_low_val = BIT(4), - .type_level_high_val = BIT(4), - .type_falling_val = 0, - .type_rising_val = 0, - }, - }, + WCD934X_REGMAP_IRQ_REG(WCD934X_IRQ_SLIMBUS, 0, BIT(0)), + WCD934X_REGMAP_IRQ_REG(WCD934X_IRQ_HPH_PA_OCPL_FAULT, 0, BIT(2)), + WCD934X_REGMAP_IRQ_REG(WCD934X_IRQ_HPH_PA_OCPR_FAULT, 0, BIT(3)), + WCD934X_REGMAP_IRQ_REG(WCD934X_IRQ_MBHC_SW_DET, 1, BIT(0)), + WCD934X_REGMAP_IRQ_REG(WCD934X_IRQ_MBHC_ELECT_INS_REM_DET, 1, BIT(1)), + WCD934X_REGMAP_IRQ_REG(WCD934X_IRQ_MBHC_BUTTON_PRESS_DET, 1, BIT(2)), + WCD934X_REGMAP_IRQ_REG(WCD934X_IRQ_MBHC_BUTTON_RELEASE_DET, 1, BIT(3)), + WCD934X_REGMAP_IRQ_REG(WCD934X_IRQ_MBHC_ELECT_INS_REM_LEG_DET, 1, BIT(4)), + WCD934X_REGMAP_IRQ_REG(WCD934X_IRQ_SOUNDWIRE, 2, BIT(4)), }; static const struct regmap_irq_chip wcd934x_regmap_irq_chip = { diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index bcef08f58fb3..d2f444d2ae78 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -109,7 +109,7 @@ static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg) } /** - * wm831x_reg_unlock: Unlock user keyed registers + * wm831x_reg_lock: Unlock user keyed registers * * The WM831x has a user key preventing writes to particularly * critical registers. This function locks those registers, @@ -622,18 +622,8 @@ static const struct resource wm831x_dcdc1_resources[] = { .end = WM831X_DC1_DVS_CONTROL, .flags = IORESOURCE_REG, }, - { - .name = "UV", - .start = WM831X_IRQ_UV_DC1, - .end = WM831X_IRQ_UV_DC1, - .flags = IORESOURCE_IRQ, - }, - { - .name = "HC", - .start = WM831X_IRQ_HC_DC1, - .end = WM831X_IRQ_HC_DC1, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_UV_DC1, "UV"), + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_HC_DC1, "HC"), }; @@ -643,18 +633,8 @@ static const struct resource wm831x_dcdc2_resources[] = { .end = WM831X_DC2_DVS_CONTROL, .flags = IORESOURCE_REG, }, - { - .name = "UV", - .start = WM831X_IRQ_UV_DC2, - .end = WM831X_IRQ_UV_DC2, - .flags = IORESOURCE_IRQ, - }, - { - .name = "HC", - .start = WM831X_IRQ_HC_DC2, - .end = WM831X_IRQ_HC_DC2, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_UV_DC2, "UV"), + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_HC_DC2, "HC"), }; static const struct resource wm831x_dcdc3_resources[] = { @@ -663,12 +643,7 @@ static const struct resource wm831x_dcdc3_resources[] = { .end = WM831X_DC3_SLEEP_CONTROL, .flags = IORESOURCE_REG, }, - { - .name = "UV", - .start = WM831X_IRQ_UV_DC3, - .end = WM831X_IRQ_UV_DC3, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_UV_DC3, "UV"), }; static const struct resource wm831x_dcdc4_resources[] = { @@ -677,12 +652,7 @@ static const struct resource wm831x_dcdc4_resources[] = { .end = WM831X_DC4_SLEEP_CONTROL, .flags = IORESOURCE_REG, }, - { - .name = "UV", - .start = WM831X_IRQ_UV_DC4, - .end = WM831X_IRQ_UV_DC4, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_UV_DC4, "UV"), }; static const struct resource wm8320_dcdc4_buck_resources[] = { @@ -691,12 +661,7 @@ static const struct resource wm8320_dcdc4_buck_resources[] = { .end = WM832X_DC4_SLEEP_CONTROL, .flags = IORESOURCE_REG, }, - { - .name = "UV", - .start = WM831X_IRQ_UV_DC4, - .end = WM831X_IRQ_UV_DC4, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_UV_DC4, "UV"), }; static const struct resource wm831x_gpio_resources[] = { @@ -713,11 +678,7 @@ static const struct resource wm831x_isink1_resources[] = { .end = WM831X_CURRENT_SINK_1, .flags = IORESOURCE_REG, }, - { - .start = WM831X_IRQ_CS1, - .end = WM831X_IRQ_CS1, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ(WM831X_IRQ_CS1), }; static const struct resource wm831x_isink2_resources[] = { @@ -726,11 +687,7 @@ static const struct resource wm831x_isink2_resources[] = { .end = WM831X_CURRENT_SINK_2, .flags = IORESOURCE_REG, }, - { - .start = WM831X_IRQ_CS2, - .end = WM831X_IRQ_CS2, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ(WM831X_IRQ_CS2), }; static const struct resource wm831x_ldo1_resources[] = { @@ -739,12 +696,7 @@ static const struct resource wm831x_ldo1_resources[] = { .end = WM831X_LDO1_SLEEP_CONTROL, .flags = IORESOURCE_REG, }, - { - .name = "UV", - .start = WM831X_IRQ_UV_LDO1, - .end = WM831X_IRQ_UV_LDO1, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_UV_LDO1, "UV"), }; static const struct resource wm831x_ldo2_resources[] = { @@ -753,12 +705,7 @@ static const struct resource wm831x_ldo2_resources[] = { .end = WM831X_LDO2_SLEEP_CONTROL, .flags = IORESOURCE_REG, }, - { - .name = "UV", - .start = WM831X_IRQ_UV_LDO2, - .end = WM831X_IRQ_UV_LDO2, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_UV_LDO2, "UV"), }; static const struct resource wm831x_ldo3_resources[] = { @@ -767,12 +714,7 @@ static const struct resource wm831x_ldo3_resources[] = { .end = WM831X_LDO3_SLEEP_CONTROL, .flags = IORESOURCE_REG, }, - { - .name = "UV", - .start = WM831X_IRQ_UV_LDO3, - .end = WM831X_IRQ_UV_LDO3, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_UV_LDO3, "UV"), }; static const struct resource wm831x_ldo4_resources[] = { @@ -781,12 +723,7 @@ static const struct resource wm831x_ldo4_resources[] = { .end = WM831X_LDO4_SLEEP_CONTROL, .flags = IORESOURCE_REG, }, - { - .name = "UV", - .start = WM831X_IRQ_UV_LDO4, - .end = WM831X_IRQ_UV_LDO4, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_UV_LDO4, "UV"), }; static const struct resource wm831x_ldo5_resources[] = { @@ -795,12 +732,7 @@ static const struct resource wm831x_ldo5_resources[] = { .end = WM831X_LDO5_SLEEP_CONTROL, .flags = IORESOURCE_REG, }, - { - .name = "UV", - .start = WM831X_IRQ_UV_LDO5, - .end = WM831X_IRQ_UV_LDO5, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_UV_LDO5, "UV"), }; static const struct resource wm831x_ldo6_resources[] = { @@ -809,12 +741,7 @@ static const struct resource wm831x_ldo6_resources[] = { .end = WM831X_LDO6_SLEEP_CONTROL, .flags = IORESOURCE_REG, }, - { - .name = "UV", - .start = WM831X_IRQ_UV_LDO6, - .end = WM831X_IRQ_UV_LDO6, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_UV_LDO6, "UV"), }; static const struct resource wm831x_ldo7_resources[] = { @@ -823,12 +750,7 @@ static const struct resource wm831x_ldo7_resources[] = { .end = WM831X_LDO7_SLEEP_CONTROL, .flags = IORESOURCE_REG, }, - { - .name = "UV", - .start = WM831X_IRQ_UV_LDO7, - .end = WM831X_IRQ_UV_LDO7, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_UV_LDO7, "UV"), }; static const struct resource wm831x_ldo8_resources[] = { @@ -837,12 +759,7 @@ static const struct resource wm831x_ldo8_resources[] = { .end = WM831X_LDO8_SLEEP_CONTROL, .flags = IORESOURCE_REG, }, - { - .name = "UV", - .start = WM831X_IRQ_UV_LDO8, - .end = WM831X_IRQ_UV_LDO8, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_UV_LDO8, "UV"), }; static const struct resource wm831x_ldo9_resources[] = { @@ -851,12 +768,7 @@ static const struct resource wm831x_ldo9_resources[] = { .end = WM831X_LDO9_SLEEP_CONTROL, .flags = IORESOURCE_REG, }, - { - .name = "UV", - .start = WM831X_IRQ_UV_LDO9, - .end = WM831X_IRQ_UV_LDO9, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_UV_LDO9, "UV"), }; static const struct resource wm831x_ldo10_resources[] = { @@ -865,12 +777,7 @@ static const struct resource wm831x_ldo10_resources[] = { .end = WM831X_LDO10_SLEEP_CONTROL, .flags = IORESOURCE_REG, }, - { - .name = "UV", - .start = WM831X_IRQ_UV_LDO10, - .end = WM831X_IRQ_UV_LDO10, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_UV_LDO10, "UV"), }; static const struct resource wm831x_ldo11_resources[] = { @@ -882,96 +789,27 @@ static const struct resource wm831x_ldo11_resources[] = { }; static const struct resource wm831x_on_resources[] = { - { - .start = WM831X_IRQ_ON, - .end = WM831X_IRQ_ON, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ(WM831X_IRQ_ON), }; static const struct resource wm831x_power_resources[] = { - { - .name = "SYSLO", - .start = WM831X_IRQ_PPM_SYSLO, - .end = WM831X_IRQ_PPM_SYSLO, - .flags = IORESOURCE_IRQ, - }, - { - .name = "PWR SRC", - .start = WM831X_IRQ_PPM_PWR_SRC, - .end = WM831X_IRQ_PPM_PWR_SRC, - .flags = IORESOURCE_IRQ, - }, - { - .name = "USB CURR", - .start = WM831X_IRQ_PPM_USB_CURR, - .end = WM831X_IRQ_PPM_USB_CURR, - .flags = IORESOURCE_IRQ, - }, - { - .name = "BATT HOT", - .start = WM831X_IRQ_CHG_BATT_HOT, - .end = WM831X_IRQ_CHG_BATT_HOT, - .flags = IORESOURCE_IRQ, - }, - { - .name = "BATT COLD", - .start = WM831X_IRQ_CHG_BATT_COLD, - .end = WM831X_IRQ_CHG_BATT_COLD, - .flags = IORESOURCE_IRQ, - }, - { - .name = "BATT FAIL", - .start = WM831X_IRQ_CHG_BATT_FAIL, - .end = WM831X_IRQ_CHG_BATT_FAIL, - .flags = IORESOURCE_IRQ, - }, - { - .name = "OV", - .start = WM831X_IRQ_CHG_OV, - .end = WM831X_IRQ_CHG_OV, - .flags = IORESOURCE_IRQ, - }, - { - .name = "END", - .start = WM831X_IRQ_CHG_END, - .end = WM831X_IRQ_CHG_END, - .flags = IORESOURCE_IRQ, - }, - { - .name = "TO", - .start = WM831X_IRQ_CHG_TO, - .end = WM831X_IRQ_CHG_TO, - .flags = IORESOURCE_IRQ, - }, - { - .name = "MODE", - .start = WM831X_IRQ_CHG_MODE, - .end = WM831X_IRQ_CHG_MODE, - .flags = IORESOURCE_IRQ, - }, - { - .name = "START", - .start = WM831X_IRQ_CHG_START, - .end = WM831X_IRQ_CHG_START, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_PPM_SYSLO, "SYSLO"), + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_PPM_PWR_SRC, "PWR SRC"), + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_PPM_USB_CURR, "USB CURR"), + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_CHG_BATT_HOT, "BATT HOT"), + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_CHG_BATT_COLD, "BATT COLD"), + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_CHG_BATT_FAIL, "BATT FAIL"), + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_CHG_OV, "OV"), + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_CHG_END, "END"), + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_CHG_TO, "TO"), + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_CHG_MODE, "MODE"), + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_CHG_START, "START"), }; static const struct resource wm831x_rtc_resources[] = { - { - .name = "PER", - .start = WM831X_IRQ_RTC_PER, - .end = WM831X_IRQ_RTC_PER, - .flags = IORESOURCE_IRQ, - }, - { - .name = "ALM", - .start = WM831X_IRQ_RTC_ALM, - .end = WM831X_IRQ_RTC_ALM, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_RTC_PER, "PER"), + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_RTC_ALM, "ALM"), }; static const struct resource wm831x_status1_resources[] = { @@ -991,26 +829,12 @@ static const struct resource wm831x_status2_resources[] = { }; static const struct resource wm831x_touch_resources[] = { - { - .name = "TCHPD", - .start = WM831X_IRQ_TCHPD, - .end = WM831X_IRQ_TCHPD, - .flags = IORESOURCE_IRQ, - }, - { - .name = "TCHDATA", - .start = WM831X_IRQ_TCHDATA, - .end = WM831X_IRQ_TCHDATA, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_TCHPD, "TCHPD"), + DEFINE_RES_IRQ_NAMED(WM831X_IRQ_TCHDATA, "TCHDATA"), }; static const struct resource wm831x_wdt_resources[] = { - { - .start = WM831X_IRQ_WDOG_TO, - .end = WM831X_IRQ_WDOG_TO, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ(WM831X_IRQ_WDOG_TO), }; static const struct mfd_cell wm8310_devs[] = { diff --git a/drivers/mfd/wm831x-otp.c b/drivers/mfd/wm831x-otp.c index afe59d52dd74..25f5d9fe33a1 100644 --- a/drivers/mfd/wm831x-otp.c +++ b/drivers/mfd/wm831x-otp.c @@ -38,8 +38,8 @@ static int wm831x_unique_id_read(struct wm831x *wm831x, char *id) return 0; } -static ssize_t wm831x_unique_id_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t unique_id_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct wm831x *wm831x = dev_get_drvdata(dev); int rval; @@ -52,7 +52,7 @@ static ssize_t wm831x_unique_id_show(struct device *dev, return sprintf(buf, "%*phN\n", WM831X_UNIQUE_ID_LEN, id); } -static DEVICE_ATTR(unique_id, 0444, wm831x_unique_id_show, NULL); +static DEVICE_ATTR_RO(unique_id); int wm831x_otp_init(struct wm831x *wm831x) { diff --git a/drivers/misc/bcm-vk/bcm_vk_msg.c b/drivers/misc/bcm-vk/bcm_vk_msg.c index f40cf08a6192..066b9ef7fcd7 100644 --- a/drivers/misc/bcm-vk/bcm_vk_msg.c +++ b/drivers/misc/bcm-vk/bcm_vk_msg.c @@ -354,8 +354,7 @@ static void bcm_vk_drain_all_pend(struct device *dev, for (num = 0; num < chan->q_nr; num++) { list_for_each_entry_safe(entry, tmp, &chan->pendq[num], node) { if ((!ctx) || (entry->ctx->idx == ctx->idx)) { - list_del(&entry->node); - list_add_tail(&entry->node, &del_q); + list_move_tail(&entry->node, &del_q); } } } @@ -701,8 +700,7 @@ int bcm_vk_send_shutdown_msg(struct bcm_vk *vk, u32 shut_type, return -EINVAL; } - entry = kzalloc(sizeof(*entry) + - sizeof(struct vk_msg_blk), GFP_KERNEL); + entry = kzalloc(struct_size(entry, to_v_msg, 1), GFP_KERNEL); if (!entry) return -ENOMEM; diff --git a/drivers/misc/bcm-vk/bcm_vk_msg.h b/drivers/misc/bcm-vk/bcm_vk_msg.h index 4eaad84825d6..56784c8896d8 100644 --- a/drivers/misc/bcm-vk/bcm_vk_msg.h +++ b/drivers/misc/bcm-vk/bcm_vk_msg.h @@ -116,7 +116,7 @@ struct bcm_vk_wkent { u32 usr_msg_id; u32 to_v_blks; u32 seq_num; - struct vk_msg_blk to_v_msg[0]; + struct vk_msg_blk to_v_msg[]; }; /* queue stats counters */ diff --git a/drivers/misc/bcm-vk/bcm_vk_tty.c b/drivers/misc/bcm-vk/bcm_vk_tty.c index 4d02692ecfc7..dae9eeed84a2 100644 --- a/drivers/misc/bcm-vk/bcm_vk_tty.c +++ b/drivers/misc/bcm-vk/bcm_vk_tty.c @@ -214,7 +214,7 @@ static int bcm_vk_tty_write(struct tty_struct *tty, return count; } -static int bcm_vk_tty_write_room(struct tty_struct *tty) +static unsigned int bcm_vk_tty_write_room(struct tty_struct *tty) { struct bcm_vk *vk = dev_get_drvdata(tty->dev); diff --git a/drivers/misc/cardreader/alcor_pci.c b/drivers/misc/cardreader/alcor_pci.c index cd402c89189e..de6d44a158bb 100644 --- a/drivers/misc/cardreader/alcor_pci.c +++ b/drivers/misc/cardreader/alcor_pci.c @@ -139,7 +139,13 @@ static void alcor_pci_init_check_aspm(struct alcor_pci_priv *priv) u32 val32; priv->pdev_cap_off = alcor_pci_find_cap_offset(priv, priv->pdev); - priv->parent_cap_off = alcor_pci_find_cap_offset(priv, + /* + * A device might be attached to root complex directly and + * priv->parent_pdev will be NULL. In this case we don't check its + * capability and disable ASPM completely. + */ + if (priv->parent_pdev) + priv->parent_cap_off = alcor_pci_find_cap_offset(priv, priv->parent_pdev); if ((priv->pdev_cap_off == 0) || (priv->parent_cap_off == 0)) { diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c index bd3bd32333c5..3dbdce96fae0 100644 --- a/drivers/misc/cxl/file.c +++ b/drivers/misc/cxl/file.c @@ -569,7 +569,8 @@ static int cxl_add_chardev(struct cxl_afu *afu, dev_t devt, struct cdev *cdev, int rc; cdev_init(cdev, fops); - if ((rc = cdev_add(cdev, devt, 1))) { + rc = cdev_add(cdev, devt, 1); + if (rc) { dev_err(&afu->dev, "Unable to add %s chardev: %i\n", desc, rc); return rc; } @@ -577,8 +578,8 @@ static int cxl_add_chardev(struct cxl_afu *afu, dev_t devt, struct cdev *cdev, dev = device_create(cxl_class, &afu->dev, devt, afu, "afu%i.%i%s", afu->adapter->adapter_num, afu->slice, postfix); if (IS_ERR(dev)) { - dev_err(&afu->dev, "Unable to create %s chardev in sysfs: %i\n", desc, rc); rc = PTR_ERR(dev); + dev_err(&afu->dev, "Unable to create %s chardev in sysfs: %i\n", desc, rc); goto err; } diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig index 0f791bfdc1f5..f0a7531f354c 100644 --- a/drivers/misc/eeprom/Kconfig +++ b/drivers/misc/eeprom/Kconfig @@ -32,12 +32,13 @@ config EEPROM_AT24 will be called at24. config EEPROM_AT25 - tristate "SPI EEPROMs from most vendors" + tristate "SPI EEPROMs (FRAMs) from most vendors" depends on SPI && SYSFS select NVMEM select NVMEM_SYSFS help - Enable this driver to get read/write support to most SPI EEPROMs, + Enable this driver to get read/write support to most SPI EEPROMs + and Cypress FRAMs, after you configure the board init code to know about each eeprom on your target board. diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c index b76e4901b4a4..4d09b672ac3c 100644 --- a/drivers/misc/eeprom/at25.c +++ b/drivers/misc/eeprom/at25.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * at25.c -- support most SPI EEPROMs, such as Atmel AT25 models + * and Cypress FRAMs FM25 models * * Copyright (C) 2006 David Brownell */ @@ -16,6 +17,9 @@ #include <linux/spi/spi.h> #include <linux/spi/eeprom.h> #include <linux/property.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/math.h> /* * NOTE: this is an *EEPROM* driver. The vagaries of product naming @@ -27,6 +31,7 @@ * AT25M02, AT25128B */ +#define FM25_SN_LEN 8 /* serial number length */ struct at25_data { struct spi_device *spi; struct mutex lock; @@ -34,6 +39,7 @@ struct at25_data { unsigned addrlen; struct nvmem_config nvmem_config; struct nvmem_device *nvmem; + u8 sernum[FM25_SN_LEN]; }; #define AT25_WREN 0x06 /* latch the write enable */ @@ -42,6 +48,9 @@ struct at25_data { #define AT25_WRSR 0x01 /* write status register */ #define AT25_READ 0x03 /* read byte(s) */ #define AT25_WRITE 0x02 /* write byte(s)/sector */ +#define FM25_SLEEP 0xb9 /* enter sleep mode */ +#define FM25_RDID 0x9f /* read device ID */ +#define FM25_RDSN 0xc3 /* read S/N */ #define AT25_SR_nRDY 0x01 /* nRDY = write-in-progress */ #define AT25_SR_WEN 0x02 /* write enable (latched) */ @@ -51,6 +60,8 @@ struct at25_data { #define AT25_INSTR_BIT3 0x08 /* Additional address bit in instr */ +#define FM25_ID_LEN 9 /* ID length */ + #define EE_MAXADDRLEN 3 /* 24 bit addresses, up to 2 MBytes */ /* Specs often allow 5 msec for a page write, sometimes 20 msec; @@ -129,6 +140,51 @@ static int at25_ee_read(void *priv, unsigned int offset, return status; } +/* + * read extra registers as ID or serial number + */ +static int fm25_aux_read(struct at25_data *at25, u8 *buf, uint8_t command, + int len) +{ + int status; + struct spi_transfer t[2]; + struct spi_message m; + + spi_message_init(&m); + memset(t, 0, sizeof(t)); + + t[0].tx_buf = &command; + t[0].len = 1; + spi_message_add_tail(&t[0], &m); + + t[1].rx_buf = buf; + t[1].len = len; + spi_message_add_tail(&t[1], &m); + + mutex_lock(&at25->lock); + + status = spi_sync(at25->spi, &m); + dev_dbg(&at25->spi->dev, "read %d aux bytes --> %d\n", len, status); + + mutex_unlock(&at25->lock); + return status; +} + +static ssize_t sernum_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct at25_data *at25; + + at25 = dev_get_drvdata(dev); + return sysfs_emit(buf, "%*ph\n", (int)sizeof(at25->sernum), at25->sernum); +} +static DEVICE_ATTR_RO(sernum); + +static struct attribute *sernum_attrs[] = { + &dev_attr_sernum.attr, + NULL, +}; +ATTRIBUTE_GROUPS(sernum); + static int at25_ee_write(void *priv, unsigned int off, void *val, size_t count) { struct at25_data *at25 = priv; @@ -303,34 +359,39 @@ static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip) return 0; } +static const struct of_device_id at25_of_match[] = { + { .compatible = "atmel,at25",}, + { .compatible = "cypress,fm25",}, + { } +}; +MODULE_DEVICE_TABLE(of, at25_of_match); + static int at25_probe(struct spi_device *spi) { struct at25_data *at25 = NULL; struct spi_eeprom chip; int err; int sr; - int addrlen; + u8 id[FM25_ID_LEN]; + u8 sernum[FM25_SN_LEN]; + int i; + const struct of_device_id *match; + bool is_fram = 0; + + match = of_match_device(of_match_ptr(at25_of_match), &spi->dev); + if (match && !strcmp(match->compatible, "cypress,fm25")) + is_fram = 1; /* Chip description */ if (!spi->dev.platform_data) { - err = at25_fw_to_chip(&spi->dev, &chip); - if (err) - return err; + if (!is_fram) { + err = at25_fw_to_chip(&spi->dev, &chip); + if (err) + return err; + } } else chip = *(struct spi_eeprom *)spi->dev.platform_data; - /* For now we only support 8/16/24 bit addressing */ - if (chip.flags & EE_ADDR1) - addrlen = 1; - else if (chip.flags & EE_ADDR2) - addrlen = 2; - else if (chip.flags & EE_ADDR3) - addrlen = 3; - else { - dev_dbg(&spi->dev, "unsupported address type\n"); - return -EINVAL; - } - /* Ping the chip ... the status register is pretty portable, * unlike probing manufacturer IDs. We do expect that system * firmware didn't write it in the past few milliseconds! @@ -349,9 +410,51 @@ static int at25_probe(struct spi_device *spi) at25->chip = chip; at25->spi = spi; spi_set_drvdata(spi, at25); - at25->addrlen = addrlen; - at25->nvmem_config.type = NVMEM_TYPE_EEPROM; + if (is_fram) { + /* Get ID of chip */ + fm25_aux_read(at25, id, FM25_RDID, FM25_ID_LEN); + if (id[6] != 0xc2) { + dev_err(&spi->dev, + "Error: no Cypress FRAM (id %02x)\n", id[6]); + return -ENODEV; + } + /* set size found in ID */ + if (id[7] < 0x21 || id[7] > 0x26) { + dev_err(&spi->dev, "Error: unsupported size (id %02x)\n", id[7]); + return -ENODEV; + } + chip.byte_len = int_pow(2, id[7] - 0x21 + 4) * 1024; + + if (at25->chip.byte_len > 64 * 1024) + at25->chip.flags |= EE_ADDR3; + else + at25->chip.flags |= EE_ADDR2; + + if (id[8]) { + fm25_aux_read(at25, sernum, FM25_RDSN, FM25_SN_LEN); + /* swap byte order */ + for (i = 0; i < FM25_SN_LEN; i++) + at25->sernum[i] = sernum[FM25_SN_LEN - 1 - i]; + } + + at25->chip.page_size = PAGE_SIZE; + strncpy(at25->chip.name, "fm25", sizeof(at25->chip.name)); + } + + /* For now we only support 8/16/24 bit addressing */ + if (at25->chip.flags & EE_ADDR1) + at25->addrlen = 1; + else if (at25->chip.flags & EE_ADDR2) + at25->addrlen = 2; + else if (at25->chip.flags & EE_ADDR3) + at25->addrlen = 3; + else { + dev_dbg(&spi->dev, "unsupported address type\n"); + return -EINVAL; + } + + at25->nvmem_config.type = is_fram ? NVMEM_TYPE_FRAM : NVMEM_TYPE_EEPROM; at25->nvmem_config.name = dev_name(&spi->dev); at25->nvmem_config.dev = &spi->dev; at25->nvmem_config.read_only = chip.flags & EE_READONLY; @@ -370,27 +473,22 @@ static int at25_probe(struct spi_device *spi) if (IS_ERR(at25->nvmem)) return PTR_ERR(at25->nvmem); - dev_info(&spi->dev, "%d %s %s eeprom%s, pagesize %u\n", - (chip.byte_len < 1024) ? chip.byte_len : (chip.byte_len / 1024), - (chip.byte_len < 1024) ? "Byte" : "KByte", - at25->chip.name, - (chip.flags & EE_READONLY) ? " (readonly)" : "", - at25->chip.page_size); + dev_info(&spi->dev, "%d %s %s %s%s, pagesize %u\n", + (chip.byte_len < 1024) ? chip.byte_len : (chip.byte_len / 1024), + (chip.byte_len < 1024) ? "Byte" : "KByte", + at25->chip.name, is_fram ? "fram" : "eeprom", + (chip.flags & EE_READONLY) ? " (readonly)" : "", + at25->chip.page_size); return 0; } /*-------------------------------------------------------------------------*/ -static const struct of_device_id at25_of_match[] = { - { .compatible = "atmel,at25", }, - { } -}; -MODULE_DEVICE_TABLE(of, at25_of_match); - static struct spi_driver at25_driver = { .driver = { .name = "at25", .of_match_table = at25_of_match, + .dev_groups = sernum_groups, }, .probe = at25_probe, }; diff --git a/drivers/misc/eeprom/ee1004.c b/drivers/misc/eeprom/ee1004.c index 252e15ba65e1..bb9c4512c968 100644 --- a/drivers/misc/eeprom/ee1004.c +++ b/drivers/misc/eeprom/ee1004.c @@ -32,16 +32,17 @@ */ #define EE1004_ADDR_SET_PAGE 0x36 -#define EE1004_EEPROM_SIZE 512 +#define EE1004_NUM_PAGES 2 #define EE1004_PAGE_SIZE 256 #define EE1004_PAGE_SHIFT 8 +#define EE1004_EEPROM_SIZE (EE1004_PAGE_SIZE * EE1004_NUM_PAGES) /* * Mutex protects ee1004_set_page and ee1004_dev_count, and must be held * from page selection to end of read. */ static DEFINE_MUTEX(ee1004_bus_lock); -static struct i2c_client *ee1004_set_page[2]; +static struct i2c_client *ee1004_set_page[EE1004_NUM_PAGES]; static unsigned int ee1004_dev_count; static int ee1004_current_page; @@ -71,40 +72,58 @@ static int ee1004_get_current_page(void) return 0; } +static int ee1004_set_current_page(struct device *dev, int page) +{ + int ret; + + if (page == ee1004_current_page) + return 0; + + /* Data is ignored */ + ret = i2c_smbus_write_byte(ee1004_set_page[page], 0x00); + /* + * Don't give up just yet. Some memory modules will select the page + * but not ack the command. Check which page is selected now. + */ + if (ret == -ENXIO && ee1004_get_current_page() == page) + ret = 0; + if (ret < 0) { + dev_err(dev, "Failed to select page %d (%d)\n", page, ret); + return ret; + } + + dev_dbg(dev, "Selected page %d\n", page); + ee1004_current_page = page; + + return 0; +} + static ssize_t ee1004_eeprom_read(struct i2c_client *client, char *buf, unsigned int offset, size_t count) { - int status; + int status, page; + + page = offset >> EE1004_PAGE_SHIFT; + offset &= (1 << EE1004_PAGE_SHIFT) - 1; + + status = ee1004_set_current_page(&client->dev, page); + if (status) + return status; - if (count > I2C_SMBUS_BLOCK_MAX) - count = I2C_SMBUS_BLOCK_MAX; /* Can't cross page boundaries */ - if (unlikely(offset + count > EE1004_PAGE_SIZE)) + if (offset + count > EE1004_PAGE_SIZE) count = EE1004_PAGE_SIZE - offset; - status = i2c_smbus_read_i2c_block_data_or_emulated(client, offset, - count, buf); - dev_dbg(&client->dev, "read %zu@%d --> %d\n", count, offset, status); - - return status; + return i2c_smbus_read_i2c_block_data_or_emulated(client, offset, count, buf); } -static ssize_t ee1004_read(struct file *filp, struct kobject *kobj, +static ssize_t eeprom_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct device *dev = kobj_to_dev(kobj); - struct i2c_client *client = to_i2c_client(dev); + struct i2c_client *client = kobj_to_i2c_client(kobj); size_t requested = count; - int page; - - if (unlikely(!count)) - return count; - - page = off >> EE1004_PAGE_SHIFT; - if (unlikely(page > 1)) - return 0; - off &= (1 << EE1004_PAGE_SHIFT) - 1; + int ret = 0; /* * Read data from chip, protecting against concurrent access to @@ -113,139 +132,85 @@ static ssize_t ee1004_read(struct file *filp, struct kobject *kobj, mutex_lock(&ee1004_bus_lock); while (count) { - int status; - - /* Select page */ - if (page != ee1004_current_page) { - /* Data is ignored */ - status = i2c_smbus_write_byte(ee1004_set_page[page], - 0x00); - if (status == -ENXIO) { - /* - * Don't give up just yet. Some memory - * modules will select the page but not - * ack the command. Check which page is - * selected now. - */ - if (ee1004_get_current_page() == page) - status = 0; - } - if (status < 0) { - dev_err(dev, "Failed to select page %d (%d)\n", - page, status); - mutex_unlock(&ee1004_bus_lock); - return status; - } - dev_dbg(dev, "Selected page %d\n", page); - ee1004_current_page = page; - } - - status = ee1004_eeprom_read(client, buf, off, count); - if (status < 0) { - mutex_unlock(&ee1004_bus_lock); - return status; - } - buf += status; - off += status; - count -= status; + ret = ee1004_eeprom_read(client, buf, off, count); + if (ret < 0) + goto out; - if (off == EE1004_PAGE_SIZE) { - page++; - off = 0; - } + buf += ret; + off += ret; + count -= ret; } - +out: mutex_unlock(&ee1004_bus_lock); - return requested; + return ret < 0 ? ret : requested; } -static const struct bin_attribute eeprom_attr = { - .attr = { - .name = "eeprom", - .mode = 0444, - }, - .size = EE1004_EEPROM_SIZE, - .read = ee1004_read, +static BIN_ATTR_RO(eeprom, EE1004_EEPROM_SIZE); + +static struct bin_attribute *ee1004_attrs[] = { + &bin_attr_eeprom, + NULL }; -static int ee1004_probe(struct i2c_client *client, - const struct i2c_device_id *id) +BIN_ATTRIBUTE_GROUPS(ee1004); + +static void ee1004_cleanup(int idx) +{ + if (--ee1004_dev_count == 0) + while (--idx >= 0) { + i2c_unregister_device(ee1004_set_page[idx]); + ee1004_set_page[idx] = NULL; + } +} + +static int ee1004_probe(struct i2c_client *client) { int err, cnr = 0; - const char *slow = NULL; /* Make sure we can operate on this adapter */ if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_BYTE | - I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { - if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_BYTE | - I2C_FUNC_SMBUS_READ_WORD_DATA)) - slow = "word"; - else if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_BYTE | - I2C_FUNC_SMBUS_READ_BYTE_DATA)) - slow = "byte"; - else - return -EPFNOSUPPORT; - } + I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_READ_I2C_BLOCK) && + !i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_READ_BYTE_DATA)) + return -EPFNOSUPPORT; /* Use 2 dummy devices for page select command */ mutex_lock(&ee1004_bus_lock); if (++ee1004_dev_count == 1) { - for (cnr = 0; cnr < 2; cnr++) { - ee1004_set_page[cnr] = i2c_new_dummy_device(client->adapter, - EE1004_ADDR_SET_PAGE + cnr); - if (IS_ERR(ee1004_set_page[cnr])) { - dev_err(&client->dev, - "address 0x%02x unavailable\n", - EE1004_ADDR_SET_PAGE + cnr); - err = PTR_ERR(ee1004_set_page[cnr]); + for (cnr = 0; cnr < EE1004_NUM_PAGES; cnr++) { + struct i2c_client *cl; + + cl = i2c_new_dummy_device(client->adapter, EE1004_ADDR_SET_PAGE + cnr); + if (IS_ERR(cl)) { + err = PTR_ERR(cl); goto err_clients; } + ee1004_set_page[cnr] = cl; } - } else if (i2c_adapter_id(client->adapter) != - i2c_adapter_id(ee1004_set_page[0]->adapter)) { + + /* Remember current page to avoid unneeded page select */ + err = ee1004_get_current_page(); + if (err < 0) + goto err_clients; + dev_dbg(&client->dev, "Currently selected page: %d\n", err); + ee1004_current_page = err; + } else if (client->adapter != ee1004_set_page[0]->adapter) { dev_err(&client->dev, "Driver only supports devices on a single I2C bus\n"); err = -EOPNOTSUPP; goto err_clients; } - - /* Remember current page to avoid unneeded page select */ - err = ee1004_get_current_page(); - if (err < 0) - goto err_clients; - ee1004_current_page = err; - dev_dbg(&client->dev, "Currently selected page: %d\n", - ee1004_current_page); mutex_unlock(&ee1004_bus_lock); - /* Create the sysfs eeprom file */ - err = sysfs_create_bin_file(&client->dev.kobj, &eeprom_attr); - if (err) - goto err_clients_lock; - dev_info(&client->dev, "%u byte EE1004-compliant SPD EEPROM, read-only\n", EE1004_EEPROM_SIZE); - if (slow) - dev_notice(&client->dev, - "Falling back to %s reads, performance will suffer\n", - slow); return 0; - err_clients_lock: - mutex_lock(&ee1004_bus_lock); err_clients: - if (--ee1004_dev_count == 0) { - for (cnr--; cnr >= 0; cnr--) { - i2c_unregister_device(ee1004_set_page[cnr]); - ee1004_set_page[cnr] = NULL; - } - } + ee1004_cleanup(cnr); mutex_unlock(&ee1004_bus_lock); return err; @@ -253,18 +218,9 @@ static int ee1004_probe(struct i2c_client *client, static int ee1004_remove(struct i2c_client *client) { - int i; - - sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr); - /* Remove page select clients if this is the last device */ mutex_lock(&ee1004_bus_lock); - if (--ee1004_dev_count == 0) { - for (i = 0; i < 2; i++) { - i2c_unregister_device(ee1004_set_page[i]); - ee1004_set_page[i] = NULL; - } - } + ee1004_cleanup(EE1004_NUM_PAGES); mutex_unlock(&ee1004_bus_lock); return 0; @@ -275,8 +231,9 @@ static int ee1004_remove(struct i2c_client *client) static struct i2c_driver ee1004_driver = { .driver = { .name = "ee1004", + .dev_groups = ee1004_groups, }, - .probe = ee1004_probe, + .probe_new = ee1004_probe, .remove = ee1004_remove, .id_table = ee1004_ids, }; diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index 80114f4c80ad..29d8971ec558 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -9,6 +9,7 @@ #include <linux/device.h> #include <linux/gpio/consumer.h> #include <linux/kernel.h> +#include <linux/log2.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/of.h> @@ -28,14 +29,29 @@ struct eeprom_93xx46_devtype_data { unsigned int quirks; + unsigned char flags; +}; + +static const struct eeprom_93xx46_devtype_data at93c46_data = { + .flags = EE_SIZE1K, +}; + +static const struct eeprom_93xx46_devtype_data at93c56_data = { + .flags = EE_SIZE2K, +}; + +static const struct eeprom_93xx46_devtype_data at93c66_data = { + .flags = EE_SIZE4K, }; static const struct eeprom_93xx46_devtype_data atmel_at93c46d_data = { + .flags = EE_SIZE1K, .quirks = EEPROM_93XX46_QUIRK_SINGLE_WORD_READ | EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH, }; static const struct eeprom_93xx46_devtype_data microchip_93lc46b_data = { + .flags = EE_SIZE1K, .quirks = EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE, }; @@ -70,6 +86,7 @@ static int eeprom_93xx46_read(void *priv, unsigned int off, struct eeprom_93xx46_dev *edev = priv; char *buf = val; int err = 0; + int bits; if (unlikely(off >= edev->size)) return 0; @@ -83,21 +100,21 @@ static int eeprom_93xx46_read(void *priv, unsigned int off, if (edev->pdata->prepare) edev->pdata->prepare(edev); + /* The opcode in front of the address is three bits. */ + bits = edev->addrlen + 3; + while (count) { struct spi_message m; struct spi_transfer t[2] = { { 0 } }; u16 cmd_addr = OP_READ << edev->addrlen; size_t nbytes = count; - int bits; - if (edev->addrlen == 7) { - cmd_addr |= off & 0x7f; - bits = 10; + if (edev->pdata->flags & EE_ADDR8) { + cmd_addr |= off; if (has_quirk_single_word_read(edev)) nbytes = 1; } else { - cmd_addr |= (off >> 1) & 0x3f; - bits = 9; + cmd_addr |= (off >> 1); if (has_quirk_single_word_read(edev)) nbytes = 2; } @@ -152,14 +169,14 @@ static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on) int bits, ret; u16 cmd_addr; + /* The opcode in front of the address is three bits. */ + bits = edev->addrlen + 3; + cmd_addr = OP_START << edev->addrlen; - if (edev->addrlen == 7) { + if (edev->pdata->flags & EE_ADDR8) cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS) << 1; - bits = 10; - } else { + else cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS); - bits = 9; - } if (has_quirk_instruction_length(edev)) { cmd_addr <<= 2; @@ -205,15 +222,19 @@ eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev, int bits, data_len, ret; u16 cmd_addr; + if (unlikely(off >= edev->size)) + return -EINVAL; + + /* The opcode in front of the address is three bits. */ + bits = edev->addrlen + 3; + cmd_addr = OP_WRITE << edev->addrlen; - if (edev->addrlen == 7) { - cmd_addr |= off & 0x7f; - bits = 10; + if (edev->pdata->flags & EE_ADDR8) { + cmd_addr |= off; data_len = 1; } else { - cmd_addr |= (off >> 1) & 0x3f; - bits = 9; + cmd_addr |= (off >> 1); data_len = 2; } @@ -253,7 +274,7 @@ static int eeprom_93xx46_write(void *priv, unsigned int off, return count; /* only write even number of bytes on 16-bit devices */ - if (edev->addrlen == 6) { + if (edev->pdata->flags & EE_ADDR16) { step = 2; count &= ~1; } @@ -295,14 +316,14 @@ static int eeprom_93xx46_eral(struct eeprom_93xx46_dev *edev) int bits, ret; u16 cmd_addr; + /* The opcode in front of the address is three bits. */ + bits = edev->addrlen + 3; + cmd_addr = OP_START << edev->addrlen; - if (edev->addrlen == 7) { + if (edev->pdata->flags & EE_ADDR8) cmd_addr |= ADDR_ERAL << 1; - bits = 10; - } else { + else cmd_addr |= ADDR_ERAL; - bits = 9; - } if (has_quirk_instruction_length(edev)) { cmd_addr <<= 2; @@ -375,8 +396,11 @@ static void select_deassert(void *context) } static const struct of_device_id eeprom_93xx46_of_table[] = { - { .compatible = "eeprom-93xx46", }, + { .compatible = "eeprom-93xx46", .data = &at93c46_data, }, + { .compatible = "atmel,at93c46", .data = &at93c46_data, }, { .compatible = "atmel,at93c46d", .data = &atmel_at93c46d_data, }, + { .compatible = "atmel,at93c56", .data = &at93c56_data, }, + { .compatible = "atmel,at93c66", .data = &at93c66_data, }, { .compatible = "microchip,93lc46b", .data = µchip_93lc46b_data, }, {} }; @@ -426,6 +450,7 @@ static int eeprom_93xx46_probe_dt(struct spi_device *spi) const struct eeprom_93xx46_devtype_data *data = of_id->data; pd->quirks = data->quirks; + pd->flags |= data->flags; } spi->dev.platform_data = pd; @@ -455,10 +480,21 @@ static int eeprom_93xx46_probe(struct spi_device *spi) if (!edev) return -ENOMEM; + if (pd->flags & EE_SIZE1K) + edev->size = 128; + else if (pd->flags & EE_SIZE2K) + edev->size = 256; + else if (pd->flags & EE_SIZE4K) + edev->size = 512; + else { + dev_err(&spi->dev, "unspecified size\n"); + return -EINVAL; + } + if (pd->flags & EE_ADDR8) - edev->addrlen = 7; + edev->addrlen = ilog2(edev->size); else if (pd->flags & EE_ADDR16) - edev->addrlen = 6; + edev->addrlen = ilog2(edev->size) - 1; else { dev_err(&spi->dev, "unspecified address type\n"); return -EINVAL; @@ -469,7 +505,6 @@ static int eeprom_93xx46_probe(struct spi_device *spi) edev->spi = spi; edev->pdata = pd; - edev->size = 128; edev->nvmem_config.type = NVMEM_TYPE_EEPROM; edev->nvmem_config.name = dev_name(&spi->dev); edev->nvmem_config.dev = &spi->dev; @@ -489,8 +524,9 @@ static int eeprom_93xx46_probe(struct spi_device *spi) if (IS_ERR(edev->nvmem)) return PTR_ERR(edev->nvmem); - dev_info(&spi->dev, "%d-bit eeprom %s\n", + dev_info(&spi->dev, "%d-bit eeprom containing %d bytes %s\n", (pd->flags & EE_ADDR8) ? 8 : 16, + edev->size, (pd->flags & EE_READONLY) ? "(readonly)" : ""); if (!(pd->flags & EE_READONLY)) { diff --git a/drivers/misc/eeprom/idt_89hpesx.c b/drivers/misc/eeprom/idt_89hpesx.c index 81c70e5bc168..b0cff4b152da 100644 --- a/drivers/misc/eeprom/idt_89hpesx.c +++ b/drivers/misc/eeprom/idt_89hpesx.c @@ -1,38 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-only /* - * This file is provided under a GPLv2 license. When using or - * redistributing this file, you may do so under that license. - * - * GPL LICENSE SUMMARY - * * Copyright (C) 2016 T-Platforms. All Rights Reserved. * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, it can be found <http://www.gnu.org/licenses/>. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * * IDT PCIe-switch NTB Linux driver * * Contact Information: @@ -1126,11 +1095,10 @@ static void idt_get_fw_data(struct idt_89hpesx_dev *pdev) device_for_each_child_node(dev, fwnode) { ee_id = idt_ee_match_id(fwnode); - if (!ee_id) { - dev_warn(dev, "Skip unsupported EEPROM device"); - continue; - } else + if (ee_id) break; + + dev_warn(dev, "Skip unsupported EEPROM device %pfw\n", fwnode); } /* If there is no fwnode EEPROM device, then set zero size */ @@ -1161,6 +1129,7 @@ static void idt_get_fw_data(struct idt_89hpesx_dev *pdev) else /* if (!fwnode_property_read_bool(node, "read-only")) */ pdev->eero = false; + fwnode_handle_put(fwnode); dev_info(dev, "EEPROM of %d bytes found by 0x%x", pdev->eesize, pdev->eeaddr); } diff --git a/drivers/misc/habanalabs/common/command_submission.c b/drivers/misc/habanalabs/common/command_submission.c index af3c497defb1..80c60fb41bbc 100644 --- a/drivers/misc/habanalabs/common/command_submission.c +++ b/drivers/misc/habanalabs/common/command_submission.c @@ -556,6 +556,13 @@ out: else if (!cs->submitted) cs->fence->error = -EBUSY; + if (unlikely(cs->skip_reset_on_timeout)) { + dev_err(hdev->dev, + "Command submission %llu completed after %llu (s)\n", + cs->sequence, + div_u64(jiffies - cs->submission_time_jiffies, HZ)); + } + if (cs->timestamp) cs->fence->timestamp = ktime_get(); complete_all(&cs->fence->completion); @@ -571,6 +578,8 @@ static void cs_timedout(struct work_struct *work) int rc; struct hl_cs *cs = container_of(work, struct hl_cs, work_tdr.work); + bool skip_reset_on_timeout = cs->skip_reset_on_timeout; + rc = cs_get_unless_zero(cs); if (!rc) return; @@ -581,7 +590,8 @@ static void cs_timedout(struct work_struct *work) } /* Mark the CS is timed out so we won't try to cancel its TDR */ - cs->timedout = true; + if (likely(!skip_reset_on_timeout)) + cs->timedout = true; hdev = cs->ctx->hdev; @@ -613,10 +623,12 @@ static void cs_timedout(struct work_struct *work) cs_put(cs); - if (hdev->reset_on_lockup) - hl_device_reset(hdev, 0); - else - hdev->needs_reset = true; + if (likely(!skip_reset_on_timeout)) { + if (hdev->reset_on_lockup) + hl_device_reset(hdev, HL_RESET_TDR); + else + hdev->needs_reset = true; + } } static int allocate_cs(struct hl_device *hdev, struct hl_ctx *ctx, @@ -650,6 +662,10 @@ static int allocate_cs(struct hl_device *hdev, struct hl_ctx *ctx, cs->type = cs_type; cs->timestamp = !!(flags & HL_CS_FLAGS_TIMESTAMP); cs->timeout_jiffies = timeout; + cs->skip_reset_on_timeout = + hdev->skip_reset_on_timeout || + !!(flags & HL_CS_FLAGS_SKIP_RESET_ON_TIMEOUT); + cs->submission_time_jiffies = jiffies; INIT_LIST_HEAD(&cs->job_list); INIT_DELAYED_WORK(&cs->work_tdr, cs_timedout); kref_init(&cs->refcount); @@ -1481,6 +1497,61 @@ out: return rc; } +/* + * hl_cs_signal_sob_wraparound_handler: handle SOB value wrapaound case. + * if the SOB value reaches the max value move to the other SOB reserved + * to the queue. + * Note that this function must be called while hw_queues_lock is taken. + */ +int hl_cs_signal_sob_wraparound_handler(struct hl_device *hdev, u32 q_idx, + struct hl_hw_sob **hw_sob, u32 count) +{ + struct hl_sync_stream_properties *prop; + struct hl_hw_sob *sob = *hw_sob, *other_sob; + u8 other_sob_offset; + + prop = &hdev->kernel_queues[q_idx].sync_stream_prop; + + kref_get(&sob->kref); + + /* check for wraparound */ + if (prop->next_sob_val + count >= HL_MAX_SOB_VAL) { + /* + * Decrement as we reached the max value. + * The release function won't be called here as we've + * just incremented the refcount right before calling this + * function. + */ + kref_put(&sob->kref, hl_sob_reset_error); + + /* + * check the other sob value, if it still in use then fail + * otherwise make the switch + */ + other_sob_offset = (prop->curr_sob_offset + 1) % HL_RSVD_SOBS; + other_sob = &prop->hw_sob[other_sob_offset]; + + if (kref_read(&other_sob->kref) != 1) { + dev_err(hdev->dev, "error: Cannot switch SOBs q_idx: %d\n", + q_idx); + return -EINVAL; + } + + prop->next_sob_val = 1; + + /* only two SOBs are currently in use */ + prop->curr_sob_offset = other_sob_offset; + *hw_sob = other_sob; + + dev_dbg(hdev->dev, "switched to SOB %d, q_idx: %d\n", + prop->curr_sob_offset, q_idx); + } else { + prop->next_sob_val += count; + } + + return 0; +} + static int cs_ioctl_extract_signal_seq(struct hl_device *hdev, struct hl_cs_chunk *chunk, u64 *signal_seq, struct hl_ctx *ctx) { diff --git a/drivers/misc/habanalabs/common/context.c b/drivers/misc/habanalabs/common/context.c index 62d705889ca8..19b6b045219e 100644 --- a/drivers/misc/habanalabs/common/context.c +++ b/drivers/misc/habanalabs/common/context.c @@ -12,7 +12,6 @@ static void hl_ctx_fini(struct hl_ctx *ctx) { struct hl_device *hdev = ctx->hdev; - u64 idle_mask[HL_BUSY_ENGINES_MASK_EXT_SIZE] = {0}; int i; /* Release all allocated pending cb's, those cb's were never @@ -57,14 +56,6 @@ static void hl_ctx_fini(struct hl_ctx *ctx) /* Scrub both SRAM and DRAM */ hdev->asic_funcs->scrub_device_mem(hdev, 0, 0); - - if ((!hdev->pldm) && (hdev->pdev) && - (!hdev->asic_funcs->is_device_idle(hdev, - idle_mask, - HL_BUSY_ENGINES_MASK_EXT_SIZE, NULL))) - dev_notice(hdev->dev, - "device not idle after user context is closed (0x%llx, 0x%llx)\n", - idle_mask[0], idle_mask[1]); } else { dev_dbg(hdev->dev, "closing kernel context\n"); hdev->asic_funcs->ctx_fini(ctx); diff --git a/drivers/misc/habanalabs/common/debugfs.c b/drivers/misc/habanalabs/common/debugfs.c index 8381155578a0..703d79fb6f3f 100644 --- a/drivers/misc/habanalabs/common/debugfs.c +++ b/drivers/misc/habanalabs/common/debugfs.c @@ -1278,6 +1278,11 @@ void hl_debugfs_add_device(struct hl_device *hdev) dev_entry->root, &dev_entry->blob_desc); + debugfs_create_x8("skip_reset_on_timeout", + 0644, + dev_entry->root, + &hdev->skip_reset_on_timeout); + for (i = 0, entry = dev_entry->entry_arr ; i < count ; i++, entry++) { debugfs_create_file(hl_debugfs_list[i].name, 0444, diff --git a/drivers/misc/habanalabs/common/device.c b/drivers/misc/habanalabs/common/device.c index 00e92b678828..ff4cbde289c0 100644 --- a/drivers/misc/habanalabs/common/device.c +++ b/drivers/misc/habanalabs/common/device.c @@ -51,6 +51,8 @@ bool hl_device_operational(struct hl_device *hdev, static void hpriv_release(struct kref *ref) { + u64 idle_mask[HL_BUSY_ENGINES_MASK_EXT_SIZE] = {0}; + bool device_is_idle = true; struct hl_fpriv *hpriv; struct hl_device *hdev; @@ -71,8 +73,20 @@ static void hpriv_release(struct kref *ref) kfree(hpriv); - if (hdev->reset_upon_device_release) - hl_device_reset(hdev, 0); + if ((!hdev->pldm) && (hdev->pdev) && + (!hdev->asic_funcs->is_device_idle(hdev, + idle_mask, + HL_BUSY_ENGINES_MASK_EXT_SIZE, NULL))) { + dev_err(hdev->dev, + "device not idle after user context is closed (0x%llx_%llx)\n", + idle_mask[1], idle_mask[0]); + + device_is_idle = false; + } + + if ((hdev->reset_if_device_not_idle && !device_is_idle) + || hdev->reset_upon_device_release) + hl_device_reset(hdev, HL_RESET_DEVICE_RELEASE); } void hl_hpriv_get(struct hl_fpriv *hpriv) @@ -118,6 +132,9 @@ static int hl_device_release(struct inode *inode, struct file *filp) dev_warn(hdev->dev, "Device is still in use because there are live CS and/or memory mappings\n"); + hdev->last_open_session_duration_jif = + jiffies - hdev->last_successful_open_jif; + return 0; } @@ -868,7 +885,7 @@ static void device_disable_open_processes(struct hl_device *hdev) int hl_device_reset(struct hl_device *hdev, u32 flags) { u64 idle_mask[HL_BUSY_ENGINES_MASK_EXT_SIZE] = {0}; - bool hard_reset, from_hard_reset_thread; + bool hard_reset, from_hard_reset_thread, hard_instead_soft = false; int i, rc; if (!hdev->init_done) { @@ -880,11 +897,28 @@ int hl_device_reset(struct hl_device *hdev, u32 flags) hard_reset = (flags & HL_RESET_HARD) != 0; from_hard_reset_thread = (flags & HL_RESET_FROM_RESET_THREAD) != 0; - if ((!hard_reset) && (!hdev->supports_soft_reset)) { - dev_dbg(hdev->dev, "Doing hard-reset instead of soft-reset\n"); + if (!hard_reset && !hdev->supports_soft_reset) { + hard_instead_soft = true; + hard_reset = true; + } + + if (hdev->reset_upon_device_release && + (flags & HL_RESET_DEVICE_RELEASE)) { + dev_dbg(hdev->dev, + "Perform %s-reset upon device release\n", + hard_reset ? "hard" : "soft"); + goto do_reset; + } + + if (!hard_reset && !hdev->allow_external_soft_reset) { + hard_instead_soft = true; hard_reset = true; } + if (hard_instead_soft) + dev_dbg(hdev->dev, "Doing hard-reset instead of soft-reset\n"); + +do_reset: /* Re-entry of reset thread */ if (from_hard_reset_thread && hdev->process_kill_trial_cnt) goto kill_processes; @@ -901,6 +935,19 @@ int hl_device_reset(struct hl_device *hdev, u32 flags) return 0; /* + * 'reset cause' is being updated here, because getting here + * means that it's the 1st time and the last time we're here + * ('in_reset' makes sure of it). This makes sure that + * 'reset_cause' will continue holding its 1st recorded reason! + */ + if (flags & HL_RESET_HEARTBEAT) + hdev->curr_reset_cause = HL_RESET_CAUSE_HEARTBEAT; + else if (flags & HL_RESET_TDR) + hdev->curr_reset_cause = HL_RESET_CAUSE_TDR; + else + hdev->curr_reset_cause = HL_RESET_CAUSE_UNKNOWN; + + /* * if reset is due to heartbeat, device CPU is no responsive in * which case no point sending PCI disable message to it */ @@ -943,9 +990,8 @@ again: hdev->process_kill_trial_cnt = 0; /* - * Because the reset function can't run from interrupt or - * from heartbeat work, we need to call the reset function - * from a dedicated work + * Because the reset function can't run from heartbeat work, + * we need to call the reset function from a dedicated work. */ queue_delayed_work(hdev->device_reset_work.wq, &hdev->device_reset_work.reset_work, 0); @@ -1096,8 +1142,8 @@ kill_processes: if (!hdev->asic_funcs->is_device_idle(hdev, idle_mask, HL_BUSY_ENGINES_MASK_EXT_SIZE, NULL)) { dev_err(hdev->dev, - "device is not idle (mask %#llx %#llx) after reset\n", - idle_mask[0], idle_mask[1]); + "device is not idle (mask 0x%llx_%llx) after reset\n", + idle_mask[1], idle_mask[0]); rc = -EIO; goto out_err; } @@ -1334,8 +1380,9 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass) } /* - * From this point, in case of an error, add char devices and create - * sysfs nodes as part of the error flow, to allow debugging. + * From this point, override rc (=0) in case of an error to allow + * debugging (by adding char devices and create sysfs nodes as part of + * the error flow). */ add_cdev_sysfs_on_err = true; @@ -1369,7 +1416,7 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass) dev_info(hdev->dev, "Found %s device with %lluGB DRAM\n", hdev->asic_name, - hdev->asic_prop.dram_size / 1024 / 1024 / 1024); + hdev->asic_prop.dram_size / SZ_1G); rc = hl_vm_init(hdev); if (rc) { @@ -1475,6 +1522,7 @@ out_disabled: void hl_device_fini(struct hl_device *hdev) { ktime_t timeout; + u64 reset_sec; int i, rc; dev_info(hdev->dev, "Removing device\n"); @@ -1482,6 +1530,11 @@ void hl_device_fini(struct hl_device *hdev) hdev->device_fini_pending = 1; flush_delayed_work(&hdev->device_reset_work.reset_work); + if (hdev->pldm) + reset_sec = HL_PLDM_HARD_RESET_MAX_TIMEOUT; + else + reset_sec = HL_HARD_RESET_MAX_TIMEOUT; + /* * This function is competing with the reset function, so try to * take the reset atomic and if we are already in middle of reset, @@ -1490,8 +1543,7 @@ void hl_device_fini(struct hl_device *hdev) * ports, the hard reset could take between 10-30 seconds */ - timeout = ktime_add_us(ktime_get(), - HL_HARD_RESET_MAX_TIMEOUT * 1000 * 1000); + timeout = ktime_add_us(ktime_get(), reset_sec * 1000 * 1000); rc = atomic_cmpxchg(&hdev->in_reset, 0, 1); while (rc) { usleep_range(50, 200); diff --git a/drivers/misc/habanalabs/common/firmware_if.c b/drivers/misc/habanalabs/common/firmware_if.c index 0713b2c12d54..2e4d04ec6b53 100644 --- a/drivers/misc/habanalabs/common/firmware_if.c +++ b/drivers/misc/habanalabs/common/firmware_if.c @@ -9,42 +9,63 @@ #include "../include/common/hl_boot_if.h" #include <linux/firmware.h> +#include <linux/crc32.h> #include <linux/slab.h> +#include <linux/ctype.h> -#define FW_FILE_MAX_SIZE 0x1400000 /* maximum size of 20MB */ -/** - * hl_fw_load_fw_to_device() - Load F/W code to device's memory. - * - * @hdev: pointer to hl_device structure. - * @fw_name: the firmware image name - * @dst: IO memory mapped address space to copy firmware to - * @src_offset: offset in src FW to copy from - * @size: amount of bytes to copy (0 to copy the whole binary) - * - * Copy fw code from firmware file to device memory. - * - * Return: 0 on success, non-zero for failure. - */ -int hl_fw_load_fw_to_device(struct hl_device *hdev, const char *fw_name, - void __iomem *dst, u32 src_offset, u32 size) +#define FW_FILE_MAX_SIZE 0x1400000 /* maximum size of 20MB */ + +#define FW_CPU_STATUS_POLL_INTERVAL_USEC 10000 + +static char *extract_fw_ver_from_str(const char *fw_str) +{ + char *str, *fw_ver, *whitespace; + + fw_ver = kmalloc(16, GFP_KERNEL); + if (!fw_ver) + return NULL; + + str = strnstr(fw_str, "fw-", VERSION_MAX_LEN); + if (!str) + goto free_fw_ver; + + /* Skip the fw- part */ + str += 3; + + /* Copy until the next whitespace */ + whitespace = strnstr(str, " ", 15); + if (!whitespace) + goto free_fw_ver; + + strscpy(fw_ver, str, whitespace - str + 1); + + return fw_ver; + +free_fw_ver: + kfree(fw_ver); + return NULL; +} + +static int hl_request_fw(struct hl_device *hdev, + const struct firmware **firmware_p, + const char *fw_name) { - const struct firmware *fw; - const void *fw_data; size_t fw_size; int rc; - rc = request_firmware(&fw, fw_name, hdev->dev); + rc = request_firmware(firmware_p, fw_name, hdev->dev); if (rc) { - dev_err(hdev->dev, "Firmware file %s is not found!\n", fw_name); + dev_err(hdev->dev, "Firmware file %s is not found! (error %d)\n", + fw_name, rc); goto out; } - fw_size = fw->size; + fw_size = (*firmware_p)->size; if ((fw_size % 4) != 0) { dev_err(hdev->dev, "Illegal %s firmware size %zu\n", - fw_name, fw_size); + fw_name, fw_size); rc = -EINVAL; - goto out; + goto release_fw; } dev_dbg(hdev->dev, "%s firmware size == %zu\n", fw_name, fw_size); @@ -54,26 +75,125 @@ int hl_fw_load_fw_to_device(struct hl_device *hdev, const char *fw_name, "FW file size %zu exceeds maximum of %u bytes\n", fw_size, FW_FILE_MAX_SIZE); rc = -EINVAL; - goto out; + goto release_fw; } - if (size - src_offset > fw_size) { + return 0; + +release_fw: + release_firmware(*firmware_p); +out: + return rc; +} + +/** + * hl_release_firmware() - release FW + * + * @fw: fw descriptor + * + * note: this inline function added to serve as a comprehensive mirror for the + * hl_request_fw function. + */ +static inline void hl_release_firmware(const struct firmware *fw) +{ + release_firmware(fw); +} + +/** + * hl_fw_copy_fw_to_device() - copy FW to device + * + * @hdev: pointer to hl_device structure. + * @fw: fw descriptor + * @dst: IO memory mapped address space to copy firmware to + * @src_offset: offset in src FW to copy from + * @size: amount of bytes to copy (0 to copy the whole binary) + * + * actual copy of FW binary data to device, shared by static and dynamic loaders + */ +static int hl_fw_copy_fw_to_device(struct hl_device *hdev, + const struct firmware *fw, void __iomem *dst, + u32 src_offset, u32 size) +{ + const void *fw_data; + + /* size 0 indicates to copy the whole file */ + if (!size) + size = fw->size; + + if (src_offset + size > fw->size) { dev_err(hdev->dev, "size to copy(%u) and offset(%u) are invalid\n", size, src_offset); - rc = -EINVAL; - goto out; + return -EINVAL; } - if (size) - fw_size = size; - fw_data = (const void *) fw->data; - memcpy_toio(dst, fw_data + src_offset, fw_size); + memcpy_toio(dst, fw_data + src_offset, size); + return 0; +} -out: - release_firmware(fw); +/** + * hl_fw_copy_msg_to_device() - copy message to device + * + * @hdev: pointer to hl_device structure. + * @msg: message + * @dst: IO memory mapped address space to copy firmware to + * @src_offset: offset in src message to copy from + * @size: amount of bytes to copy (0 to copy the whole binary) + * + * actual copy of message data to device. + */ +static int hl_fw_copy_msg_to_device(struct hl_device *hdev, + struct lkd_msg_comms *msg, void __iomem *dst, + u32 src_offset, u32 size) +{ + void *msg_data; + + /* size 0 indicates to copy the whole file */ + if (!size) + size = sizeof(struct lkd_msg_comms); + + if (src_offset + size > sizeof(struct lkd_msg_comms)) { + dev_err(hdev->dev, + "size to copy(%u) and offset(%u) are invalid\n", + size, src_offset); + return -EINVAL; + } + + msg_data = (void *) msg; + + memcpy_toio(dst, msg_data + src_offset, size); + + return 0; +} + +/** + * hl_fw_load_fw_to_device() - Load F/W code to device's memory. + * + * @hdev: pointer to hl_device structure. + * @fw_name: the firmware image name + * @dst: IO memory mapped address space to copy firmware to + * @src_offset: offset in src FW to copy from + * @size: amount of bytes to copy (0 to copy the whole binary) + * + * Copy fw code from firmware file to device memory. + * + * Return: 0 on success, non-zero for failure. + */ +int hl_fw_load_fw_to_device(struct hl_device *hdev, const char *fw_name, + void __iomem *dst, u32 src_offset, u32 size) +{ + const struct firmware *fw; + int rc; + + rc = hl_request_fw(hdev, &fw, fw_name); + if (rc) + return rc; + + rc = hl_fw_copy_fw_to_device(hdev, fw, dst, src_offset, size); + + hl_release_firmware(fw); return rc; } @@ -91,6 +211,7 @@ int hl_fw_send_cpu_message(struct hl_device *hdev, u32 hw_queue_id, u32 *msg, u16 len, u32 timeout, u64 *result) { struct hl_hw_queue *queue = &hdev->kernel_queues[hw_queue_id]; + struct asic_fixed_properties *prop = &hdev->asic_prop; struct cpucp_packet *pkt; dma_addr_t pkt_dma_addr; u32 tmp, expected_ack_val; @@ -117,7 +238,7 @@ int hl_fw_send_cpu_message(struct hl_device *hdev, u32 hw_queue_id, u32 *msg, } /* set fence to a non valid value */ - pkt->fence = UINT_MAX; + pkt->fence = cpu_to_le32(UINT_MAX); rc = hl_hw_queue_send_cb_no_cmpl(hdev, hw_queue_id, len, pkt_dma_addr); if (rc) { @@ -125,8 +246,7 @@ int hl_fw_send_cpu_message(struct hl_device *hdev, u32 hw_queue_id, u32 *msg, goto out; } - if (hdev->asic_prop.fw_app_security_map & - CPU_BOOT_DEV_STS0_PKT_PI_ACK_EN) + if (prop->fw_app_cpu_boot_dev_sts0 & CPU_BOOT_DEV_STS0_PKT_PI_ACK_EN) expected_ack_val = queue->pi; else expected_ack_val = CPUCP_PACKET_FENCE_VAL; @@ -272,10 +392,11 @@ void hl_fw_cpu_accessible_dma_pool_free(struct hl_device *hdev, size_t size, int hl_fw_send_heartbeat(struct hl_device *hdev) { - struct cpucp_packet hb_pkt = {}; + struct cpucp_packet hb_pkt; u64 result; int rc; + memset(&hb_pkt, 0, sizeof(hb_pkt)); hb_pkt.ctl = cpu_to_le32(CPUCP_PACKET_TEST << CPUCP_PKT_CTL_OPCODE_SHIFT); hb_pkt.value = cpu_to_le64(CPUCP_PACKET_FENCE_VAL); @@ -284,29 +405,24 @@ int hl_fw_send_heartbeat(struct hl_device *hdev) sizeof(hb_pkt), 0, &result); if ((rc) || (result != CPUCP_PACKET_FENCE_VAL)) + return -EIO; + + if (le32_to_cpu(hb_pkt.status_mask) & + CPUCP_PKT_HB_STATUS_EQ_FAULT_MASK) { + dev_warn(hdev->dev, "FW reported EQ fault during heartbeat\n"); rc = -EIO; + } return rc; } -static int fw_read_errors(struct hl_device *hdev, u32 boot_err0_reg, - u32 cpu_security_boot_status_reg) +static bool fw_report_boot_dev0(struct hl_device *hdev, u32 err_val, + u32 sts_val) { - u32 err_val, security_val; bool err_exists = false; - /* Some of the firmware status codes are deprecated in newer f/w - * versions. In those versions, the errors are reported - * in different registers. Therefore, we need to check those - * registers and print the exact errors. Moreover, there - * may be multiple errors, so we need to report on each error - * separately. Some of the error codes might indicate a state - * that is not an error per-se, but it is an error in production - * environment - */ - err_val = RREG32(boot_err0_reg); if (!(err_val & CPU_BOOT_ERR0_ENABLED)) - return 0; + return false; if (err_val & CPU_BOOT_ERR0_DRAM_INIT_FAIL) { dev_err(hdev->dev, @@ -377,44 +493,120 @@ static int fw_read_errors(struct hl_device *hdev, u32 boot_err0_reg, err_exists = true; } + if (err_val & CPU_BOOT_ERR0_PRI_IMG_VER_FAIL) { + dev_warn(hdev->dev, + "Device boot warning - Failed to load preboot primary image\n"); + /* This is a warning so we don't want it to disable the + * device as we have a secondary preboot image + */ + err_val &= ~CPU_BOOT_ERR0_PRI_IMG_VER_FAIL; + } + + if (err_val & CPU_BOOT_ERR0_SEC_IMG_VER_FAIL) { + dev_err(hdev->dev, "Device boot error - Failed to load preboot secondary image\n"); + err_exists = true; + } + if (err_val & CPU_BOOT_ERR0_PLL_FAIL) { dev_err(hdev->dev, "Device boot error - PLL failure\n"); err_exists = true; } if (err_val & CPU_BOOT_ERR0_DEVICE_UNUSABLE_FAIL) { - dev_err(hdev->dev, - "Device boot error - device unusable\n"); - err_exists = true; + /* Ignore this bit, don't prevent driver loading */ + dev_dbg(hdev->dev, "device unusable status is set\n"); + err_val &= ~CPU_BOOT_ERR0_DEVICE_UNUSABLE_FAIL; } - security_val = RREG32(cpu_security_boot_status_reg); - if (security_val & CPU_BOOT_DEV_STS0_ENABLED) - dev_dbg(hdev->dev, "Device security status %#x\n", - security_val); + if (sts_val & CPU_BOOT_DEV_STS0_ENABLED) + dev_dbg(hdev->dev, "Device status0 %#x\n", sts_val); if (!err_exists && (err_val & ~CPU_BOOT_ERR0_ENABLED)) { dev_err(hdev->dev, - "Device boot error - unknown error 0x%08x\n", - err_val); + "Device boot error - unknown ERR0 error 0x%08x\n", err_val); err_exists = true; } + /* return error only if it's in the predefined mask */ if (err_exists && ((err_val & ~CPU_BOOT_ERR0_ENABLED) & lower_32_bits(hdev->boot_error_status_mask))) + return true; + + return false; +} + +/* placeholder for ERR1 as no errors defined there yet */ +static bool fw_report_boot_dev1(struct hl_device *hdev, u32 err_val, + u32 sts_val) +{ + /* + * keep this variable to preserve the logic of the function. + * this way it would require less modifications when error will be + * added to DEV_ERR1 + */ + bool err_exists = false; + + if (!(err_val & CPU_BOOT_ERR1_ENABLED)) + return false; + + if (sts_val & CPU_BOOT_DEV_STS1_ENABLED) + dev_dbg(hdev->dev, "Device status1 %#x\n", sts_val); + + if (!err_exists && (err_val & ~CPU_BOOT_ERR1_ENABLED)) { + dev_err(hdev->dev, + "Device boot error - unknown ERR1 error 0x%08x\n", + err_val); + err_exists = true; + } + + /* return error only if it's in the predefined mask */ + if (err_exists && ((err_val & ~CPU_BOOT_ERR1_ENABLED) & + upper_32_bits(hdev->boot_error_status_mask))) + return true; + + return false; +} + +static int fw_read_errors(struct hl_device *hdev, u32 boot_err0_reg, + u32 boot_err1_reg, u32 cpu_boot_dev_status0_reg, + u32 cpu_boot_dev_status1_reg) +{ + u32 err_val, status_val; + bool err_exists = false; + + /* Some of the firmware status codes are deprecated in newer f/w + * versions. In those versions, the errors are reported + * in different registers. Therefore, we need to check those + * registers and print the exact errors. Moreover, there + * may be multiple errors, so we need to report on each error + * separately. Some of the error codes might indicate a state + * that is not an error per-se, but it is an error in production + * environment + */ + err_val = RREG32(boot_err0_reg); + status_val = RREG32(cpu_boot_dev_status0_reg); + err_exists = fw_report_boot_dev0(hdev, err_val, status_val); + + err_val = RREG32(boot_err1_reg); + status_val = RREG32(cpu_boot_dev_status1_reg); + err_exists |= fw_report_boot_dev1(hdev, err_val, status_val); + + if (err_exists) return -EIO; return 0; } int hl_fw_cpucp_info_get(struct hl_device *hdev, - u32 cpu_security_boot_status_reg, - u32 boot_err0_reg) + u32 sts_boot_dev_sts0_reg, + u32 sts_boot_dev_sts1_reg, u32 boot_err0_reg, + u32 boot_err1_reg) { struct asic_fixed_properties *prop = &hdev->asic_prop; struct cpucp_packet pkt = {}; - void *cpucp_info_cpu_addr; dma_addr_t cpucp_info_dma_addr; + void *cpucp_info_cpu_addr; + char *kernel_ver; u64 result; int rc; @@ -443,7 +635,8 @@ int hl_fw_cpucp_info_get(struct hl_device *hdev, goto out; } - rc = fw_read_errors(hdev, boot_err0_reg, cpu_security_boot_status_reg); + rc = fw_read_errors(hdev, boot_err0_reg, boot_err1_reg, + sts_boot_dev_sts0_reg, sts_boot_dev_sts1_reg); if (rc) { dev_err(hdev->dev, "Errors in device boot\n"); goto out; @@ -460,10 +653,27 @@ int hl_fw_cpucp_info_get(struct hl_device *hdev, goto out; } + kernel_ver = extract_fw_ver_from_str(prop->cpucp_info.kernel_version); + if (kernel_ver) { + dev_info(hdev->dev, "Linux version %s", kernel_ver); + kfree(kernel_ver); + } + + /* assume EQ code doesn't need to check eqe index */ + hdev->event_queue.check_eqe_index = false; + /* Read FW application security bits again */ - if (hdev->asic_prop.fw_security_status_valid) - hdev->asic_prop.fw_app_security_map = - RREG32(cpu_security_boot_status_reg); + if (hdev->asic_prop.fw_cpu_boot_dev_sts0_valid) { + hdev->asic_prop.fw_app_cpu_boot_dev_sts0 = + RREG32(sts_boot_dev_sts0_reg); + if (hdev->asic_prop.fw_app_cpu_boot_dev_sts0 & + CPU_BOOT_DEV_STS0_EQ_INDEX_EN) + hdev->event_queue.check_eqe_index = true; + } + + if (hdev->asic_prop.fw_cpu_boot_dev_sts1_valid) + hdev->asic_prop.fw_app_cpu_boot_dev_sts1 = + RREG32(sts_boot_dev_sts1_reg); out: hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev, @@ -501,7 +711,8 @@ static int hl_fw_send_msi_info_msg(struct hl_device *hdev) pkt->length = cpu_to_le32(CPUCP_NUM_OF_MSI_TYPES); - hdev->asic_funcs->get_msi_info((u32 *)&pkt->data); + memset((void *) &pkt->data, 0xFF, data_size); + hdev->asic_funcs->get_msi_info(pkt->data); pkt->cpucp_pkt.ctl = cpu_to_le32(CPUCP_PACKET_MSI_INFO_SET << CPUCP_PKT_CTL_OPCODE_SHIFT); @@ -526,13 +737,15 @@ static int hl_fw_send_msi_info_msg(struct hl_device *hdev) } int hl_fw_cpucp_handshake(struct hl_device *hdev, - u32 cpu_security_boot_status_reg, - u32 boot_err0_reg) + u32 sts_boot_dev_sts0_reg, + u32 sts_boot_dev_sts1_reg, u32 boot_err0_reg, + u32 boot_err1_reg) { int rc; - rc = hl_fw_cpucp_info_get(hdev, cpu_security_boot_status_reg, - boot_err0_reg); + rc = hl_fw_cpucp_info_get(hdev, sts_boot_dev_sts0_reg, + sts_boot_dev_sts1_reg, boot_err0_reg, + boot_err1_reg); if (rc) return rc; @@ -667,8 +880,8 @@ int get_used_pll_index(struct hl_device *hdev, u32 input_pll_index, bool dynamic_pll; int fw_pll_idx; - dynamic_pll = prop->fw_security_status_valid && - (prop->fw_app_security_map & CPU_BOOT_DEV_STS0_DYN_PLL_EN); + dynamic_pll = !!(prop->fw_app_cpu_boot_dev_sts0 & + CPU_BOOT_DEV_STS0_DYN_PLL_EN); if (!dynamic_pll) { /* @@ -759,6 +972,47 @@ int hl_fw_cpucp_power_get(struct hl_device *hdev, u64 *power) return rc; } +void hl_fw_ask_hard_reset_without_linux(struct hl_device *hdev) +{ + struct static_fw_load_mgr *static_loader = + &hdev->fw_loader.static_loader; + int rc; + + if (hdev->asic_prop.dynamic_fw_load) { + rc = hl_fw_dynamic_send_protocol_cmd(hdev, &hdev->fw_loader, + COMMS_RST_DEV, 0, false, + hdev->fw_loader.cpu_timeout); + if (rc) + dev_warn(hdev->dev, "Failed sending COMMS_RST_DEV\n"); + } else { + WREG32(static_loader->kmd_msg_to_cpu_reg, KMD_MSG_RST_DEV); + } +} + +void hl_fw_ask_halt_machine_without_linux(struct hl_device *hdev) +{ + struct static_fw_load_mgr *static_loader = + &hdev->fw_loader.static_loader; + int rc; + + if (hdev->device_cpu_is_halted) + return; + + /* Stop device CPU to make sure nothing bad happens */ + if (hdev->asic_prop.dynamic_fw_load) { + rc = hl_fw_dynamic_send_protocol_cmd(hdev, &hdev->fw_loader, + COMMS_GOTO_WFE, 0, true, + hdev->fw_loader.cpu_timeout); + if (rc) + dev_warn(hdev->dev, "Failed sending COMMS_GOTO_WFE\n"); + } else { + WREG32(static_loader->kmd_msg_to_cpu_reg, KMD_MSG_GOTO_WFE); + msleep(static_loader->cpu_reset_wait_msec); + } + + hdev->device_cpu_is_halted = true; +} + static void detect_cpu_boot_status(struct hl_device *hdev, u32 status) { /* Some of the status codes below are deprecated in newer f/w @@ -767,63 +1021,59 @@ static void detect_cpu_boot_status(struct hl_device *hdev, u32 status) switch (status) { case CPU_BOOT_STATUS_NA: dev_err(hdev->dev, - "Device boot error - BTL did NOT run\n"); + "Device boot progress - BTL did NOT run\n"); break; case CPU_BOOT_STATUS_IN_WFE: dev_err(hdev->dev, - "Device boot error - Stuck inside WFE loop\n"); + "Device boot progress - Stuck inside WFE loop\n"); break; case CPU_BOOT_STATUS_IN_BTL: dev_err(hdev->dev, - "Device boot error - Stuck in BTL\n"); + "Device boot progress - Stuck in BTL\n"); break; case CPU_BOOT_STATUS_IN_PREBOOT: dev_err(hdev->dev, - "Device boot error - Stuck in Preboot\n"); + "Device boot progress - Stuck in Preboot\n"); break; case CPU_BOOT_STATUS_IN_SPL: dev_err(hdev->dev, - "Device boot error - Stuck in SPL\n"); + "Device boot progress - Stuck in SPL\n"); break; case CPU_BOOT_STATUS_IN_UBOOT: dev_err(hdev->dev, - "Device boot error - Stuck in u-boot\n"); + "Device boot progress - Stuck in u-boot\n"); break; case CPU_BOOT_STATUS_DRAM_INIT_FAIL: dev_err(hdev->dev, - "Device boot error - DRAM initialization failed\n"); + "Device boot progress - DRAM initialization failed\n"); break; case CPU_BOOT_STATUS_UBOOT_NOT_READY: dev_err(hdev->dev, - "Device boot error - u-boot stopped by user\n"); + "Device boot progress - Cannot boot\n"); break; case CPU_BOOT_STATUS_TS_INIT_FAIL: dev_err(hdev->dev, - "Device boot error - Thermal Sensor initialization failed\n"); + "Device boot progress - Thermal Sensor initialization failed\n"); break; default: dev_err(hdev->dev, - "Device boot error - Invalid status code %d\n", + "Device boot progress - Invalid status code %d\n", status); break; } } -int hl_fw_read_preboot_status(struct hl_device *hdev, u32 cpu_boot_status_reg, - u32 cpu_security_boot_status_reg, u32 boot_err0_reg, - u32 timeout) +static int hl_fw_read_preboot_caps(struct hl_device *hdev, + u32 cpu_boot_status_reg, + u32 sts_boot_dev_sts0_reg, + u32 sts_boot_dev_sts1_reg, + u32 boot_err0_reg, u32 boot_err1_reg, + u32 timeout) { struct asic_fixed_properties *prop = &hdev->asic_prop; - u32 status, security_status; + u32 status, reg_val; int rc; - /* pldm was added for cases in which we use preboot on pldm and want - * to load boot fit, but we can't wait for preboot because it runs - * very slowly - */ - if (!(hdev->fw_components & FW_TYPE_PREBOOT_CPU) || hdev->pldm) - return 0; - /* Need to check two possible scenarios: * * CPU_BOOT_STATUS_WAITING_FOR_BOOT_FIT - for newer firmwares where @@ -842,29 +1092,145 @@ int hl_fw_read_preboot_status(struct hl_device *hdev, u32 cpu_boot_status_reg, (status == CPU_BOOT_STATUS_READY_TO_BOOT) || (status == CPU_BOOT_STATUS_SRAM_AVAIL) || (status == CPU_BOOT_STATUS_WAITING_FOR_BOOT_FIT), - 10000, + FW_CPU_STATUS_POLL_INTERVAL_USEC, timeout); if (rc) { - dev_err(hdev->dev, "Failed to read preboot version\n"); + dev_err(hdev->dev, "CPU boot ready status timeout\n"); detect_cpu_boot_status(hdev, status); /* If we read all FF, then something is totally wrong, no point * of reading specific errors */ if (status != -1) - fw_read_errors(hdev, boot_err0_reg, - cpu_security_boot_status_reg); + fw_read_errors(hdev, boot_err0_reg, boot_err1_reg, + sts_boot_dev_sts0_reg, + sts_boot_dev_sts1_reg); return -EIO; } - rc = hdev->asic_funcs->read_device_fw_version(hdev, FW_COMP_PREBOOT); - if (rc) - return rc; + /* + * the registers DEV_STS* contain FW capabilities/features. + * We can rely on this registers only if bit CPU_BOOT_DEV_STS*_ENABLED + * is set. + * In the first read of this register we store the value of this + * register ONLY if the register is enabled (which will be propagated + * to next stages) and also mark the register as valid. + * In case it is not enabled the stored value will be left 0- all + * caps/features are off + */ + reg_val = RREG32(sts_boot_dev_sts0_reg); + if (reg_val & CPU_BOOT_DEV_STS0_ENABLED) { + prop->fw_cpu_boot_dev_sts0_valid = true; + prop->fw_preboot_cpu_boot_dev_sts0 = reg_val; + } + + reg_val = RREG32(sts_boot_dev_sts1_reg); + if (reg_val & CPU_BOOT_DEV_STS1_ENABLED) { + prop->fw_cpu_boot_dev_sts1_valid = true; + prop->fw_preboot_cpu_boot_dev_sts1 = reg_val; + } - security_status = RREG32(cpu_security_boot_status_reg); + prop->dynamic_fw_load = !!(prop->fw_preboot_cpu_boot_dev_sts0 & + CPU_BOOT_DEV_STS0_FW_LD_COM_EN); + + /* initialize FW loader once we know what load protocol is used */ + hdev->asic_funcs->init_firmware_loader(hdev); + + dev_dbg(hdev->dev, "Attempting %s FW load\n", + prop->dynamic_fw_load ? "dynamic" : "legacy"); + return 0; +} - /* We read security status multiple times during boot: +static int hl_fw_static_read_device_fw_version(struct hl_device *hdev, + enum hl_fw_component fwc) +{ + struct asic_fixed_properties *prop = &hdev->asic_prop; + struct fw_load_mgr *fw_loader = &hdev->fw_loader; + struct static_fw_load_mgr *static_loader; + char *dest, *boot_ver, *preboot_ver; + u32 ver_off, limit; + const char *name; + char btl_ver[32]; + + static_loader = &hdev->fw_loader.static_loader; + + switch (fwc) { + case FW_COMP_BOOT_FIT: + ver_off = RREG32(static_loader->boot_fit_version_offset_reg); + dest = prop->uboot_ver; + name = "Boot-fit"; + limit = static_loader->boot_fit_version_max_off; + break; + case FW_COMP_PREBOOT: + ver_off = RREG32(static_loader->preboot_version_offset_reg); + dest = prop->preboot_ver; + name = "Preboot"; + limit = static_loader->preboot_version_max_off; + break; + default: + dev_warn(hdev->dev, "Undefined FW component: %d\n", fwc); + return -EIO; + } + + ver_off &= static_loader->sram_offset_mask; + + if (ver_off < limit) { + memcpy_fromio(dest, + hdev->pcie_bar[fw_loader->sram_bar_id] + ver_off, + VERSION_MAX_LEN); + } else { + dev_err(hdev->dev, "%s version offset (0x%x) is above SRAM\n", + name, ver_off); + strscpy(dest, "unavailable", VERSION_MAX_LEN); + return -EIO; + } + + if (fwc == FW_COMP_BOOT_FIT) { + boot_ver = extract_fw_ver_from_str(prop->uboot_ver); + if (boot_ver) { + dev_info(hdev->dev, "boot-fit version %s\n", boot_ver); + kfree(boot_ver); + } + } else if (fwc == FW_COMP_PREBOOT) { + preboot_ver = strnstr(prop->preboot_ver, "Preboot", + VERSION_MAX_LEN); + if (preboot_ver && preboot_ver != prop->preboot_ver) { + strscpy(btl_ver, prop->preboot_ver, + min((int) (preboot_ver - prop->preboot_ver), + 31)); + dev_info(hdev->dev, "%s\n", btl_ver); + } + + preboot_ver = extract_fw_ver_from_str(prop->preboot_ver); + if (preboot_ver) { + dev_info(hdev->dev, "preboot version %s\n", + preboot_ver); + kfree(preboot_ver); + } + } + + return 0; +} + +/** + * hl_fw_preboot_update_state - update internal data structures during + * handshake with preboot + * + * + * @hdev: pointer to the habanalabs device structure + * + * @return 0 on success, otherwise non-zero error code + */ +static void hl_fw_preboot_update_state(struct hl_device *hdev) +{ + struct asic_fixed_properties *prop = &hdev->asic_prop; + u32 cpu_boot_dev_sts0, cpu_boot_dev_sts1; + + cpu_boot_dev_sts0 = prop->fw_preboot_cpu_boot_dev_sts0; + cpu_boot_dev_sts1 = prop->fw_preboot_cpu_boot_dev_sts1; + + /* We read boot_dev_sts registers multiple times during boot: * 1. preboot - a. Check whether the security status bits are valid * b. Check whether fw security is enabled * c. Check whether hard reset is done by preboot @@ -874,48 +1240,1121 @@ int hl_fw_read_preboot_status(struct hl_device *hdev, u32 cpu_boot_status_reg, * b. Check whether hard reset is done by fw app * * Preboot: - * Check security status bit (CPU_BOOT_DEV_STS0_ENABLED), if it is set + * Check security status bit (CPU_BOOT_DEV_STS0_ENABLED). If set, then- * check security enabled bit (CPU_BOOT_DEV_STS0_SECURITY_EN) + * If set, then mark GIC controller to be disabled. */ - if (security_status & CPU_BOOT_DEV_STS0_ENABLED) { - prop->fw_security_status_valid = 1; + prop->hard_reset_done_by_fw = + !!(cpu_boot_dev_sts0 & CPU_BOOT_DEV_STS0_FW_HARD_RST_EN); - /* FW security should be derived from PCI ID, we keep this - * check for backward compatibility - */ - if (security_status & CPU_BOOT_DEV_STS0_SECURITY_EN) - prop->fw_security_disabled = false; + dev_dbg(hdev->dev, "Firmware preboot boot device status0 %#x\n", + cpu_boot_dev_sts0); + + dev_dbg(hdev->dev, "Firmware preboot boot device status1 %#x\n", + cpu_boot_dev_sts1); + + dev_dbg(hdev->dev, "Firmware preboot hard-reset is %s\n", + prop->hard_reset_done_by_fw ? "enabled" : "disabled"); + + dev_dbg(hdev->dev, "firmware-level security is %s\n", + prop->fw_security_enabled ? "enabled" : "disabled"); + + dev_dbg(hdev->dev, "GIC controller is %s\n", + prop->gic_interrupts_enable ? "enabled" : "disabled"); +} + +static int hl_fw_static_read_preboot_status(struct hl_device *hdev) +{ + int rc; + + rc = hl_fw_static_read_device_fw_version(hdev, FW_COMP_PREBOOT); + if (rc) + return rc; + + return 0; +} + +int hl_fw_read_preboot_status(struct hl_device *hdev, u32 cpu_boot_status_reg, + u32 sts_boot_dev_sts0_reg, + u32 sts_boot_dev_sts1_reg, u32 boot_err0_reg, + u32 boot_err1_reg, u32 timeout) +{ + int rc; + + /* pldm was added for cases in which we use preboot on pldm and want + * to load boot fit, but we can't wait for preboot because it runs + * very slowly + */ + if (!(hdev->fw_components & FW_TYPE_PREBOOT_CPU) || hdev->pldm) + return 0; + + /* + * In order to determine boot method (static VS dymanic) we need to + * read the boot caps register + */ + rc = hl_fw_read_preboot_caps(hdev, cpu_boot_status_reg, + sts_boot_dev_sts0_reg, + sts_boot_dev_sts1_reg, boot_err0_reg, + boot_err1_reg, timeout); + if (rc) + return rc; + + hl_fw_preboot_update_state(hdev); - if (security_status & CPU_BOOT_DEV_STS0_FW_HARD_RST_EN) + /* no need to read preboot status in dynamic load */ + if (hdev->asic_prop.dynamic_fw_load) + return 0; + + return hl_fw_static_read_preboot_status(hdev); +} + +/* associate string with COMM status */ +static char *hl_dynamic_fw_status_str[COMMS_STS_INVLD_LAST] = { + [COMMS_STS_NOOP] = "NOOP", + [COMMS_STS_ACK] = "ACK", + [COMMS_STS_OK] = "OK", + [COMMS_STS_ERR] = "ERR", + [COMMS_STS_VALID_ERR] = "VALID_ERR", + [COMMS_STS_TIMEOUT_ERR] = "TIMEOUT_ERR", +}; + +/** + * hl_fw_dynamic_report_error_status - report error status + * + * @hdev: pointer to the habanalabs device structure + * @status: value of FW status register + * @expected_status: the expected status + */ +static void hl_fw_dynamic_report_error_status(struct hl_device *hdev, + u32 status, + enum comms_sts expected_status) +{ + enum comms_sts comm_status = + FIELD_GET(COMMS_STATUS_STATUS_MASK, status); + + if (comm_status < COMMS_STS_INVLD_LAST) + dev_err(hdev->dev, "Device status %s, expected status: %s\n", + hl_dynamic_fw_status_str[comm_status], + hl_dynamic_fw_status_str[expected_status]); + else + dev_err(hdev->dev, "Device status unknown %d, expected status: %s\n", + comm_status, + hl_dynamic_fw_status_str[expected_status]); +} + +/** + * hl_fw_dynamic_send_cmd - send LKD to FW cmd + * + * @hdev: pointer to the habanalabs device structure + * @fw_loader: managing structure for loading device's FW + * @cmd: LKD to FW cmd code + * @size: size of next FW component to be loaded (0 if not necessary) + * + * LDK to FW exact command layout is defined at struct comms_command. + * note: the size argument is used only when the next FW component should be + * loaded, otherwise it shall be 0. the size is used by the FW in later + * protocol stages and when sending only indicating the amount of memory + * to be allocated by the FW to receive the next boot component. + */ +static void hl_fw_dynamic_send_cmd(struct hl_device *hdev, + struct fw_load_mgr *fw_loader, + enum comms_cmd cmd, unsigned int size) +{ + struct cpu_dyn_regs *dyn_regs; + u32 val; + + dyn_regs = &fw_loader->dynamic_loader.comm_desc.cpu_dyn_regs; + + val = FIELD_PREP(COMMS_COMMAND_CMD_MASK, cmd); + val |= FIELD_PREP(COMMS_COMMAND_SIZE_MASK, size); + + WREG32(le32_to_cpu(dyn_regs->kmd_msg_to_cpu), val); +} + +/** + * hl_fw_dynamic_extract_fw_response - update the FW response + * + * @hdev: pointer to the habanalabs device structure + * @fw_loader: managing structure for loading device's FW + * @response: FW response + * @status: the status read from CPU status register + * + * @return 0 on success, otherwise non-zero error code + */ +static int hl_fw_dynamic_extract_fw_response(struct hl_device *hdev, + struct fw_load_mgr *fw_loader, + struct fw_response *response, + u32 status) +{ + response->status = FIELD_GET(COMMS_STATUS_STATUS_MASK, status); + response->ram_offset = FIELD_GET(COMMS_STATUS_OFFSET_MASK, status) << + COMMS_STATUS_OFFSET_ALIGN_SHIFT; + response->ram_type = FIELD_GET(COMMS_STATUS_RAM_TYPE_MASK, status); + + if ((response->ram_type != COMMS_SRAM) && + (response->ram_type != COMMS_DRAM)) { + dev_err(hdev->dev, "FW status: invalid RAM type %u\n", + response->ram_type); + return -EIO; + } + + return 0; +} + +/** + * hl_fw_dynamic_wait_for_status - wait for status in dynamic FW load + * + * @hdev: pointer to the habanalabs device structure + * @fw_loader: managing structure for loading device's FW + * @expected_status: expected status to wait for + * @timeout: timeout for status wait + * + * @return 0 on success, otherwise non-zero error code + * + * waiting for status from FW include polling the FW status register until + * expected status is received or timeout occurs (whatever occurs first). + */ +static int hl_fw_dynamic_wait_for_status(struct hl_device *hdev, + struct fw_load_mgr *fw_loader, + enum comms_sts expected_status, + u32 timeout) +{ + struct cpu_dyn_regs *dyn_regs; + u32 status; + int rc; + + dyn_regs = &fw_loader->dynamic_loader.comm_desc.cpu_dyn_regs; + + /* Wait for expected status */ + rc = hl_poll_timeout( + hdev, + le32_to_cpu(dyn_regs->cpu_cmd_status_to_host), + status, + FIELD_GET(COMMS_STATUS_STATUS_MASK, status) == expected_status, + FW_CPU_STATUS_POLL_INTERVAL_USEC, + timeout); + + if (rc) { + hl_fw_dynamic_report_error_status(hdev, status, + expected_status); + return -EIO; + } + + /* + * skip storing FW response for NOOP to preserve the actual desired + * FW status + */ + if (expected_status == COMMS_STS_NOOP) + return 0; + + rc = hl_fw_dynamic_extract_fw_response(hdev, fw_loader, + &fw_loader->dynamic_loader.response, + status); + return rc; +} + +/** + * hl_fw_dynamic_send_clear_cmd - send clear command to FW + * + * @hdev: pointer to the habanalabs device structure + * @fw_loader: managing structure for loading device's FW + * + * @return 0 on success, otherwise non-zero error code + * + * after command cycle between LKD to FW CPU (i.e. LKD got an expected status + * from FW) we need to clear the CPU status register in order to avoid garbage + * between command cycles. + * This is done by sending clear command and polling the CPU to LKD status + * register to hold the status NOOP + */ +static int hl_fw_dynamic_send_clear_cmd(struct hl_device *hdev, + struct fw_load_mgr *fw_loader) +{ + hl_fw_dynamic_send_cmd(hdev, fw_loader, COMMS_CLR_STS, 0); + + return hl_fw_dynamic_wait_for_status(hdev, fw_loader, COMMS_STS_NOOP, + fw_loader->cpu_timeout); +} + +/** + * hl_fw_dynamic_send_protocol_cmd - send LKD to FW cmd and wait for ACK + * + * @hdev: pointer to the habanalabs device structure + * @fw_loader: managing structure for loading device's FW + * @cmd: LKD to FW cmd code + * @size: size of next FW component to be loaded (0 if not necessary) + * @wait_ok: if true also wait for OK response from FW + * @timeout: timeout for status wait + * + * @return 0 on success, otherwise non-zero error code + * + * brief: + * when sending protocol command we have the following steps: + * - send clear (clear command and verify clear status register) + * - send the actual protocol command + * - wait for ACK on the protocol command + * - send clear + * - send NOOP + * if, in addition, the specific protocol command should wait for OK then: + * - wait for OK + * - send clear + * - send NOOP + * + * NOTES: + * send clear: this is necessary in order to clear the status register to avoid + * leftovers between command + * NOOP command: necessary to avoid loop on the clear command by the FW + */ +int hl_fw_dynamic_send_protocol_cmd(struct hl_device *hdev, + struct fw_load_mgr *fw_loader, + enum comms_cmd cmd, unsigned int size, + bool wait_ok, u32 timeout) +{ + int rc; + + /* first send clear command to clean former commands */ + rc = hl_fw_dynamic_send_clear_cmd(hdev, fw_loader); + + /* send the actual command */ + hl_fw_dynamic_send_cmd(hdev, fw_loader, cmd, size); + + /* wait for ACK for the command */ + rc = hl_fw_dynamic_wait_for_status(hdev, fw_loader, COMMS_STS_ACK, + timeout); + if (rc) + return rc; + + /* clear command to prepare for NOOP command */ + rc = hl_fw_dynamic_send_clear_cmd(hdev, fw_loader); + if (rc) + return rc; + + /* send the actual NOOP command */ + hl_fw_dynamic_send_cmd(hdev, fw_loader, COMMS_NOOP, 0); + + if (!wait_ok) + return 0; + + rc = hl_fw_dynamic_wait_for_status(hdev, fw_loader, COMMS_STS_OK, + timeout); + if (rc) + return rc; + + /* clear command to prepare for NOOP command */ + rc = hl_fw_dynamic_send_clear_cmd(hdev, fw_loader); + if (rc) + return rc; + + /* send the actual NOOP command */ + hl_fw_dynamic_send_cmd(hdev, fw_loader, COMMS_NOOP, 0); + + return 0; +} + +/** + * hl_fw_compat_crc32 - CRC compatible with FW + * + * @data: pointer to the data + * @size: size of the data + * + * @return the CRC32 result + * + * NOTE: kernel's CRC32 differ's from standard CRC32 calculation. + * in order to be aligned we need to flip the bits of both the input + * initial CRC and kernel's CRC32 result. + * in addition both sides use initial CRC of 0, + */ +static u32 hl_fw_compat_crc32(u8 *data, size_t size) +{ + return ~crc32_le(~((u32)0), data, size); +} + +/** + * hl_fw_dynamic_validate_memory_bound - validate memory bounds for memory + * transfer (image or descriptor) between + * host and FW + * + * @hdev: pointer to the habanalabs device structure + * @addr: device address of memory transfer + * @size: memory transter size + * @region: PCI memory region + * + * @return 0 on success, otherwise non-zero error code + */ +static int hl_fw_dynamic_validate_memory_bound(struct hl_device *hdev, + u64 addr, size_t size, + struct pci_mem_region *region) +{ + u64 end_addr; + + /* now make sure that the memory transfer is within region's bounds */ + end_addr = addr + size; + if (end_addr >= region->region_base + region->region_size) { + dev_err(hdev->dev, + "dynamic FW load: memory transfer end address out of memory region bounds. addr: %llx\n", + end_addr); + return -EIO; + } + + /* + * now make sure memory transfer is within predefined BAR bounds. + * this is to make sure we do not need to set the bar (e.g. for DRAM + * memory transfers) + */ + if (end_addr >= region->region_base - region->offset_in_bar + + region->bar_size) { + dev_err(hdev->dev, + "FW image beyond PCI BAR bounds\n"); + return -EIO; + } + + return 0; +} + +/** + * hl_fw_dynamic_validate_descriptor - validate FW descriptor + * + * @hdev: pointer to the habanalabs device structure + * @fw_loader: managing structure for loading device's FW + * @fw_desc: the descriptor form FW + * + * @return 0 on success, otherwise non-zero error code + */ +static int hl_fw_dynamic_validate_descriptor(struct hl_device *hdev, + struct fw_load_mgr *fw_loader, + struct lkd_fw_comms_desc *fw_desc) +{ + struct pci_mem_region *region; + enum pci_region region_id; + size_t data_size; + u32 data_crc32; + u8 *data_ptr; + u64 addr; + int rc; + + if (le32_to_cpu(fw_desc->header.magic) != HL_COMMS_DESC_MAGIC) { + dev_err(hdev->dev, "Invalid magic for dynamic FW descriptor (%x)\n", + fw_desc->header.magic); + return -EIO; + } + + if (fw_desc->header.version != HL_COMMS_DESC_VER) { + dev_err(hdev->dev, "Invalid version for dynamic FW descriptor (%x)\n", + fw_desc->header.version); + return -EIO; + } + + /* + * calc CRC32 of data without header. + * note that no alignment/stride address issues here as all structures + * are 64 bit padded + */ + data_size = sizeof(struct lkd_fw_comms_desc) - + sizeof(struct comms_desc_header); + data_ptr = (u8 *)fw_desc + sizeof(struct comms_desc_header); + + if (le16_to_cpu(fw_desc->header.size) != data_size) { + dev_err(hdev->dev, + "Invalid descriptor size 0x%x, expected size 0x%zx\n", + le16_to_cpu(fw_desc->header.size), data_size); + return -EIO; + } + + data_crc32 = hl_fw_compat_crc32(data_ptr, data_size); + + if (data_crc32 != le32_to_cpu(fw_desc->header.crc32)) { + dev_err(hdev->dev, + "CRC32 mismatch for dynamic FW descriptor (%x:%x)\n", + data_crc32, fw_desc->header.crc32); + return -EIO; + } + + /* find memory region to which to copy the image */ + addr = le64_to_cpu(fw_desc->img_addr); + region_id = hl_get_pci_memory_region(hdev, addr); + if ((region_id != PCI_REGION_SRAM) && + ((region_id != PCI_REGION_DRAM))) { + dev_err(hdev->dev, + "Invalid region to copy FW image address=%llx\n", addr); + return -EIO; + } + + region = &hdev->pci_mem_region[region_id]; + + /* store the region for the copy stage */ + fw_loader->dynamic_loader.image_region = region; + + /* + * here we know that the start address is valid, now make sure that the + * image is within region's bounds + */ + rc = hl_fw_dynamic_validate_memory_bound(hdev, addr, + fw_loader->dynamic_loader.fw_image_size, + region); + if (rc) { + dev_err(hdev->dev, + "invalid mem transfer request for FW image\n"); + return rc; + } + + return 0; +} + +static int hl_fw_dynamic_validate_response(struct hl_device *hdev, + struct fw_response *response, + struct pci_mem_region *region) +{ + u64 device_addr; + int rc; + + device_addr = region->region_base + response->ram_offset; + + /* + * validate that the descriptor is within region's bounds + * Note that as the start address was supplied according to the RAM + * type- testing only the end address is enough + */ + rc = hl_fw_dynamic_validate_memory_bound(hdev, device_addr, + sizeof(struct lkd_fw_comms_desc), + region); + return rc; +} + +/** + * hl_fw_dynamic_read_and_validate_descriptor - read and validate FW descriptor + * + * @hdev: pointer to the habanalabs device structure + * @fw_loader: managing structure for loading device's FW + * + * @return 0 on success, otherwise non-zero error code + */ +static int hl_fw_dynamic_read_and_validate_descriptor(struct hl_device *hdev, + struct fw_load_mgr *fw_loader) +{ + struct lkd_fw_comms_desc *fw_desc; + struct pci_mem_region *region; + struct fw_response *response; + enum pci_region region_id; + void __iomem *src; + int rc; + + fw_desc = &fw_loader->dynamic_loader.comm_desc; + response = &fw_loader->dynamic_loader.response; + + region_id = (response->ram_type == COMMS_SRAM) ? + PCI_REGION_SRAM : PCI_REGION_DRAM; + + region = &hdev->pci_mem_region[region_id]; + + rc = hl_fw_dynamic_validate_response(hdev, response, region); + if (rc) { + dev_err(hdev->dev, + "invalid mem transfer request for FW descriptor\n"); + return rc; + } + + /* extract address copy the descriptor from */ + src = hdev->pcie_bar[region->bar_id] + region->offset_in_bar + + response->ram_offset; + memcpy_fromio(fw_desc, src, sizeof(struct lkd_fw_comms_desc)); + + return hl_fw_dynamic_validate_descriptor(hdev, fw_loader, fw_desc); +} + +/** + * hl_fw_dynamic_request_descriptor - handshake with CPU to get FW descriptor + * + * @hdev: pointer to the habanalabs device structure + * @fw_loader: managing structure for loading device's FW + * @next_image_size: size to allocate for next FW component + * + * @return 0 on success, otherwise non-zero error code + */ +static int hl_fw_dynamic_request_descriptor(struct hl_device *hdev, + struct fw_load_mgr *fw_loader, + size_t next_image_size) +{ + int rc; + + rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, COMMS_PREP_DESC, + next_image_size, true, + fw_loader->cpu_timeout); + if (rc) + return rc; + + return hl_fw_dynamic_read_and_validate_descriptor(hdev, fw_loader); +} + +/** + * hl_fw_dynamic_read_device_fw_version - read FW version to exposed properties + * + * @hdev: pointer to the habanalabs device structure + * @fwc: the firmware component + * @fw_version: fw component's version string + */ +static void hl_fw_dynamic_read_device_fw_version(struct hl_device *hdev, + enum hl_fw_component fwc, + const char *fw_version) +{ + struct asic_fixed_properties *prop = &hdev->asic_prop; + char *preboot_ver, *boot_ver; + char btl_ver[32]; + + switch (fwc) { + case FW_COMP_BOOT_FIT: + strscpy(prop->uboot_ver, fw_version, VERSION_MAX_LEN); + boot_ver = extract_fw_ver_from_str(prop->uboot_ver); + if (boot_ver) { + dev_info(hdev->dev, "boot-fit version %s\n", boot_ver); + kfree(boot_ver); + } + + break; + case FW_COMP_PREBOOT: + strscpy(prop->preboot_ver, fw_version, VERSION_MAX_LEN); + preboot_ver = strnstr(prop->preboot_ver, "Preboot", + VERSION_MAX_LEN); + if (preboot_ver && preboot_ver != prop->preboot_ver) { + strscpy(btl_ver, prop->preboot_ver, + min((int) (preboot_ver - prop->preboot_ver), + 31)); + dev_info(hdev->dev, "%s\n", btl_ver); + } + + preboot_ver = extract_fw_ver_from_str(prop->preboot_ver); + if (preboot_ver) { + dev_info(hdev->dev, "preboot version %s\n", + preboot_ver); + kfree(preboot_ver); + } + + break; + default: + dev_warn(hdev->dev, "Undefined FW component: %d\n", fwc); + return; + } +} + +/** + * hl_fw_dynamic_copy_image - copy image to memory allocated by the FW + * + * @hdev: pointer to the habanalabs device structure + * @fw: fw descriptor + * @fw_loader: managing structure for loading device's FW + */ +static int hl_fw_dynamic_copy_image(struct hl_device *hdev, + const struct firmware *fw, + struct fw_load_mgr *fw_loader) +{ + struct lkd_fw_comms_desc *fw_desc; + struct pci_mem_region *region; + void __iomem *dest; + u64 addr; + int rc; + + fw_desc = &fw_loader->dynamic_loader.comm_desc; + addr = le64_to_cpu(fw_desc->img_addr); + + /* find memory region to which to copy the image */ + region = fw_loader->dynamic_loader.image_region; + + dest = hdev->pcie_bar[region->bar_id] + region->offset_in_bar + + (addr - region->region_base); + + rc = hl_fw_copy_fw_to_device(hdev, fw, dest, + fw_loader->boot_fit_img.src_off, + fw_loader->boot_fit_img.copy_size); + + return rc; +} + +/** + * hl_fw_dynamic_copy_msg - copy msg to memory allocated by the FW + * + * @hdev: pointer to the habanalabs device structure + * @msg: message + * @fw_loader: managing structure for loading device's FW + */ +static int hl_fw_dynamic_copy_msg(struct hl_device *hdev, + struct lkd_msg_comms *msg, struct fw_load_mgr *fw_loader) +{ + struct lkd_fw_comms_desc *fw_desc; + struct pci_mem_region *region; + void __iomem *dest; + u64 addr; + int rc; + + fw_desc = &fw_loader->dynamic_loader.comm_desc; + addr = le64_to_cpu(fw_desc->img_addr); + + /* find memory region to which to copy the image */ + region = fw_loader->dynamic_loader.image_region; + + dest = hdev->pcie_bar[region->bar_id] + region->offset_in_bar + + (addr - region->region_base); + + rc = hl_fw_copy_msg_to_device(hdev, msg, dest, 0, 0); + + return rc; +} + +/** + * hl_fw_boot_fit_update_state - update internal data structures after boot-fit + * is loaded + * + * @hdev: pointer to the habanalabs device structure + * @cpu_boot_dev_sts0_reg: register holding CPU boot dev status 0 + * @cpu_boot_dev_sts1_reg: register holding CPU boot dev status 1 + * + * @return 0 on success, otherwise non-zero error code + */ +static void hl_fw_boot_fit_update_state(struct hl_device *hdev, + u32 cpu_boot_dev_sts0_reg, + u32 cpu_boot_dev_sts1_reg) +{ + struct asic_fixed_properties *prop = &hdev->asic_prop; + + /* Clear reset status since we need to read it again from boot CPU */ + prop->hard_reset_done_by_fw = false; + + /* Read boot_cpu status bits */ + if (prop->fw_preboot_cpu_boot_dev_sts0 & CPU_BOOT_DEV_STS0_ENABLED) { + prop->fw_bootfit_cpu_boot_dev_sts0 = + RREG32(cpu_boot_dev_sts0_reg); + + if (prop->fw_bootfit_cpu_boot_dev_sts0 & + CPU_BOOT_DEV_STS0_FW_HARD_RST_EN) prop->hard_reset_done_by_fw = true; - } else { - prop->fw_security_status_valid = 0; + + dev_dbg(hdev->dev, "Firmware boot CPU status0 %#x\n", + prop->fw_bootfit_cpu_boot_dev_sts0); } - dev_dbg(hdev->dev, "Firmware preboot security status %#x\n", - security_status); + if (prop->fw_cpu_boot_dev_sts1_valid) { + prop->fw_bootfit_cpu_boot_dev_sts1 = + RREG32(cpu_boot_dev_sts1_reg); - dev_dbg(hdev->dev, "Firmware preboot hard-reset is %s\n", + dev_dbg(hdev->dev, "Firmware boot CPU status1 %#x\n", + prop->fw_bootfit_cpu_boot_dev_sts1); + } + + dev_dbg(hdev->dev, "Firmware boot CPU hard-reset is %s\n", prop->hard_reset_done_by_fw ? "enabled" : "disabled"); +} + +static void hl_fw_dynamic_update_linux_interrupt_if(struct hl_device *hdev) +{ + struct cpu_dyn_regs *dyn_regs = + &hdev->fw_loader.dynamic_loader.comm_desc.cpu_dyn_regs; + + /* Check whether all 3 interrupt interfaces are set, if not use a + * single interface + */ + if (!hdev->asic_prop.gic_interrupts_enable && + !(hdev->asic_prop.fw_app_cpu_boot_dev_sts0 & + CPU_BOOT_DEV_STS0_MULTI_IRQ_POLL_EN)) { + dyn_regs->gic_host_halt_irq = dyn_regs->gic_host_irq_ctrl; + dyn_regs->gic_host_ints_irq = dyn_regs->gic_host_irq_ctrl; + + dev_warn(hdev->dev, + "Using a single interrupt interface towards cpucp"); + } +} +/** + * hl_fw_dynamic_load_image - load FW image using dynamic protocol + * + * @hdev: pointer to the habanalabs device structure + * @fw_loader: managing structure for loading device's FW + * @load_fwc: the FW component to be loaded + * @img_ld_timeout: image load timeout + * + * @return 0 on success, otherwise non-zero error code + */ +static int hl_fw_dynamic_load_image(struct hl_device *hdev, + struct fw_load_mgr *fw_loader, + enum hl_fw_component load_fwc, + u32 img_ld_timeout) +{ + enum hl_fw_component cur_fwc; + const struct firmware *fw; + char *fw_name; + int rc = 0; + + /* + * when loading image we have one of 2 scenarios: + * 1. current FW component is preboot and we want to load boot-fit + * 2. current FW component is boot-fit and we want to load linux + */ + if (load_fwc == FW_COMP_BOOT_FIT) { + cur_fwc = FW_COMP_PREBOOT; + fw_name = fw_loader->boot_fit_img.image_name; + } else { + cur_fwc = FW_COMP_BOOT_FIT; + fw_name = fw_loader->linux_img.image_name; + } + + /* request FW in order to communicate to FW the size to be allocated */ + rc = hl_request_fw(hdev, &fw, fw_name); + if (rc) + return rc; + + /* store the image size for future validation */ + fw_loader->dynamic_loader.fw_image_size = fw->size; + + rc = hl_fw_dynamic_request_descriptor(hdev, fw_loader, fw->size); + if (rc) + goto release_fw; + + /* read preboot version */ + hl_fw_dynamic_read_device_fw_version(hdev, cur_fwc, + fw_loader->dynamic_loader.comm_desc.cur_fw_ver); + + + /* update state according to boot stage */ + if (cur_fwc == FW_COMP_BOOT_FIT) { + struct cpu_dyn_regs *dyn_regs; + + dyn_regs = &fw_loader->dynamic_loader.comm_desc.cpu_dyn_regs; + hl_fw_boot_fit_update_state(hdev, + le32_to_cpu(dyn_regs->cpu_boot_dev_sts0), + le32_to_cpu(dyn_regs->cpu_boot_dev_sts1)); + } + + /* copy boot fit to space allocated by FW */ + rc = hl_fw_dynamic_copy_image(hdev, fw, fw_loader); + if (rc) + goto release_fw; - dev_info(hdev->dev, "firmware-level security is %s\n", - prop->fw_security_disabled ? "disabled" : "enabled"); + rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, COMMS_DATA_RDY, + 0, true, + fw_loader->cpu_timeout); + if (rc) + goto release_fw; + + rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, COMMS_EXEC, + 0, false, + img_ld_timeout); +release_fw: + hl_release_firmware(fw); + return rc; +} + +static int hl_fw_dynamic_wait_for_boot_fit_active(struct hl_device *hdev, + struct fw_load_mgr *fw_loader) +{ + struct dynamic_fw_load_mgr *dyn_loader; + u32 status; + int rc; + + dyn_loader = &fw_loader->dynamic_loader; + + /* Make sure CPU boot-loader is running */ + rc = hl_poll_timeout( + hdev, + le32_to_cpu(dyn_loader->comm_desc.cpu_dyn_regs.cpu_boot_status), + status, + (status == CPU_BOOT_STATUS_NIC_FW_RDY) || + (status == CPU_BOOT_STATUS_READY_TO_BOOT), + FW_CPU_STATUS_POLL_INTERVAL_USEC, + dyn_loader->wait_for_bl_timeout); + if (rc) { + dev_err(hdev->dev, "failed to wait for boot\n"); + return rc; + } + + dev_dbg(hdev->dev, "uboot status = %d\n", status); return 0; } -int hl_fw_init_cpu(struct hl_device *hdev, u32 cpu_boot_status_reg, - u32 msg_to_cpu_reg, u32 cpu_msg_status_reg, - u32 cpu_security_boot_status_reg, u32 boot_err0_reg, - bool skip_bmc, u32 cpu_timeout, u32 boot_fit_timeout) +static int hl_fw_dynamic_wait_for_linux_active(struct hl_device *hdev, + struct fw_load_mgr *fw_loader) { - struct asic_fixed_properties *prop = &hdev->asic_prop; + struct dynamic_fw_load_mgr *dyn_loader; u32 status; int rc; + dyn_loader = &fw_loader->dynamic_loader; + + /* Make sure CPU boot-loader is running */ + + rc = hl_poll_timeout( + hdev, + le32_to_cpu(dyn_loader->comm_desc.cpu_dyn_regs.cpu_boot_status), + status, + (status == CPU_BOOT_STATUS_SRAM_AVAIL), + FW_CPU_STATUS_POLL_INTERVAL_USEC, + fw_loader->cpu_timeout); + if (rc) { + dev_err(hdev->dev, "failed to wait for Linux\n"); + return rc; + } + + dev_dbg(hdev->dev, "Boot status = %d\n", status); + return 0; +} + +/** + * hl_fw_linux_update_state - update internal data structures after Linux + * is loaded. + * Note: Linux initialization is comprised mainly + * of two stages - loading kernel (SRAM_AVAIL) + * & loading ARMCP. + * Therefore reading boot device status in any of + * these stages might result in different values. + * + * @hdev: pointer to the habanalabs device structure + * @cpu_boot_dev_sts0_reg: register holding CPU boot dev status 0 + * @cpu_boot_dev_sts1_reg: register holding CPU boot dev status 1 + * + * @return 0 on success, otherwise non-zero error code + */ +static void hl_fw_linux_update_state(struct hl_device *hdev, + u32 cpu_boot_dev_sts0_reg, + u32 cpu_boot_dev_sts1_reg) +{ + struct asic_fixed_properties *prop = &hdev->asic_prop; + + hdev->fw_loader.linux_loaded = true; + + /* Clear reset status since we need to read again from app */ + prop->hard_reset_done_by_fw = false; + + /* Read FW application security bits */ + if (prop->fw_cpu_boot_dev_sts0_valid) { + prop->fw_app_cpu_boot_dev_sts0 = + RREG32(cpu_boot_dev_sts0_reg); + + if (prop->fw_app_cpu_boot_dev_sts0 & + CPU_BOOT_DEV_STS0_FW_HARD_RST_EN) + prop->hard_reset_done_by_fw = true; + + if (prop->fw_app_cpu_boot_dev_sts0 & + CPU_BOOT_DEV_STS0_GIC_PRIVILEGED_EN) + prop->gic_interrupts_enable = false; + + dev_dbg(hdev->dev, + "Firmware application CPU status0 %#x\n", + prop->fw_app_cpu_boot_dev_sts0); + + dev_dbg(hdev->dev, "GIC controller is %s\n", + prop->gic_interrupts_enable ? + "enabled" : "disabled"); + } + + if (prop->fw_cpu_boot_dev_sts1_valid) { + prop->fw_app_cpu_boot_dev_sts1 = + RREG32(cpu_boot_dev_sts1_reg); + + dev_dbg(hdev->dev, + "Firmware application CPU status1 %#x\n", + prop->fw_app_cpu_boot_dev_sts1); + } + + dev_dbg(hdev->dev, "Firmware application CPU hard-reset is %s\n", + prop->hard_reset_done_by_fw ? "enabled" : "disabled"); + + dev_info(hdev->dev, "Successfully loaded firmware to device\n"); +} + +/** + * hl_fw_dynamic_report_reset_cause - send a COMMS message with the cause + * of the newly triggered hard reset + * + * @hdev: pointer to the habanalabs device structure + * @fw_loader: managing structure for loading device's FW + * @reset_cause: enumerated cause for the recent hard reset + * + * @return 0 on success, otherwise non-zero error code + */ +static int hl_fw_dynamic_report_reset_cause(struct hl_device *hdev, + struct fw_load_mgr *fw_loader, + enum comms_reset_cause reset_cause) +{ + struct lkd_msg_comms msg; + int rc; + + memset(&msg, 0, sizeof(msg)); + + /* create message to be sent */ + msg.header.type = HL_COMMS_RESET_CAUSE_TYPE; + msg.header.size = cpu_to_le16(sizeof(struct comms_msg_header)); + msg.header.magic = cpu_to_le32(HL_COMMS_MSG_MAGIC); + + msg.reset_cause = reset_cause; + + rc = hl_fw_dynamic_request_descriptor(hdev, fw_loader, + sizeof(struct lkd_msg_comms)); + if (rc) + return rc; + + /* copy message to space allocated by FW */ + rc = hl_fw_dynamic_copy_msg(hdev, &msg, fw_loader); + if (rc) + return rc; + + rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, COMMS_DATA_RDY, + 0, true, + fw_loader->cpu_timeout); + if (rc) + return rc; + + rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, COMMS_EXEC, + 0, true, + fw_loader->cpu_timeout); + if (rc) + return rc; + + return 0; +} + +/** + * hl_fw_dynamic_init_cpu - initialize the device CPU using dynamic protocol + * + * @hdev: pointer to the habanalabs device structure + * @fw_loader: managing structure for loading device's FW + * + * @return 0 on success, otherwise non-zero error code + * + * brief: the dynamic protocol is master (LKD) slave (FW CPU) protocol. + * the communication is done using registers: + * - LKD command register + * - FW status register + * the protocol is race free. this goal is achieved by splitting the requests + * and response to known synchronization points between the LKD and the FW. + * each response to LKD request is known and bound to a predefined timeout. + * in case of timeout expiration without the desired status from FW- the + * protocol (and hence the boot) will fail. + */ +static int hl_fw_dynamic_init_cpu(struct hl_device *hdev, + struct fw_load_mgr *fw_loader) +{ + struct cpu_dyn_regs *dyn_regs; + int rc; + + dev_info(hdev->dev, + "Loading firmware to device, may take some time...\n"); + + dyn_regs = &fw_loader->dynamic_loader.comm_desc.cpu_dyn_regs; + + rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, COMMS_RST_STATE, + 0, true, + fw_loader->cpu_timeout); + if (rc) + goto protocol_err; + + if (hdev->curr_reset_cause) { + rc = hl_fw_dynamic_report_reset_cause(hdev, fw_loader, + hdev->curr_reset_cause); + if (rc) + goto protocol_err; + + /* Clear current reset cause */ + hdev->curr_reset_cause = HL_RESET_CAUSE_UNKNOWN; + } + + if (!(hdev->fw_components & FW_TYPE_BOOT_CPU)) { + rc = hl_fw_dynamic_request_descriptor(hdev, fw_loader, 0); + if (rc) + goto protocol_err; + + /* read preboot version */ + hl_fw_dynamic_read_device_fw_version(hdev, FW_COMP_PREBOOT, + fw_loader->dynamic_loader.comm_desc.cur_fw_ver); + return 0; + } + + /* load boot fit to FW */ + rc = hl_fw_dynamic_load_image(hdev, fw_loader, FW_COMP_BOOT_FIT, + fw_loader->boot_fit_timeout); + if (rc) { + dev_err(hdev->dev, "failed to load boot fit\n"); + goto protocol_err; + } + + rc = hl_fw_dynamic_wait_for_boot_fit_active(hdev, fw_loader); + if (rc) + goto protocol_err; + + /* Enable DRAM scrambling before Linux boot and after successful + * UBoot + */ + hdev->asic_funcs->init_cpu_scrambler_dram(hdev); + + if (!(hdev->fw_components & FW_TYPE_LINUX)) { + dev_info(hdev->dev, "Skip loading Linux F/W\n"); + return 0; + } + + if (fw_loader->skip_bmc) { + rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, + COMMS_SKIP_BMC, 0, + true, + fw_loader->cpu_timeout); + if (rc) { + dev_err(hdev->dev, "failed to load boot fit\n"); + goto protocol_err; + } + } + + /* load Linux image to FW */ + rc = hl_fw_dynamic_load_image(hdev, fw_loader, FW_COMP_LINUX, + fw_loader->cpu_timeout); + if (rc) { + dev_err(hdev->dev, "failed to load Linux\n"); + goto protocol_err; + } + + rc = hl_fw_dynamic_wait_for_linux_active(hdev, fw_loader); + if (rc) + goto protocol_err; + + hl_fw_linux_update_state(hdev, le32_to_cpu(dyn_regs->cpu_boot_dev_sts0), + le32_to_cpu(dyn_regs->cpu_boot_dev_sts1)); + + hl_fw_dynamic_update_linux_interrupt_if(hdev); + + return 0; + +protocol_err: + fw_read_errors(hdev, le32_to_cpu(dyn_regs->cpu_boot_err0), + le32_to_cpu(dyn_regs->cpu_boot_err1), + le32_to_cpu(dyn_regs->cpu_boot_dev_sts0), + le32_to_cpu(dyn_regs->cpu_boot_dev_sts1)); + return rc; +} + +/** + * hl_fw_static_init_cpu - initialize the device CPU using static protocol + * + * @hdev: pointer to the habanalabs device structure + * @fw_loader: managing structure for loading device's FW + * + * @return 0 on success, otherwise non-zero error code + */ +static int hl_fw_static_init_cpu(struct hl_device *hdev, + struct fw_load_mgr *fw_loader) +{ + u32 cpu_msg_status_reg, cpu_timeout, msg_to_cpu_reg, status; + u32 cpu_boot_dev_status0_reg, cpu_boot_dev_status1_reg; + struct static_fw_load_mgr *static_loader; + u32 cpu_boot_status_reg; + int rc; + if (!(hdev->fw_components & FW_TYPE_BOOT_CPU)) return 0; + /* init common loader parameters */ + cpu_timeout = fw_loader->cpu_timeout; + + /* init static loader parameters */ + static_loader = &fw_loader->static_loader; + cpu_msg_status_reg = static_loader->cpu_cmd_status_to_host_reg; + msg_to_cpu_reg = static_loader->kmd_msg_to_cpu_reg; + cpu_boot_dev_status0_reg = static_loader->cpu_boot_dev_status0_reg; + cpu_boot_dev_status1_reg = static_loader->cpu_boot_dev_status1_reg; + cpu_boot_status_reg = static_loader->cpu_boot_status_reg; + dev_info(hdev->dev, "Going to wait for device boot (up to %lds)\n", cpu_timeout / USEC_PER_SEC); @@ -925,8 +2364,8 @@ int hl_fw_init_cpu(struct hl_device *hdev, u32 cpu_boot_status_reg, cpu_boot_status_reg, status, status == CPU_BOOT_STATUS_WAITING_FOR_BOOT_FIT, - 10000, - boot_fit_timeout); + FW_CPU_STATUS_POLL_INTERVAL_USEC, + fw_loader->boot_fit_timeout); if (rc) { dev_dbg(hdev->dev, @@ -948,8 +2387,8 @@ int hl_fw_init_cpu(struct hl_device *hdev, u32 cpu_boot_status_reg, cpu_msg_status_reg, status, status == CPU_MSG_OK, - 10000, - boot_fit_timeout); + FW_CPU_STATUS_POLL_INTERVAL_USEC, + fw_loader->boot_fit_timeout); if (rc) { dev_err(hdev->dev, @@ -970,33 +2409,17 @@ int hl_fw_init_cpu(struct hl_device *hdev, u32 cpu_boot_status_reg, (status == CPU_BOOT_STATUS_NIC_FW_RDY) || (status == CPU_BOOT_STATUS_READY_TO_BOOT) || (status == CPU_BOOT_STATUS_SRAM_AVAIL), - 10000, + FW_CPU_STATUS_POLL_INTERVAL_USEC, cpu_timeout); dev_dbg(hdev->dev, "uboot status = %d\n", status); /* Read U-Boot version now in case we will later fail */ - hdev->asic_funcs->read_device_fw_version(hdev, FW_COMP_UBOOT); - - /* Clear reset status since we need to read it again from boot CPU */ - prop->hard_reset_done_by_fw = false; - - /* Read boot_cpu security bits */ - if (prop->fw_security_status_valid) { - prop->fw_boot_cpu_security_map = - RREG32(cpu_security_boot_status_reg); - - if (prop->fw_boot_cpu_security_map & - CPU_BOOT_DEV_STS0_FW_HARD_RST_EN) - prop->hard_reset_done_by_fw = true; - - dev_dbg(hdev->dev, - "Firmware boot CPU security status %#x\n", - prop->fw_boot_cpu_security_map); - } + hl_fw_static_read_device_fw_version(hdev, FW_COMP_BOOT_FIT); - dev_dbg(hdev->dev, "Firmware boot CPU hard-reset is %s\n", - prop->hard_reset_done_by_fw ? "enabled" : "disabled"); + /* update state according to boot stage */ + hl_fw_boot_fit_update_state(hdev, cpu_boot_dev_status0_reg, + cpu_boot_dev_status1_reg); if (rc) { detect_cpu_boot_status(hdev, status); @@ -1004,13 +2427,21 @@ int hl_fw_init_cpu(struct hl_device *hdev, u32 cpu_boot_status_reg, goto out; } + /* Enable DRAM scrambling before Linux boot and after successful + * UBoot + */ + hdev->asic_funcs->init_cpu_scrambler_dram(hdev); + if (!(hdev->fw_components & FW_TYPE_LINUX)) { dev_info(hdev->dev, "Skip loading Linux F/W\n"); + rc = 0; goto out; } - if (status == CPU_BOOT_STATUS_SRAM_AVAIL) + if (status == CPU_BOOT_STATUS_SRAM_AVAIL) { + rc = 0; goto out; + } dev_info(hdev->dev, "Loading firmware to device, may take some time...\n"); @@ -1019,7 +2450,7 @@ int hl_fw_init_cpu(struct hl_device *hdev, u32 cpu_boot_status_reg, if (rc) goto out; - if (skip_bmc) { + if (fw_loader->skip_bmc) { WREG32(msg_to_cpu_reg, KMD_MSG_SKIP_BMC); rc = hl_poll_timeout( @@ -1027,7 +2458,7 @@ int hl_fw_init_cpu(struct hl_device *hdev, u32 cpu_boot_status_reg, cpu_boot_status_reg, status, (status == CPU_BOOT_STATUS_BMC_WAITING_SKIPPED), - 10000, + FW_CPU_STATUS_POLL_INTERVAL_USEC, cpu_timeout); if (rc) { @@ -1047,7 +2478,7 @@ int hl_fw_init_cpu(struct hl_device *hdev, u32 cpu_boot_status_reg, cpu_boot_status_reg, status, (status == CPU_BOOT_STATUS_SRAM_AVAIL), - 10000, + FW_CPU_STATUS_POLL_INTERVAL_USEC, cpu_timeout); /* Clear message */ @@ -1066,36 +2497,43 @@ int hl_fw_init_cpu(struct hl_device *hdev, u32 cpu_boot_status_reg, goto out; } - rc = fw_read_errors(hdev, boot_err0_reg, cpu_security_boot_status_reg); + rc = fw_read_errors(hdev, fw_loader->static_loader.boot_err0_reg, + fw_loader->static_loader.boot_err1_reg, + cpu_boot_dev_status0_reg, + cpu_boot_dev_status1_reg); if (rc) return rc; - /* Clear reset status since we need to read again from app */ - prop->hard_reset_done_by_fw = false; - - /* Read FW application security bits */ - if (prop->fw_security_status_valid) { - prop->fw_app_security_map = - RREG32(cpu_security_boot_status_reg); - - if (prop->fw_app_security_map & - CPU_BOOT_DEV_STS0_FW_HARD_RST_EN) - prop->hard_reset_done_by_fw = true; - - dev_dbg(hdev->dev, - "Firmware application CPU security status %#x\n", - prop->fw_app_security_map); - } - - dev_dbg(hdev->dev, "Firmware application CPU hard-reset is %s\n", - prop->hard_reset_done_by_fw ? "enabled" : "disabled"); - - dev_info(hdev->dev, "Successfully loaded firmware to device\n"); + hl_fw_linux_update_state(hdev, cpu_boot_dev_status0_reg, + cpu_boot_dev_status1_reg); return 0; out: - fw_read_errors(hdev, boot_err0_reg, cpu_security_boot_status_reg); + fw_read_errors(hdev, fw_loader->static_loader.boot_err0_reg, + fw_loader->static_loader.boot_err1_reg, + cpu_boot_dev_status0_reg, + cpu_boot_dev_status1_reg); return rc; } + +/** + * hl_fw_init_cpu - initialize the device CPU + * + * @hdev: pointer to the habanalabs device structure + * + * @return 0 on success, otherwise non-zero error code + * + * perform necessary initializations for device's CPU. takes into account if + * init protocol is static or dynamic. + */ +int hl_fw_init_cpu(struct hl_device *hdev) +{ + struct asic_fixed_properties *prop = &hdev->asic_prop; + struct fw_load_mgr *fw_loader = &hdev->fw_loader; + + return prop->dynamic_fw_load ? + hl_fw_dynamic_init_cpu(hdev, fw_loader) : + hl_fw_static_init_cpu(hdev, fw_loader); +} diff --git a/drivers/misc/habanalabs/common/habanalabs.h b/drivers/misc/habanalabs/common/habanalabs.h index 6579f8767abd..6b3cdd7e068a 100644 --- a/drivers/misc/habanalabs/common/habanalabs.h +++ b/drivers/misc/habanalabs/common/habanalabs.h @@ -48,6 +48,7 @@ #define HL_PENDING_RESET_LONG_SEC 60 #define HL_HARD_RESET_MAX_TIMEOUT 120 +#define HL_PLDM_HARD_RESET_MAX_TIMEOUT (HL_HARD_RESET_MAX_TIMEOUT * 3) #define HL_DEVICE_TIMEOUT_USEC 1000000 /* 1 s */ @@ -115,10 +116,18 @@ enum hl_mmu_page_table_location { * * - HL_RESET_HEARTBEAT * Set if reset is due to heartbeat + * + * - HL_RESET_TDR + * Set if reset is due to TDR + * + * - HL_RESET_DEVICE_RELEASE + * Set if reset is due to device release */ #define HL_RESET_HARD (1 << 0) #define HL_RESET_FROM_RESET_THREAD (1 << 1) #define HL_RESET_HEARTBEAT (1 << 2) +#define HL_RESET_TDR (1 << 3) +#define HL_RESET_DEVICE_RELEASE (1 << 4) #define HL_MAX_SOBS_PER_MONITOR 8 @@ -178,12 +187,14 @@ enum hl_pci_match_mode { /** * enum hl_fw_component - F/W components to read version through registers. - * @FW_COMP_UBOOT: u-boot. + * @FW_COMP_BOOT_FIT: boot fit. * @FW_COMP_PREBOOT: preboot. + * @FW_COMP_LINUX: linux. */ enum hl_fw_component { - FW_COMP_UBOOT, - FW_COMP_PREBOOT + FW_COMP_BOOT_FIT, + FW_COMP_PREBOOT, + FW_COMP_LINUX, }; /** @@ -420,12 +431,24 @@ struct hl_mmu_properties { * @cb_pool_cb_size: size of each CB in the CB pool. * @max_pending_cs: maximum of concurrent pending command submissions * @max_queues: maximum amount of queues in the system - * @fw_boot_cpu_security_map: bitmap representation of boot cpu security status - * reported by FW, bit description can be found in - * CPU_BOOT_DEV_STS* - * @fw_app_security_map: bitmap representation of application security status - * reported by FW, bit description can be found in - * CPU_BOOT_DEV_STS* + * @fw_preboot_cpu_boot_dev_sts0: bitmap representation of preboot cpu + * capabilities reported by FW, bit description + * can be found in CPU_BOOT_DEV_STS0 + * @fw_preboot_cpu_boot_dev_sts1: bitmap representation of preboot cpu + * capabilities reported by FW, bit description + * can be found in CPU_BOOT_DEV_STS1 + * @fw_bootfit_cpu_boot_dev_sts0: bitmap representation of boot cpu security + * status reported by FW, bit description can be + * found in CPU_BOOT_DEV_STS0 + * @fw_bootfit_cpu_boot_dev_sts1: bitmap representation of boot cpu security + * status reported by FW, bit description can be + * found in CPU_BOOT_DEV_STS1 + * @fw_app_cpu_boot_dev_sts0: bitmap representation of application security + * status reported by FW, bit description can be + * found in CPU_BOOT_DEV_STS0 + * @fw_app_cpu_boot_dev_sts1: bitmap representation of application security + * status reported by FW, bit description can be + * found in CPU_BOOT_DEV_STS1 * @collective_first_sob: first sync object available for collective use * @collective_first_mon: first monitor available for collective use * @sync_stream_first_sob: first sync object available for sync stream use @@ -438,14 +461,19 @@ struct hl_mmu_properties { * @user_interrupt_count: number of user interrupts. * @tpc_enabled_mask: which TPCs are enabled. * @completion_queues_count: number of completion queues. - * @fw_security_disabled: true if security measures are disabled in firmware, - * false otherwise - * @fw_security_status_valid: security status bits are valid and can be fetched - * from BOOT_DEV_STS0 + * @fw_security_enabled: true if security measures are enabled in firmware, + * false otherwise + * @fw_cpu_boot_dev_sts0_valid: status bits are valid and can be fetched from + * BOOT_DEV_STS0 + * @fw_cpu_boot_dev_sts1_valid: status bits are valid and can be fetched from + * BOOT_DEV_STS1 * @dram_supports_virtual_memory: is there an MMU towards the DRAM * @hard_reset_done_by_fw: true if firmware is handling hard reset flow * @num_functional_hbms: number of functional HBMs in each DCORE. * @iatu_done_by_fw: true if iATU configuration is being done by FW. + * @dynamic_fw_load: is dynamic FW load is supported. + * @gic_interrupts_enable: true if FW is not blocking GIC controller, + * false otherwise. */ struct asic_fixed_properties { struct hw_queue_properties *hw_queues_props; @@ -491,8 +519,12 @@ struct asic_fixed_properties { u32 cb_pool_cb_size; u32 max_pending_cs; u32 max_queues; - u32 fw_boot_cpu_security_map; - u32 fw_app_security_map; + u32 fw_preboot_cpu_boot_dev_sts0; + u32 fw_preboot_cpu_boot_dev_sts1; + u32 fw_bootfit_cpu_boot_dev_sts0; + u32 fw_bootfit_cpu_boot_dev_sts1; + u32 fw_app_cpu_boot_dev_sts0; + u32 fw_app_cpu_boot_dev_sts1; u16 collective_first_sob; u16 collective_first_mon; u16 sync_stream_first_sob; @@ -504,12 +536,15 @@ struct asic_fixed_properties { u16 user_interrupt_count; u8 tpc_enabled_mask; u8 completion_queues_count; - u8 fw_security_disabled; - u8 fw_security_status_valid; + u8 fw_security_enabled; + u8 fw_cpu_boot_dev_sts0_valid; + u8 fw_cpu_boot_dev_sts1_valid; u8 dram_supports_virtual_memory; u8 hard_reset_done_by_fw; u8 num_functional_hbms; u8 iatu_done_by_fw; + u8 dynamic_fw_load; + u8 gic_interrupts_enable; }; /** @@ -750,12 +785,19 @@ struct hl_user_pending_interrupt { * @kernel_address: holds the queue's kernel virtual address * @bus_address: holds the queue's DMA address * @ci: ci inside the queue + * @prev_eqe_index: the index of the previous event queue entry. The index of + * the current entry's index must be +1 of the previous one. + * @check_eqe_index: do we need to check the index of the current entry vs. the + * previous one. This is for backward compatibility with older + * firmwares */ struct hl_eq { struct hl_device *hdev; void *kernel_address; dma_addr_t bus_address; u32 ci; + u32 prev_eqe_index; + bool check_eqe_index; }; @@ -812,6 +854,132 @@ enum div_select_defs { DIV_SEL_DIVIDED_PLL = 3, }; +enum pci_region { + PCI_REGION_CFG, + PCI_REGION_SRAM, + PCI_REGION_DRAM, + PCI_REGION_SP_SRAM, + PCI_REGION_NUMBER, +}; + +/** + * struct pci_mem_region - describe memory region in a PCI bar + * @region_base: region base address + * @region_size: region size + * @bar_size: size of the BAR + * @offset_in_bar: region offset into the bar + * @bar_id: bar ID of the region + * @used: if used 1, otherwise 0 + */ +struct pci_mem_region { + u64 region_base; + u64 region_size; + u64 bar_size; + u32 offset_in_bar; + u8 bar_id; + u8 used; +}; + +/** + * struct static_fw_load_mgr - static FW load manager + * @preboot_version_max_off: max offset to preboot version + * @boot_fit_version_max_off: max offset to boot fit version + * @kmd_msg_to_cpu_reg: register address for KDM->CPU messages + * @cpu_cmd_status_to_host_reg: register address for CPU command status response + * @cpu_boot_status_reg: boot status register + * @cpu_boot_dev_status0_reg: boot device status register 0 + * @cpu_boot_dev_status1_reg: boot device status register 1 + * @boot_err0_reg: boot error register 0 + * @boot_err1_reg: boot error register 1 + * @preboot_version_offset_reg: SRAM offset to preboot version register + * @boot_fit_version_offset_reg: SRAM offset to boot fit version register + * @sram_offset_mask: mask for getting offset into the SRAM + * @cpu_reset_wait_msec: used when setting WFE via kmd_msg_to_cpu_reg + */ +struct static_fw_load_mgr { + u64 preboot_version_max_off; + u64 boot_fit_version_max_off; + u32 kmd_msg_to_cpu_reg; + u32 cpu_cmd_status_to_host_reg; + u32 cpu_boot_status_reg; + u32 cpu_boot_dev_status0_reg; + u32 cpu_boot_dev_status1_reg; + u32 boot_err0_reg; + u32 boot_err1_reg; + u32 preboot_version_offset_reg; + u32 boot_fit_version_offset_reg; + u32 sram_offset_mask; + u32 cpu_reset_wait_msec; +}; + +/** + * struct fw_response - FW response to LKD command + * @ram_offset: descriptor offset into the RAM + * @ram_type: RAM type containing the descriptor (SRAM/DRAM) + * @status: command status + */ +struct fw_response { + u32 ram_offset; + u8 ram_type; + u8 status; +}; + +/** + * struct dynamic_fw_load_mgr - dynamic FW load manager + * @response: FW to LKD response + * @comm_desc: the communication descriptor with FW + * @image_region: region to copy the FW image to + * @fw_image_size: size of FW image to load + * @wait_for_bl_timeout: timeout for waiting for boot loader to respond + */ +struct dynamic_fw_load_mgr { + struct fw_response response; + struct lkd_fw_comms_desc comm_desc; + struct pci_mem_region *image_region; + size_t fw_image_size; + u32 wait_for_bl_timeout; +}; + +/** + * struct fw_image_props - properties of FW image + * @image_name: name of the image + * @src_off: offset in src FW to copy from + * @copy_size: amount of bytes to copy (0 to copy the whole binary) + */ +struct fw_image_props { + char *image_name; + u32 src_off; + u32 copy_size; +}; + +/** + * struct fw_load_mgr - manager FW loading process + * @dynamic_loader: specific structure for dynamic load + * @static_loader: specific structure for static load + * @boot_fit_img: boot fit image properties + * @linux_img: linux image properties + * @cpu_timeout: CPU response timeout in usec + * @boot_fit_timeout: Boot fit load timeout in usec + * @skip_bmc: should BMC be skipped + * @sram_bar_id: SRAM bar ID + * @dram_bar_id: DRAM bar ID + * @linux_loaded: true if linux was loaded so far + */ +struct fw_load_mgr { + union { + struct dynamic_fw_load_mgr dynamic_loader; + struct static_fw_load_mgr static_loader; + }; + struct fw_image_props boot_fit_img; + struct fw_image_props linux_img; + u32 cpu_timeout; + u32 boot_fit_timeout; + u8 skip_bmc; + u8 sram_bar_id; + u8 dram_bar_id; + u8 linux_loaded; +}; + /** * struct hl_asic_funcs - ASIC specific functions that are can be called from * common code. @@ -901,8 +1069,6 @@ enum div_select_defs { * @ctx_fini: context dependent cleanup. * @get_clk_rate: Retrieve the ASIC current and maximum clock rate in MHz * @get_queue_id_for_cq: Get the H/W queue id related to the given CQ index. - * @read_device_fw_version: read the device's firmware versions that are - * contained in registers * @load_firmware_to_device: load the firmware to the device's memory * @load_boot_fit_to_device: load boot fit to device's memory * @get_signal_cb_size: Get signal CB size. @@ -933,6 +1099,8 @@ enum div_select_defs { * @get_msi_info: Retrieve asic-specific MSI ID of the f/w async event * @map_pll_idx_to_fw_idx: convert driver specific per asic PLL index to * generic f/w compatible PLL Indexes + * @init_firmware_loader: initialize data for FW loader. + * @init_cpu_scrambler_dram: Enable CPU specific DRAM scrambling */ struct hl_asic_funcs { int (*early_init)(struct hl_device *hdev); @@ -1006,7 +1174,7 @@ struct hl_asic_funcs { int (*mmu_invalidate_cache)(struct hl_device *hdev, bool is_hard, u32 flags); int (*mmu_invalidate_cache_range)(struct hl_device *hdev, bool is_hard, - u32 asid, u64 va, u64 size); + u32 flags, u32 asid, u64 va, u64 size); int (*send_heartbeat)(struct hl_device *hdev); void (*set_clock_gating)(struct hl_device *hdev); void (*disable_clock_gating)(struct hl_device *hdev); @@ -1030,8 +1198,6 @@ struct hl_asic_funcs { void (*ctx_fini)(struct hl_ctx *ctx); int (*get_clk_rate)(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk); u32 (*get_queue_id_for_cq)(struct hl_device *hdev, u32 cq_idx); - int (*read_device_fw_version)(struct hl_device *hdev, - enum hl_fw_component fwc); int (*load_firmware_to_device)(struct hl_device *hdev); int (*load_boot_fit_to_device)(struct hl_device *hdev); u32 (*get_signal_cb_size)(struct hl_device *hdev); @@ -1056,8 +1222,10 @@ struct hl_asic_funcs { int (*hw_block_mmap)(struct hl_device *hdev, struct vm_area_struct *vma, u32 block_id, u32 block_size); void (*enable_events_from_fw)(struct hl_device *hdev); - void (*get_msi_info)(u32 *table); + void (*get_msi_info)(__le32 *table); int (*map_pll_idx_to_fw_idx)(u32 pll_idx); + void (*init_firmware_loader)(struct hl_device *hdev); + void (*init_cpu_scrambler_dram)(struct hl_device *hdev); }; @@ -1262,6 +1430,7 @@ struct hl_userptr { * @staged_sequence: the sequence of the staged submission this CS is part of, * relevant only if staged_cs is set. * @timeout_jiffies: cs timeout in jiffies. + * @submission_time_jiffies: submission time of the cs * @type: CS_TYPE_*. * @submitted: true if CS was submitted to H/W. * @completed: true if CS was completed by device. @@ -1274,6 +1443,8 @@ struct hl_userptr { * @staged_first: true if this is the first staged CS and we need to receive * timeout for this CS. * @staged_cs: true if this CS is part of a staged submission. + * @skip_reset_on_timeout: true if we shall not reset the device in case + * timeout occurs (debug scenario). */ struct hl_cs { u16 *jobs_in_queue_cnt; @@ -1291,6 +1462,7 @@ struct hl_cs { u64 sequence; u64 staged_sequence; u64 timeout_jiffies; + u64 submission_time_jiffies; enum hl_cs_type type; u8 submitted; u8 completed; @@ -1301,6 +1473,7 @@ struct hl_cs { u8 staged_last; u8 staged_first; u8 staged_cs; + u8 skip_reset_on_timeout; }; /** @@ -1922,7 +2095,7 @@ struct hl_mmu_funcs { * @kernel_queues: array of hl_hw_queue. * @cs_mirror_list: CS mirror list for TDR. * @cs_mirror_lock: protects cs_mirror_list. - * @kernel_cb_mgr: command buffer manager for creating/destroying/handling CGs. + * @kernel_cb_mgr: command buffer manager for creating/destroying/handling CBs. * @event_queue: event queue for IRQ from CPU-CP. * @dma_pool: DMA pool for small allocations. * @cpu_accessible_dma_mem: Host <-> CPU-CP shared memory CPU address. @@ -1954,6 +2127,8 @@ struct hl_mmu_funcs { * @aggregated_cs_counters: aggregated cs counters among all contexts * @mmu_priv: device-specific MMU data. * @mmu_func: device-related MMU functions. + * @fw_loader: FW loader manager. + * @pci_mem_region: array of memory regions in the PCI * @dram_used_mem: current DRAM memory consumption. * @timeout_jiffies: device CS timeout value. * @max_power: the max power of the device, as configured by the sysadmin. This @@ -1968,6 +2143,11 @@ struct hl_mmu_funcs { * the error will be ignored by the driver during * device initialization. Mainly used to debug and * workaround firmware bugs + * @last_successful_open_jif: timestamp (jiffies) of the last successful + * device open. + * @last_open_session_duration_jif: duration (jiffies) of the last device open + * session. + * @open_counter: number of successful device open operations. * @in_reset: is device in reset flow. * @curr_pll_profile: current PLL profile. * @card_type: Various ASICs have several card types. This indicates the card @@ -2007,6 +2187,8 @@ struct hl_mmu_funcs { * @collective_mon_idx: helper index for collective initialization * @supports_coresight: is CoreSight supported. * @supports_soft_reset: is soft reset supported. + * @allow_external_soft_reset: true if soft reset initiated by user or TDR is + * allowed. * @supports_cb_mapping: is mapping a CB to the device's MMU supported. * @needs_reset: true if reset_on_lockup is false and device should be reset * due to lockup. @@ -2015,6 +2197,14 @@ struct hl_mmu_funcs { * @device_fini_pending: true if device_fini was called and might be * waiting for the reset thread to finish * @supports_staged_submission: true if staged submissions are supported + * @curr_reset_cause: saves an enumerated reset cause when a hard reset is + * triggered, and cleared after it is shared with preboot. + * @skip_reset_on_timeout: Skip device reset if CS has timed out, wait for it to + * complete instead. + * @device_cpu_is_halted: Flag to indicate whether the device CPU was already + * halted. We can't halt it again because the COMMS + * protocol will throw an error. Relevant only for + * cases where Linux was not loaded to device CPU */ struct hl_device { struct pci_dev *pdev; @@ -2079,11 +2269,18 @@ struct hl_device { struct hl_mmu_priv mmu_priv; struct hl_mmu_funcs mmu_func[MMU_NUM_PGT_LOCATIONS]; + struct fw_load_mgr fw_loader; + + struct pci_mem_region pci_mem_region[PCI_REGION_NUMBER]; + atomic64_t dram_used_mem; u64 timeout_jiffies; u64 max_power; u64 clock_gating_mask; u64 boot_error_status_mask; + u64 last_successful_open_jif; + u64 last_open_session_duration_jif; + u64 open_counter; atomic_t in_reset; enum hl_pll_frequency curr_pll_profile; enum cpucp_card_types card_type; @@ -2116,11 +2313,15 @@ struct hl_device { u8 collective_mon_idx; u8 supports_coresight; u8 supports_soft_reset; + u8 allow_external_soft_reset; u8 supports_cb_mapping; u8 needs_reset; u8 process_kill_trial_cnt; u8 device_fini_pending; u8 supports_staged_submission; + u8 curr_reset_cause; + u8 skip_reset_on_timeout; + u8 device_cpu_is_halted; /* Parameters for bring-up */ u64 nic_ports_mask; @@ -2138,6 +2339,7 @@ struct hl_device { u8 rl_enable; u8 reset_on_preboot_fail; u8 reset_upon_device_release; + u8 reset_if_device_not_idle; }; @@ -2384,11 +2586,13 @@ void hl_fw_cpu_accessible_dma_pool_free(struct hl_device *hdev, size_t size, void *vaddr); int hl_fw_send_heartbeat(struct hl_device *hdev); int hl_fw_cpucp_info_get(struct hl_device *hdev, - u32 cpu_security_boot_status_reg, - u32 boot_err0_reg); + u32 sts_boot_dev_sts0_reg, + u32 sts_boot_dev_sts1_reg, u32 boot_err0_reg, + u32 boot_err1_reg); int hl_fw_cpucp_handshake(struct hl_device *hdev, - u32 cpu_security_boot_status_reg, - u32 boot_err0_reg); + u32 sts_boot_dev_sts0_reg, + u32 sts_boot_dev_sts1_reg, u32 boot_err0_reg, + u32 boot_err1_reg); int hl_fw_get_eeprom_data(struct hl_device *hdev, void *data, size_t max_size); int hl_fw_cpucp_pci_counters_get(struct hl_device *hdev, struct hl_info_pci_counters *counters); @@ -2399,14 +2603,17 @@ int get_used_pll_index(struct hl_device *hdev, u32 input_pll_index, int hl_fw_cpucp_pll_info_get(struct hl_device *hdev, u32 pll_index, u16 *pll_freq_arr); int hl_fw_cpucp_power_get(struct hl_device *hdev, u64 *power); -int hl_fw_init_cpu(struct hl_device *hdev, u32 cpu_boot_status_reg, - u32 msg_to_cpu_reg, u32 cpu_msg_status_reg, - u32 cpu_security_boot_status_reg, u32 boot_err0_reg, - bool skip_bmc, u32 cpu_timeout, u32 boot_fit_timeout); +void hl_fw_ask_hard_reset_without_linux(struct hl_device *hdev); +void hl_fw_ask_halt_machine_without_linux(struct hl_device *hdev); +int hl_fw_init_cpu(struct hl_device *hdev); int hl_fw_read_preboot_status(struct hl_device *hdev, u32 cpu_boot_status_reg, - u32 cpu_security_boot_status_reg, u32 boot_err0_reg, - u32 timeout); - + u32 sts_boot_dev_sts0_reg, + u32 sts_boot_dev_sts1_reg, u32 boot_err0_reg, + u32 boot_err1_reg, u32 timeout); +int hl_fw_dynamic_send_protocol_cmd(struct hl_device *hdev, + struct fw_load_mgr *fw_loader, + enum comms_cmd cmd, unsigned int size, + bool wait_ok, u32 timeout); int hl_pci_bars_map(struct hl_device *hdev, const char * const name[3], bool is_wc[3]); int hl_pci_elbi_read(struct hl_device *hdev, u64 addr, u32 *data); @@ -2415,6 +2622,7 @@ int hl_pci_set_inbound_region(struct hl_device *hdev, u8 region, struct hl_inbound_pci_region *pci_region); int hl_pci_set_outbound_region(struct hl_device *hdev, struct hl_outbound_pci_region *pci_region); +enum pci_region hl_get_pci_memory_region(struct hl_device *hdev, u64 addr); int hl_pci_init(struct hl_device *hdev); void hl_pci_fini(struct hl_device *hdev); @@ -2443,6 +2651,8 @@ int hl_set_voltage(struct hl_device *hdev, int hl_set_current(struct hl_device *hdev, int sensor_index, u32 attr, long value); void hl_release_pending_user_interrupts(struct hl_device *hdev); +int hl_cs_signal_sob_wraparound_handler(struct hl_device *hdev, u32 q_idx, + struct hl_hw_sob **hw_sob, u32 count); #ifdef CONFIG_DEBUG_FS diff --git a/drivers/misc/habanalabs/common/habanalabs_drv.c b/drivers/misc/habanalabs/common/habanalabs_drv.c index 64d1530db985..4194cda2d04c 100644 --- a/drivers/misc/habanalabs/common/habanalabs_drv.c +++ b/drivers/misc/habanalabs/common/habanalabs_drv.c @@ -29,7 +29,7 @@ static DEFINE_MUTEX(hl_devs_idr_lock); static int timeout_locked = 30; static int reset_on_lockup = 1; -static int memory_scrub = 1; +static int memory_scrub; static ulong boot_error_status_mask = ULONG_MAX; module_param(timeout_locked, int, 0444); @@ -42,7 +42,7 @@ MODULE_PARM_DESC(reset_on_lockup, module_param(memory_scrub, int, 0444); MODULE_PARM_DESC(memory_scrub, - "Scrub device memory in various states (0 = no, 1 = yes, default yes)"); + "Scrub device memory in various states (0 = no, 1 = yes, default no)"); module_param(boot_error_status_mask, ulong, 0444); MODULE_PARM_DESC(boot_error_status_mask, @@ -187,6 +187,9 @@ int hl_device_open(struct inode *inode, struct file *filp) hl_debugfs_add_file(hpriv); + hdev->open_counter++; + hdev->last_successful_open_jif = jiffies; + return 0; out_err: @@ -264,6 +267,7 @@ static void set_driver_behavior_per_device(struct hl_device *hdev) hdev->bmc_enable = 1; hdev->hard_reset_on_fw_events = 1; hdev->reset_on_preboot_fail = 1; + hdev->reset_if_device_not_idle = 1; hdev->reset_pcilink = 0; hdev->axi_drain = 0; @@ -308,10 +312,10 @@ int create_hdev(struct hl_device **dev, struct pci_dev *pdev, } if (pdev) - hdev->asic_prop.fw_security_disabled = - !is_asic_secured(pdev->device); + hdev->asic_prop.fw_security_enabled = + is_asic_secured(hdev->asic_type); else - hdev->asic_prop.fw_security_disabled = true; + hdev->asic_prop.fw_security_enabled = false; /* Assign status description string */ strncpy(hdev->status[HL_DEVICE_STATUS_MALFUNCTION], @@ -325,11 +329,14 @@ int create_hdev(struct hl_device **dev, struct pci_dev *pdev, hdev->reset_on_lockup = reset_on_lockup; hdev->memory_scrub = memory_scrub; hdev->boot_error_status_mask = boot_error_status_mask; + hdev->stop_on_err = true; hdev->pldm = 0; set_driver_behavior_per_device(hdev); + hdev->curr_reset_cause = HL_RESET_CAUSE_UNKNOWN; + if (timeout_locked) hdev->timeout_jiffies = msecs_to_jiffies(timeout_locked * 1000); else @@ -464,6 +471,7 @@ static int hl_pci_probe(struct pci_dev *pdev, return 0; disable_device: + pci_disable_pcie_error_reporting(pdev); pci_set_drvdata(pdev, NULL); destroy_hdev(hdev); @@ -572,7 +580,11 @@ static struct pci_driver hl_pci_driver = { .probe = hl_pci_probe, .remove = hl_pci_remove, .shutdown = hl_pci_remove, - .driver.pm = &hl_pm_ops, + .driver = { + .name = HL_NAME, + .pm = &hl_pm_ops, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, .err_handler = &hl_pci_err_handler, }; diff --git a/drivers/misc/habanalabs/common/habanalabs_ioctl.c b/drivers/misc/habanalabs/common/habanalabs_ioctl.c index 33841c272eb6..f4dda7b4acdd 100644 --- a/drivers/misc/habanalabs/common/habanalabs_ioctl.c +++ b/drivers/misc/habanalabs/common/habanalabs_ioctl.c @@ -95,7 +95,7 @@ static int hw_ip_info(struct hl_device *hdev, struct hl_info_args *args) hw_ip.first_available_interrupt_id = prop->first_available_user_msix_interrupt; return copy_to_user(out, &hw_ip, - min((size_t)size, sizeof(hw_ip))) ? -EFAULT : 0; + min((size_t) size, sizeof(hw_ip))) ? -EFAULT : 0; } static int hw_events_info(struct hl_device *hdev, bool aggregate, @@ -460,6 +460,24 @@ static int power_info(struct hl_fpriv *hpriv, struct hl_info_args *args) min((size_t) max_size, sizeof(power_info))) ? -EFAULT : 0; } +static int open_stats_info(struct hl_fpriv *hpriv, struct hl_info_args *args) +{ + struct hl_device *hdev = hpriv->hdev; + u32 max_size = args->return_size; + struct hl_open_stats_info open_stats_info = {0}; + void __user *out = (void __user *) (uintptr_t) args->return_pointer; + + if ((!max_size) || (!out)) + return -EINVAL; + + open_stats_info.last_open_period_ms = jiffies64_to_msecs( + hdev->last_open_session_duration_jif); + open_stats_info.open_counter = hdev->open_counter; + + return copy_to_user(out, &open_stats_info, + min((size_t) max_size, sizeof(open_stats_info))) ? -EFAULT : 0; +} + static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data, struct device *dev) { @@ -543,6 +561,9 @@ static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data, case HL_INFO_POWER: return power_info(hpriv, args); + case HL_INFO_OPEN_STATS: + return open_stats_info(hpriv, args); + default: dev_err(dev, "Invalid request %d\n", args->op); rc = -ENOTTY; diff --git a/drivers/misc/habanalabs/common/hw_queue.c b/drivers/misc/habanalabs/common/hw_queue.c index 173438461835..bcabfdbf1e01 100644 --- a/drivers/misc/habanalabs/common/hw_queue.c +++ b/drivers/misc/habanalabs/common/hw_queue.c @@ -410,19 +410,20 @@ static void hw_queue_schedule_job(struct hl_cs_job *job) ext_and_hw_queue_submit_bd(hdev, q, ctl, len, ptr); } -static void init_signal_cs(struct hl_device *hdev, +static int init_signal_cs(struct hl_device *hdev, struct hl_cs_job *job, struct hl_cs_compl *cs_cmpl) { struct hl_sync_stream_properties *prop; struct hl_hw_sob *hw_sob; u32 q_idx; + int rc = 0; q_idx = job->hw_queue_id; prop = &hdev->kernel_queues[q_idx].sync_stream_prop; hw_sob = &prop->hw_sob[prop->curr_sob_offset]; cs_cmpl->hw_sob = hw_sob; - cs_cmpl->sob_val = prop->next_sob_val++; + cs_cmpl->sob_val = prop->next_sob_val; dev_dbg(hdev->dev, "generate signal CB, sob_id: %d, sob val: 0x%x, q_idx: %d\n", @@ -434,24 +435,9 @@ static void init_signal_cs(struct hl_device *hdev, hdev->asic_funcs->gen_signal_cb(hdev, job->patched_cb, cs_cmpl->hw_sob->sob_id, 0, true); - kref_get(&hw_sob->kref); + rc = hl_cs_signal_sob_wraparound_handler(hdev, q_idx, &hw_sob, 1); - /* check for wraparound */ - if (prop->next_sob_val == HL_MAX_SOB_VAL) { - /* - * Decrement as we reached the max value. - * The release function won't be called here as we've - * just incremented the refcount. - */ - kref_put(&hw_sob->kref, hl_sob_reset_error); - prop->next_sob_val = 1; - /* only two SOBs are currently in use */ - prop->curr_sob_offset = - (prop->curr_sob_offset + 1) % HL_RSVD_SOBS; - - dev_dbg(hdev->dev, "switched to SOB %d, q_idx: %d\n", - prop->curr_sob_offset, q_idx); - } + return rc; } static void init_wait_cs(struct hl_device *hdev, struct hl_cs *cs, @@ -504,22 +490,25 @@ static void init_wait_cs(struct hl_device *hdev, struct hl_cs *cs, * * H/W queues spinlock should be taken before calling this function */ -static void init_signal_wait_cs(struct hl_cs *cs) +static int init_signal_wait_cs(struct hl_cs *cs) { struct hl_ctx *ctx = cs->ctx; struct hl_device *hdev = ctx->hdev; struct hl_cs_job *job; struct hl_cs_compl *cs_cmpl = container_of(cs->fence, struct hl_cs_compl, base_fence); + int rc = 0; /* There is only one job in a signal/wait CS */ job = list_first_entry(&cs->job_list, struct hl_cs_job, cs_node); if (cs->type & CS_TYPE_SIGNAL) - init_signal_cs(hdev, job, cs_cmpl); + rc = init_signal_cs(hdev, job, cs_cmpl); else if (cs->type & CS_TYPE_WAIT) init_wait_cs(hdev, cs, job, cs_cmpl); + + return rc; } /* @@ -590,11 +579,16 @@ int hl_hw_queue_schedule_cs(struct hl_cs *cs) } } - if ((cs->type == CS_TYPE_SIGNAL) || (cs->type == CS_TYPE_WAIT)) - init_signal_wait_cs(cs); - else if (cs->type == CS_TYPE_COLLECTIVE_WAIT) + if ((cs->type == CS_TYPE_SIGNAL) || (cs->type == CS_TYPE_WAIT)) { + rc = init_signal_wait_cs(cs); + if (rc) { + dev_err(hdev->dev, "Failed to submit signal cs\n"); + goto unroll_cq_resv; + } + } else if (cs->type == CS_TYPE_COLLECTIVE_WAIT) hdev->asic_funcs->collective_wait_init_cs(cs); + spin_lock(&hdev->cs_mirror_lock); /* Verify staged CS exists and add to the staged list */ diff --git a/drivers/misc/habanalabs/common/irq.c b/drivers/misc/habanalabs/common/irq.c index 27129868c711..39b14a933393 100644 --- a/drivers/misc/habanalabs/common/irq.c +++ b/drivers/misc/habanalabs/common/irq.c @@ -207,17 +207,33 @@ irqreturn_t hl_irq_handler_eq(int irq, void *arg) struct hl_eq_entry *eq_entry; struct hl_eq_entry *eq_base; struct hl_eqe_work *handle_eqe_work; + bool entry_ready; + u32 cur_eqe; + u16 cur_eqe_index; eq_base = eq->kernel_address; while (1) { - bool entry_ready = - ((le32_to_cpu(eq_base[eq->ci].hdr.ctl) & - EQ_CTL_READY_MASK) >> EQ_CTL_READY_SHIFT); + cur_eqe = le32_to_cpu(eq_base[eq->ci].hdr.ctl); + entry_ready = !!FIELD_GET(EQ_CTL_READY_MASK, cur_eqe); if (!entry_ready) break; + cur_eqe_index = FIELD_GET(EQ_CTL_INDEX_MASK, cur_eqe); + if ((hdev->event_queue.check_eqe_index) && + (((eq->prev_eqe_index + 1) & EQ_CTL_INDEX_MASK) + != cur_eqe_index)) { + dev_dbg(hdev->dev, + "EQE 0x%x in queue is ready but index does not match %d!=%d", + eq_base[eq->ci].hdr.ctl, + ((eq->prev_eqe_index + 1) & EQ_CTL_INDEX_MASK), + cur_eqe_index); + break; + } + + eq->prev_eqe_index++; + eq_entry = &eq_base[eq->ci]; /* @@ -341,6 +357,7 @@ int hl_eq_init(struct hl_device *hdev, struct hl_eq *q) q->hdev = hdev; q->kernel_address = p; q->ci = 0; + q->prev_eqe_index = 0; return 0; } @@ -365,6 +382,7 @@ void hl_eq_fini(struct hl_device *hdev, struct hl_eq *q) void hl_eq_reset(struct hl_device *hdev, struct hl_eq *q) { q->ci = 0; + q->prev_eqe_index = 0; /* * It's not enough to just reset the PI/CI because the H/W may have diff --git a/drivers/misc/habanalabs/common/memory.c b/drivers/misc/habanalabs/common/memory.c index 2938cbbafbbc..af339ce1ab4f 100644 --- a/drivers/misc/habanalabs/common/memory.c +++ b/drivers/misc/habanalabs/common/memory.c @@ -570,8 +570,10 @@ static u64 get_va_block(struct hl_device *hdev, if ((is_align_pow_2 && (hint_addr & (va_block_align - 1))) || (!is_align_pow_2 && do_div(tmp_hint_addr, va_range->page_size))) { - dev_info(hdev->dev, "Hint address 0x%llx will be ignored\n", - hint_addr); + + dev_dbg(hdev->dev, + "Hint address 0x%llx will be ignored because it is not aligned\n", + hint_addr); hint_addr = 0; } @@ -1117,7 +1119,8 @@ static int map_device_va(struct hl_ctx *ctx, struct hl_mem_in *args, goto map_err; } - rc = hdev->asic_funcs->mmu_invalidate_cache(hdev, false, *vm_type); + rc = hdev->asic_funcs->mmu_invalidate_cache_range(hdev, false, + *vm_type, ctx->asid, ret_vaddr, phys_pg_pack->total_size); mutex_unlock(&ctx->mmu_lock); @@ -1261,8 +1264,9 @@ static int unmap_device_va(struct hl_ctx *ctx, struct hl_mem_in *args, * at the loop end rather than for each iteration */ if (!ctx_free) - rc = hdev->asic_funcs->mmu_invalidate_cache(hdev, true, - *vm_type); + rc = hdev->asic_funcs->mmu_invalidate_cache_range(hdev, true, + *vm_type, ctx->asid, vaddr, + phys_pg_pack->total_size); mutex_unlock(&ctx->mmu_lock); @@ -1369,12 +1373,7 @@ int hl_hw_block_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma) /* Driver only allows mapping of a complete HW block */ block_size = vma->vm_end - vma->vm_start; -#ifdef _HAS_TYPE_ARG_IN_ACCESS_OK - if (!access_ok(VERIFY_WRITE, - (void __user *) (uintptr_t) vma->vm_start, block_size)) { -#else if (!access_ok((void __user *) (uintptr_t) vma->vm_start, block_size)) { -#endif dev_err(hdev->dev, "user pointer is invalid - 0x%lx\n", vma->vm_start); @@ -1608,7 +1607,8 @@ static int get_user_memory(struct hl_device *hdev, u64 addr, u64 size, if (rc != npages) { dev_err(hdev->dev, - "Failed to map host memory, user ptr probably wrong\n"); + "Failed (%d) to pin host memory with user ptr 0x%llx, size 0x%llx, npages %d\n", + rc, addr, size, npages); if (rc < 0) goto destroy_pages; npages = rc; diff --git a/drivers/misc/habanalabs/common/mmu/mmu.c b/drivers/misc/habanalabs/common/mmu/mmu.c index b37189956b14..792d25b79ea6 100644 --- a/drivers/misc/habanalabs/common/mmu/mmu.c +++ b/drivers/misc/habanalabs/common/mmu/mmu.c @@ -501,12 +501,20 @@ static void hl_mmu_pa_page_with_offset(struct hl_ctx *ctx, u64 virt_addr, if ((hops->range_type == HL_VA_RANGE_TYPE_DRAM) && !is_power_of_2(prop->dram_page_size)) { - u32 bit; + unsigned long dram_page_size = prop->dram_page_size; u64 page_offset_mask; u64 phys_addr_mask; + u32 bit; - bit = __ffs64((u64)prop->dram_page_size); - page_offset_mask = ((1ull << bit) - 1); + /* + * find last set bit in page_size to cover all bits of page + * offset. note that 1 has to be added to bit index. + * note that the internal ulong variable is used to avoid + * alignment issue. + */ + bit = find_last_bit(&dram_page_size, + sizeof(dram_page_size) * BITS_PER_BYTE) + 1; + page_offset_mask = (BIT_ULL(bit) - 1); phys_addr_mask = ~page_offset_mask; *phys_addr = (tmp_phys_addr & phys_addr_mask) | (virt_addr & page_offset_mask); diff --git a/drivers/misc/habanalabs/common/pci/pci.c b/drivers/misc/habanalabs/common/pci/pci.c index e941b7eef346..d5bedf5ba011 100644 --- a/drivers/misc/habanalabs/common/pci/pci.c +++ b/drivers/misc/habanalabs/common/pci/pci.c @@ -10,7 +10,7 @@ #include <linux/pci.h> -#define HL_PLDM_PCI_ELBI_TIMEOUT_MSEC (HL_PCI_ELBI_TIMEOUT_MSEC * 10) +#define HL_PLDM_PCI_ELBI_TIMEOUT_MSEC (HL_PCI_ELBI_TIMEOUT_MSEC * 100) #define IATU_REGION_CTRL_REGION_EN_MASK BIT(31) #define IATU_REGION_CTRL_MATCH_MODE_MASK BIT(30) @@ -360,6 +360,32 @@ int hl_pci_set_outbound_region(struct hl_device *hdev, } /** + * hl_get_pci_memory_region() - get PCI region for given address + * @hdev: Pointer to hl_device structure. + * @addr: device address + * + * @return region index on success, otherwise PCI_REGION_NUMBER (invalid + * region index) + */ +enum pci_region hl_get_pci_memory_region(struct hl_device *hdev, u64 addr) +{ + int i; + + for (i = 0 ; i < PCI_REGION_NUMBER ; i++) { + struct pci_mem_region *region = &hdev->pci_mem_region[i]; + + if (!region->used) + continue; + + if ((addr >= region->region_base) && + (addr < region->region_base + region->region_size)) + return i; + } + + return PCI_REGION_NUMBER; +} + +/** * hl_pci_init() - PCI initialization code. * @hdev: Pointer to hl_device structure. * @@ -395,6 +421,12 @@ int hl_pci_init(struct hl_device *hdev) goto unmap_pci_bars; } + /* Driver must sleep in order for FW to finish the iATU configuration */ + if (hdev->asic_prop.iatu_done_by_fw) { + usleep_range(2000, 3000); + hdev->asic_funcs->set_dma_mask_from_fw(hdev); + } + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(hdev->dma_mask)); if (rc) { diff --git a/drivers/misc/habanalabs/common/sysfs.c b/drivers/misc/habanalabs/common/sysfs.c index c9f649b31e3a..db72df282ef8 100644 --- a/drivers/misc/habanalabs/common/sysfs.c +++ b/drivers/misc/habanalabs/common/sysfs.c @@ -208,7 +208,7 @@ static ssize_t soft_reset_store(struct device *dev, goto out; } - if (!hdev->supports_soft_reset) { + if (!hdev->allow_external_soft_reset) { dev_err(hdev->dev, "Device does not support soft-reset\n"); goto out; } diff --git a/drivers/misc/habanalabs/gaudi/gaudi.c b/drivers/misc/habanalabs/gaudi/gaudi.c index 9e4a6bb3acd1..aa8a0ca5aca2 100644 --- a/drivers/misc/habanalabs/gaudi/gaudi.c +++ b/drivers/misc/habanalabs/gaudi/gaudi.c @@ -78,6 +78,7 @@ #define GAUDI_PLDM_TPC_KERNEL_WAIT_USEC (HL_DEVICE_TIMEOUT_USEC * 30) #define GAUDI_BOOT_FIT_REQ_TIMEOUT_USEC 1000000 /* 1s */ #define GAUDI_MSG_TO_CPU_TIMEOUT_USEC 4000000 /* 4s */ +#define GAUDI_WAIT_FOR_BL_TIMEOUT_USEC 15000000 /* 15s */ #define GAUDI_QMAN0_FENCE_VAL 0x72E91AB9 @@ -409,7 +410,7 @@ static inline void set_default_power_values(struct hl_device *hdev) } } -static int gaudi_get_fixed_properties(struct hl_device *hdev) +static int gaudi_set_fixed_properties(struct hl_device *hdev) { struct asic_fixed_properties *prop = &hdev->asic_prop; u32 num_sync_stream_queues = 0; @@ -545,8 +546,10 @@ static int gaudi_get_fixed_properties(struct hl_device *hdev) for (i = 0 ; i < HL_MAX_DCORES ; i++) prop->first_available_cq[i] = USHRT_MAX; - prop->fw_security_status_valid = false; + prop->fw_cpu_boot_dev_sts0_valid = false; + prop->fw_cpu_boot_dev_sts1_valid = false; prop->hard_reset_done_by_fw = false; + prop->gic_interrupts_enable = true; return 0; } @@ -577,6 +580,9 @@ static u64 gaudi_set_hbm_bar_base(struct hl_device *hdev, u64 addr) if ((gaudi) && (gaudi->hbm_bar_cur_addr == addr)) return old_addr; + if (hdev->asic_prop.iatu_done_by_fw) + return U64_MAX; + /* Inbound Region 2 - Bar 4 - Point to HBM */ pci_region.mode = PCI_BAR_MATCH_MODE; pci_region.bar = HBM_BAR_ID; @@ -599,10 +605,8 @@ static int gaudi_init_iatu(struct hl_device *hdev) struct hl_outbound_pci_region outbound_region; int rc; - if (hdev->asic_prop.iatu_done_by_fw) { - hdev->asic_funcs->set_dma_mask_from_fw(hdev); + if (hdev->asic_prop.iatu_done_by_fw) return 0; - } /* Inbound Region 0 - Bar 0 - Point to SRAM + CFG */ inbound_region.mode = PCI_BAR_MATCH_MODE; @@ -651,9 +655,9 @@ static int gaudi_early_init(struct hl_device *hdev) u32 fw_boot_status; int rc; - rc = gaudi_get_fixed_properties(hdev); + rc = gaudi_set_fixed_properties(hdev); if (rc) { - dev_err(hdev->dev, "Failed to get fixed properties\n"); + dev_err(hdev->dev, "Failed setting fixed properties\n"); return rc; } @@ -683,8 +687,14 @@ static int gaudi_early_init(struct hl_device *hdev) prop->dram_pci_bar_size = pci_resource_len(pdev, HBM_BAR_ID); /* If FW security is enabled at this point it means no access to ELBI */ - if (!hdev->asic_prop.fw_security_disabled) { + if (hdev->asic_prop.fw_security_enabled) { hdev->asic_prop.iatu_done_by_fw = true; + + /* + * GIC-security-bit can ONLY be set by CPUCP, so in this stage + * decision can only be taken based on PCI ID security. + */ + hdev->asic_prop.gic_interrupts_enable = false; goto pci_init; } @@ -707,8 +717,10 @@ pci_init: * version to determine whether we run with a security-enabled firmware */ rc = hl_fw_read_preboot_status(hdev, mmPSOC_GLOBAL_CONF_CPU_BOOT_STATUS, - mmCPU_BOOT_DEV_STS0, mmCPU_BOOT_ERR0, - GAUDI_BOOT_FIT_REQ_TIMEOUT_USEC); + mmCPU_BOOT_DEV_STS0, + mmCPU_BOOT_DEV_STS1, mmCPU_BOOT_ERR0, + mmCPU_BOOT_ERR1, + GAUDI_BOOT_FIT_REQ_TIMEOUT_USEC); if (rc) { if (hdev->reset_on_preboot_fail) hdev->asic_funcs->hw_fini(hdev, true); @@ -751,7 +763,14 @@ static int gaudi_fetch_psoc_frequency(struct hl_device *hdev) u16 pll_freq_arr[HL_PLL_NUM_OUTPUTS], freq; int rc; - if (hdev->asic_prop.fw_security_disabled) { + if (hdev->asic_prop.fw_security_enabled) { + rc = hl_fw_cpucp_pll_info_get(hdev, HL_GAUDI_CPU_PLL, pll_freq_arr); + + if (rc) + return rc; + + freq = pll_freq_arr[2]; + } else { /* Backward compatibility */ div_fctr = RREG32(mmPSOC_CPU_PLL_DIV_FACTOR_2); div_sel = RREG32(mmPSOC_CPU_PLL_DIV_SEL_2); @@ -779,13 +798,6 @@ static int gaudi_fetch_psoc_frequency(struct hl_device *hdev) div_sel); freq = 0; } - } else { - rc = hl_fw_cpucp_pll_info_get(hdev, HL_GAUDI_CPU_PLL, pll_freq_arr); - - if (rc) - return rc; - - freq = pll_freq_arr[2]; } prop->psoc_timestamp_frequency = freq; @@ -988,9 +1000,27 @@ static void gaudi_sob_group_reset_error(struct kref *ref) hw_sob_group->base_sob_id); } +static void gaudi_collective_mstr_sob_mask_set(struct gaudi_device *gaudi) +{ + struct gaudi_collective_properties *prop; + int i; + + prop = &gaudi->collective_props; + + memset(prop->mstr_sob_mask, 0, sizeof(prop->mstr_sob_mask)); + + for (i = 0 ; i < NIC_NUMBER_OF_ENGINES ; i++) + if (gaudi->hw_cap_initialized & BIT(HW_CAP_NIC_SHIFT + i)) + prop->mstr_sob_mask[i / HL_MAX_SOBS_PER_MONITOR] |= + BIT(i % HL_MAX_SOBS_PER_MONITOR); + /* Set collective engine bit */ + prop->mstr_sob_mask[i / HL_MAX_SOBS_PER_MONITOR] |= + BIT(i % HL_MAX_SOBS_PER_MONITOR); +} + static int gaudi_collective_init(struct hl_device *hdev) { - u32 i, master_monitor_sobs, sob_id, reserved_sobs_per_group; + u32 i, sob_id, reserved_sobs_per_group; struct gaudi_collective_properties *prop; struct gaudi_device *gaudi; @@ -1016,22 +1046,7 @@ static int gaudi_collective_init(struct hl_device *hdev) gaudi_collective_map_sobs(hdev, i); } - prop->mstr_sob_mask[0] = 0; - master_monitor_sobs = HL_MAX_SOBS_PER_MONITOR; - for (i = 0 ; i < master_monitor_sobs ; i++) - if (gaudi->hw_cap_initialized & BIT(HW_CAP_NIC_SHIFT + i)) - prop->mstr_sob_mask[0] |= BIT(i); - - prop->mstr_sob_mask[1] = 0; - master_monitor_sobs = - NIC_NUMBER_OF_ENGINES - HL_MAX_SOBS_PER_MONITOR; - for (i = 0 ; i < master_monitor_sobs; i++) { - if (gaudi->hw_cap_initialized & BIT(HW_CAP_NIC_SHIFT + i)) - prop->mstr_sob_mask[1] |= BIT(i); - } - - /* Set collective engine bit */ - prop->mstr_sob_mask[1] |= BIT(i); + gaudi_collective_mstr_sob_mask_set(gaudi); return 0; } @@ -1513,7 +1528,7 @@ static int gaudi_alloc_cpu_accessible_dma_mem(struct hl_device *hdev) hdev->cpu_pci_msb_addr = GAUDI_CPU_PCI_MSB_ADDR(hdev->cpu_accessible_dma_address); - if (hdev->asic_prop.fw_security_disabled) + if (!hdev->asic_prop.fw_security_enabled) GAUDI_PCI_TO_CPU_ADDR(hdev->cpu_accessible_dma_address); free_dma_mem_arr: @@ -1590,6 +1605,48 @@ free_internal_qmans_pq_mem: return rc; } +static void gaudi_set_pci_memory_regions(struct hl_device *hdev) +{ + struct asic_fixed_properties *prop = &hdev->asic_prop; + struct pci_mem_region *region; + + /* CFG */ + region = &hdev->pci_mem_region[PCI_REGION_CFG]; + region->region_base = CFG_BASE; + region->region_size = CFG_SIZE; + region->offset_in_bar = CFG_BASE - SPI_FLASH_BASE_ADDR; + region->bar_size = CFG_BAR_SIZE; + region->bar_id = CFG_BAR_ID; + region->used = 1; + + /* SRAM */ + region = &hdev->pci_mem_region[PCI_REGION_SRAM]; + region->region_base = SRAM_BASE_ADDR; + region->region_size = SRAM_SIZE; + region->offset_in_bar = 0; + region->bar_size = SRAM_BAR_SIZE; + region->bar_id = SRAM_BAR_ID; + region->used = 1; + + /* DRAM */ + region = &hdev->pci_mem_region[PCI_REGION_DRAM]; + region->region_base = DRAM_PHYS_BASE; + region->region_size = hdev->asic_prop.dram_size; + region->offset_in_bar = 0; + region->bar_size = prop->dram_pci_bar_size; + region->bar_id = HBM_BAR_ID; + region->used = 1; + + /* SP SRAM */ + region = &hdev->pci_mem_region[PCI_REGION_SP_SRAM]; + region->region_base = PSOC_SCRATCHPAD_ADDR; + region->region_size = PSOC_SCRATCHPAD_SIZE; + region->offset_in_bar = PSOC_SCRATCHPAD_ADDR - SPI_FLASH_BASE_ADDR; + region->bar_size = CFG_BAR_SIZE; + region->bar_id = CFG_BAR_ID; + region->used = 1; +} + static int gaudi_sw_init(struct hl_device *hdev) { struct gaudi_device *gaudi; @@ -1664,12 +1721,14 @@ static int gaudi_sw_init(struct hl_device *hdev) hdev->supports_coresight = true; hdev->supports_staged_submission = true; + gaudi_set_pci_memory_regions(hdev); + return 0; free_cpu_accessible_dma_pool: gen_pool_destroy(hdev->cpu_accessible_dma_pool); free_cpu_dma_mem: - if (hdev->asic_prop.fw_security_disabled) + if (!hdev->asic_prop.fw_security_enabled) GAUDI_CPU_TO_PCI_ADDR(hdev->cpu_accessible_dma_address, hdev->cpu_pci_msb_addr); hdev->asic_funcs->asic_dma_free_coherent(hdev, @@ -1691,7 +1750,7 @@ static int gaudi_sw_fini(struct hl_device *hdev) gen_pool_destroy(hdev->cpu_accessible_dma_pool); - if (hdev->asic_prop.fw_security_disabled) + if (!hdev->asic_prop.fw_security_enabled) GAUDI_CPU_TO_PCI_ADDR(hdev->cpu_accessible_dma_address, hdev->cpu_pci_msb_addr); @@ -1879,12 +1938,11 @@ static void gaudi_init_scrambler_sram(struct hl_device *hdev) { struct gaudi_device *gaudi = hdev->asic_specific; - if (!hdev->asic_prop.fw_security_disabled) + if (hdev->asic_prop.fw_security_enabled) return; - if (hdev->asic_prop.fw_security_status_valid && - (hdev->asic_prop.fw_app_security_map & - CPU_BOOT_DEV_STS0_SRAM_SCR_EN)) + if (hdev->asic_prop.fw_app_cpu_boot_dev_sts0 & + CPU_BOOT_DEV_STS0_SRAM_SCR_EN) return; if (gaudi->hw_cap_initialized & HW_CAP_SRAM_SCRAMBLER) @@ -1951,12 +2009,11 @@ static void gaudi_init_scrambler_hbm(struct hl_device *hdev) { struct gaudi_device *gaudi = hdev->asic_specific; - if (!hdev->asic_prop.fw_security_disabled) + if (hdev->asic_prop.fw_security_enabled) return; - if (hdev->asic_prop.fw_security_status_valid && - (hdev->asic_prop.fw_boot_cpu_security_map & - CPU_BOOT_DEV_STS0_DRAM_SCR_EN)) + if (hdev->asic_prop.fw_bootfit_cpu_boot_dev_sts0 & + CPU_BOOT_DEV_STS0_DRAM_SCR_EN) return; if (gaudi->hw_cap_initialized & HW_CAP_HBM_SCRAMBLER) @@ -2021,12 +2078,11 @@ static void gaudi_init_scrambler_hbm(struct hl_device *hdev) static void gaudi_init_e2e(struct hl_device *hdev) { - if (!hdev->asic_prop.fw_security_disabled) + if (hdev->asic_prop.fw_security_enabled) return; - if (hdev->asic_prop.fw_security_status_valid && - (hdev->asic_prop.fw_boot_cpu_security_map & - CPU_BOOT_DEV_STS0_E2E_CRED_EN)) + if (hdev->asic_prop.fw_bootfit_cpu_boot_dev_sts0 & + CPU_BOOT_DEV_STS0_E2E_CRED_EN) return; WREG32(mmSIF_RTR_CTRL_0_E2E_HBM_WR_SIZE, 247 >> 3); @@ -2396,12 +2452,11 @@ static void gaudi_init_hbm_cred(struct hl_device *hdev) { uint32_t hbm0_wr, hbm1_wr, hbm0_rd, hbm1_rd; - if (!hdev->asic_prop.fw_security_disabled) + if (hdev->asic_prop.fw_security_enabled) return; - if (hdev->asic_prop.fw_security_status_valid && - (hdev->asic_prop.fw_boot_cpu_security_map & - CPU_BOOT_DEV_STS0_HBM_CRED_EN)) + if (hdev->asic_prop.fw_bootfit_cpu_boot_dev_sts0 & + CPU_BOOT_DEV_STS0_HBM_CRED_EN) return; hbm0_wr = 0x33333333; @@ -2487,10 +2542,12 @@ static void gaudi_init_golden_registers(struct hl_device *hdev) static void gaudi_init_pci_dma_qman(struct hl_device *hdev, int dma_id, int qman_id, dma_addr_t qman_pq_addr) { + struct cpu_dyn_regs *dyn_regs = + &hdev->fw_loader.dynamic_loader.comm_desc.cpu_dyn_regs; u32 mtr_base_en_lo, mtr_base_en_hi, mtr_base_ws_lo, mtr_base_ws_hi; u32 so_base_en_lo, so_base_en_hi, so_base_ws_lo, so_base_ws_hi; u32 q_off, dma_qm_offset; - u32 dma_qm_err_cfg; + u32 dma_qm_err_cfg, irq_handler_offset; dma_qm_offset = dma_id * DMA_QMAN_OFFSET; @@ -2539,20 +2596,23 @@ static void gaudi_init_pci_dma_qman(struct hl_device *hdev, int dma_id, /* The following configuration is needed only once per QMAN */ if (qman_id == 0) { + irq_handler_offset = hdev->asic_prop.gic_interrupts_enable ? + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR : + le32_to_cpu(dyn_regs->gic_dma_qm_irq_ctrl); + /* Configure RAZWI IRQ */ dma_qm_err_cfg = PCI_DMA_QMAN_GLBL_ERR_CFG_MSG_EN_MASK; - if (hdev->stop_on_err) { + if (hdev->stop_on_err) dma_qm_err_cfg |= PCI_DMA_QMAN_GLBL_ERR_CFG_STOP_ON_ERR_EN_MASK; - } WREG32(mmDMA0_QM_GLBL_ERR_CFG + dma_qm_offset, dma_qm_err_cfg); + WREG32(mmDMA0_QM_GLBL_ERR_ADDR_LO + dma_qm_offset, - lower_32_bits(CFG_BASE + - mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR)); + lower_32_bits(CFG_BASE + irq_handler_offset)); WREG32(mmDMA0_QM_GLBL_ERR_ADDR_HI + dma_qm_offset, - upper_32_bits(CFG_BASE + - mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR)); + upper_32_bits(CFG_BASE + irq_handler_offset)); + WREG32(mmDMA0_QM_GLBL_ERR_WDATA + dma_qm_offset, gaudi_irq_map_table[GAUDI_EVENT_DMA0_QM].cpu_id + dma_id); @@ -2573,8 +2633,11 @@ static void gaudi_init_pci_dma_qman(struct hl_device *hdev, int dma_id, static void gaudi_init_dma_core(struct hl_device *hdev, int dma_id) { - u32 dma_offset = dma_id * DMA_CORE_OFFSET; + struct cpu_dyn_regs *dyn_regs = + &hdev->fw_loader.dynamic_loader.comm_desc.cpu_dyn_regs; u32 dma_err_cfg = 1 << DMA0_CORE_ERR_CFG_ERR_MSG_EN_SHIFT; + u32 dma_offset = dma_id * DMA_CORE_OFFSET; + u32 irq_handler_offset; /* Set to maximum possible according to physical size */ WREG32(mmDMA0_CORE_RD_MAX_OUTSTAND + dma_offset, 0); @@ -2588,10 +2651,16 @@ static void gaudi_init_dma_core(struct hl_device *hdev, int dma_id) dma_err_cfg |= 1 << DMA0_CORE_ERR_CFG_STOP_ON_ERR_SHIFT; WREG32(mmDMA0_CORE_ERR_CFG + dma_offset, dma_err_cfg); + + irq_handler_offset = hdev->asic_prop.gic_interrupts_enable ? + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR : + le32_to_cpu(dyn_regs->gic_dma_core_irq_ctrl); + WREG32(mmDMA0_CORE_ERRMSG_ADDR_LO + dma_offset, - lower_32_bits(CFG_BASE + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR)); + lower_32_bits(CFG_BASE + irq_handler_offset)); WREG32(mmDMA0_CORE_ERRMSG_ADDR_HI + dma_offset, - upper_32_bits(CFG_BASE + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR)); + upper_32_bits(CFG_BASE + irq_handler_offset)); + WREG32(mmDMA0_CORE_ERRMSG_WDATA + dma_offset, gaudi_irq_map_table[GAUDI_EVENT_DMA0_CORE].cpu_id + dma_id); WREG32(mmDMA0_CORE_PROT + dma_offset, @@ -2654,10 +2723,12 @@ static void gaudi_init_pci_dma_qmans(struct hl_device *hdev) static void gaudi_init_hbm_dma_qman(struct hl_device *hdev, int dma_id, int qman_id, u64 qman_base_addr) { + struct cpu_dyn_regs *dyn_regs = + &hdev->fw_loader.dynamic_loader.comm_desc.cpu_dyn_regs; u32 mtr_base_en_lo, mtr_base_en_hi, mtr_base_ws_lo, mtr_base_ws_hi; u32 so_base_en_lo, so_base_en_hi, so_base_ws_lo, so_base_ws_hi; + u32 dma_qm_err_cfg, irq_handler_offset; u32 q_off, dma_qm_offset; - u32 dma_qm_err_cfg; dma_qm_offset = dma_id * DMA_QMAN_OFFSET; @@ -2697,6 +2768,10 @@ static void gaudi_init_hbm_dma_qman(struct hl_device *hdev, int dma_id, WREG32(mmDMA0_QM_CP_LDMA_DST_BASE_LO_OFFSET_0 + q_off, QMAN_CPDMA_DST_OFFSET); } else { + irq_handler_offset = hdev->asic_prop.gic_interrupts_enable ? + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR : + le32_to_cpu(dyn_regs->gic_dma_qm_irq_ctrl); + WREG32(mmDMA0_QM_CP_LDMA_TSIZE_OFFSET_0 + q_off, QMAN_LDMA_SIZE_OFFSET); WREG32(mmDMA0_QM_CP_LDMA_SRC_BASE_LO_OFFSET_0 + q_off, @@ -2706,18 +2781,17 @@ static void gaudi_init_hbm_dma_qman(struct hl_device *hdev, int dma_id, /* Configure RAZWI IRQ */ dma_qm_err_cfg = HBM_DMA_QMAN_GLBL_ERR_CFG_MSG_EN_MASK; - if (hdev->stop_on_err) { + if (hdev->stop_on_err) dma_qm_err_cfg |= HBM_DMA_QMAN_GLBL_ERR_CFG_STOP_ON_ERR_EN_MASK; - } + WREG32(mmDMA0_QM_GLBL_ERR_CFG + dma_qm_offset, dma_qm_err_cfg); WREG32(mmDMA0_QM_GLBL_ERR_ADDR_LO + dma_qm_offset, - lower_32_bits(CFG_BASE + - mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR)); + lower_32_bits(CFG_BASE + irq_handler_offset)); WREG32(mmDMA0_QM_GLBL_ERR_ADDR_HI + dma_qm_offset, - upper_32_bits(CFG_BASE + - mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR)); + upper_32_bits(CFG_BASE + irq_handler_offset)); + WREG32(mmDMA0_QM_GLBL_ERR_WDATA + dma_qm_offset, gaudi_irq_map_table[GAUDI_EVENT_DMA0_QM].cpu_id + dma_id); @@ -2792,8 +2866,11 @@ static void gaudi_init_hbm_dma_qmans(struct hl_device *hdev) static void gaudi_init_mme_qman(struct hl_device *hdev, u32 mme_offset, int qman_id, u64 qman_base_addr) { + struct cpu_dyn_regs *dyn_regs = + &hdev->fw_loader.dynamic_loader.comm_desc.cpu_dyn_regs; u32 mtr_base_lo, mtr_base_hi; u32 so_base_lo, so_base_hi; + u32 irq_handler_offset; u32 q_off, mme_id; u32 mme_qm_err_cfg; @@ -2825,6 +2902,10 @@ static void gaudi_init_mme_qman(struct hl_device *hdev, u32 mme_offset, WREG32(mmMME0_QM_CP_LDMA_DST_BASE_LO_OFFSET_0 + q_off, QMAN_CPDMA_DST_OFFSET); } else { + irq_handler_offset = hdev->asic_prop.gic_interrupts_enable ? + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR : + le32_to_cpu(dyn_regs->gic_mme_qm_irq_ctrl); + WREG32(mmMME0_QM_CP_LDMA_TSIZE_OFFSET_0 + q_off, QMAN_LDMA_SIZE_OFFSET); WREG32(mmMME0_QM_CP_LDMA_SRC_BASE_LO_OFFSET_0 + q_off, @@ -2834,20 +2915,20 @@ static void gaudi_init_mme_qman(struct hl_device *hdev, u32 mme_offset, /* Configure RAZWI IRQ */ mme_id = mme_offset / - (mmMME1_QM_GLBL_CFG0 - mmMME0_QM_GLBL_CFG0); + (mmMME1_QM_GLBL_CFG0 - mmMME0_QM_GLBL_CFG0) / 2; mme_qm_err_cfg = MME_QMAN_GLBL_ERR_CFG_MSG_EN_MASK; - if (hdev->stop_on_err) { + if (hdev->stop_on_err) mme_qm_err_cfg |= MME_QMAN_GLBL_ERR_CFG_STOP_ON_ERR_EN_MASK; - } + WREG32(mmMME0_QM_GLBL_ERR_CFG + mme_offset, mme_qm_err_cfg); + WREG32(mmMME0_QM_GLBL_ERR_ADDR_LO + mme_offset, - lower_32_bits(CFG_BASE + - mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR)); + lower_32_bits(CFG_BASE + irq_handler_offset)); WREG32(mmMME0_QM_GLBL_ERR_ADDR_HI + mme_offset, - upper_32_bits(CFG_BASE + - mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR)); + upper_32_bits(CFG_BASE + irq_handler_offset)); + WREG32(mmMME0_QM_GLBL_ERR_WDATA + mme_offset, gaudi_irq_map_table[GAUDI_EVENT_MME0_QM].cpu_id + mme_id); @@ -2912,10 +2993,12 @@ static void gaudi_init_mme_qmans(struct hl_device *hdev) static void gaudi_init_tpc_qman(struct hl_device *hdev, u32 tpc_offset, int qman_id, u64 qman_base_addr) { + struct cpu_dyn_regs *dyn_regs = + &hdev->fw_loader.dynamic_loader.comm_desc.cpu_dyn_regs; u32 mtr_base_en_lo, mtr_base_en_hi, mtr_base_ws_lo, mtr_base_ws_hi; u32 so_base_en_lo, so_base_en_hi, so_base_ws_lo, so_base_ws_hi; + u32 tpc_qm_err_cfg, irq_handler_offset; u32 q_off, tpc_id; - u32 tpc_qm_err_cfg; mtr_base_en_lo = lower_32_bits(CFG_BASE + mmSYNC_MNGR_E_N_SYNC_MNGR_OBJS_MON_PAY_ADDRL_0); @@ -2956,6 +3039,10 @@ static void gaudi_init_tpc_qman(struct hl_device *hdev, u32 tpc_offset, WREG32(mmTPC0_QM_CP_LDMA_DST_BASE_LO_OFFSET_0 + q_off, QMAN_CPDMA_DST_OFFSET); } else { + irq_handler_offset = hdev->asic_prop.gic_interrupts_enable ? + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR : + le32_to_cpu(dyn_regs->gic_tpc_qm_irq_ctrl); + WREG32(mmTPC0_QM_CP_LDMA_TSIZE_OFFSET_0 + q_off, QMAN_LDMA_SIZE_OFFSET); WREG32(mmTPC0_QM_CP_LDMA_SRC_BASE_LO_OFFSET_0 + q_off, @@ -2965,18 +3052,17 @@ static void gaudi_init_tpc_qman(struct hl_device *hdev, u32 tpc_offset, /* Configure RAZWI IRQ */ tpc_qm_err_cfg = TPC_QMAN_GLBL_ERR_CFG_MSG_EN_MASK; - if (hdev->stop_on_err) { + if (hdev->stop_on_err) tpc_qm_err_cfg |= TPC_QMAN_GLBL_ERR_CFG_STOP_ON_ERR_EN_MASK; - } WREG32(mmTPC0_QM_GLBL_ERR_CFG + tpc_offset, tpc_qm_err_cfg); + WREG32(mmTPC0_QM_GLBL_ERR_ADDR_LO + tpc_offset, - lower_32_bits(CFG_BASE + - mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR)); + lower_32_bits(CFG_BASE + irq_handler_offset)); WREG32(mmTPC0_QM_GLBL_ERR_ADDR_HI + tpc_offset, - upper_32_bits(CFG_BASE + - mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR)); + upper_32_bits(CFG_BASE + irq_handler_offset)); + WREG32(mmTPC0_QM_GLBL_ERR_WDATA + tpc_offset, gaudi_irq_map_table[GAUDI_EVENT_TPC0_QM].cpu_id + tpc_id); @@ -3059,10 +3145,12 @@ static void gaudi_init_tpc_qmans(struct hl_device *hdev) static void gaudi_init_nic_qman(struct hl_device *hdev, u32 nic_offset, int qman_id, u64 qman_base_addr, int nic_id) { + struct cpu_dyn_regs *dyn_regs = + &hdev->fw_loader.dynamic_loader.comm_desc.cpu_dyn_regs; u32 mtr_base_en_lo, mtr_base_en_hi, mtr_base_ws_lo, mtr_base_ws_hi; u32 so_base_en_lo, so_base_en_hi, so_base_ws_lo, so_base_ws_hi; + u32 nic_qm_err_cfg, irq_handler_offset; u32 q_off; - u32 nic_qm_err_cfg; mtr_base_en_lo = lower_32_bits(CFG_BASE + mmSYNC_MNGR_E_N_SYNC_MNGR_OBJS_MON_PAY_ADDRL_0); @@ -3109,20 +3197,23 @@ static void gaudi_init_nic_qman(struct hl_device *hdev, u32 nic_offset, WREG32(mmNIC0_QM0_CP_MSG_BASE3_ADDR_HI_0 + q_off, so_base_ws_hi); if (qman_id == 0) { + irq_handler_offset = hdev->asic_prop.gic_interrupts_enable ? + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR : + le32_to_cpu(dyn_regs->gic_nic_qm_irq_ctrl); + /* Configure RAZWI IRQ */ nic_qm_err_cfg = NIC_QMAN_GLBL_ERR_CFG_MSG_EN_MASK; - if (hdev->stop_on_err) { + if (hdev->stop_on_err) nic_qm_err_cfg |= NIC_QMAN_GLBL_ERR_CFG_STOP_ON_ERR_EN_MASK; - } WREG32(mmNIC0_QM0_GLBL_ERR_CFG + nic_offset, nic_qm_err_cfg); + WREG32(mmNIC0_QM0_GLBL_ERR_ADDR_LO + nic_offset, - lower_32_bits(CFG_BASE + - mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR)); + lower_32_bits(CFG_BASE + irq_handler_offset)); WREG32(mmNIC0_QM0_GLBL_ERR_ADDR_HI + nic_offset, - upper_32_bits(CFG_BASE + - mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR)); + upper_32_bits(CFG_BASE + irq_handler_offset)); + WREG32(mmNIC0_QM0_GLBL_ERR_WDATA + nic_offset, gaudi_irq_map_table[GAUDI_EVENT_NIC0_QM0].cpu_id + nic_id); @@ -3475,7 +3566,7 @@ static void gaudi_set_clock_gating(struct hl_device *hdev) if (hdev->in_debug) return; - if (!hdev->asic_prop.fw_security_disabled) + if (hdev->asic_prop.fw_security_enabled) return; for (i = GAUDI_PCI_DMA_1, qman_offset = 0 ; i < GAUDI_HBM_DMA_1 ; i++) { @@ -3535,7 +3626,7 @@ static void gaudi_disable_clock_gating(struct hl_device *hdev) u32 qman_offset; int i; - if (!hdev->asic_prop.fw_security_disabled) + if (hdev->asic_prop.fw_security_enabled) return; for (i = 0, qman_offset = 0 ; i < DMA_NUMBER_OF_CHANNELS ; i++) { @@ -3674,9 +3765,6 @@ static int gaudi_load_firmware_to_device(struct hl_device *hdev) { void __iomem *dst; - /* HBM scrambler must be initialized before pushing F/W to HBM */ - gaudi_init_scrambler_hbm(hdev); - dst = hdev->pcie_bar[HBM_BAR_ID] + LINUX_FW_OFFSET; return hl_fw_load_fw_to_device(hdev, GAUDI_LINUX_FW_FILE, dst, 0, 0); @@ -3691,42 +3779,71 @@ static int gaudi_load_boot_fit_to_device(struct hl_device *hdev) return hl_fw_load_fw_to_device(hdev, GAUDI_BOOT_FIT_FILE, dst, 0, 0); } -static int gaudi_read_device_fw_version(struct hl_device *hdev, - enum hl_fw_component fwc) +static void gaudi_init_dynamic_firmware_loader(struct hl_device *hdev) { - const char *name; - u32 ver_off; - char *dest; + struct dynamic_fw_load_mgr *dynamic_loader; + struct cpu_dyn_regs *dyn_regs; - switch (fwc) { - case FW_COMP_UBOOT: - ver_off = RREG32(mmUBOOT_VER_OFFSET); - dest = hdev->asic_prop.uboot_ver; - name = "U-Boot"; - break; - case FW_COMP_PREBOOT: - ver_off = RREG32(mmPREBOOT_VER_OFFSET); - dest = hdev->asic_prop.preboot_ver; - name = "Preboot"; - break; - default: - dev_warn(hdev->dev, "Undefined FW component: %d\n", fwc); - return -EIO; - } + dynamic_loader = &hdev->fw_loader.dynamic_loader; - ver_off &= ~((u32)SRAM_BASE_ADDR); + /* + * here we update initial values for few specific dynamic regs (as + * before reading the first descriptor from FW those value has to be + * hard-coded) in later stages of the protocol those values will be + * updated automatically by reading the FW descriptor so data there + * will always be up-to-date + */ + dyn_regs = &dynamic_loader->comm_desc.cpu_dyn_regs; + dyn_regs->kmd_msg_to_cpu = + cpu_to_le32(mmPSOC_GLOBAL_CONF_KMD_MSG_TO_CPU); + dyn_regs->cpu_cmd_status_to_host = + cpu_to_le32(mmCPU_CMD_STATUS_TO_HOST); - if (ver_off < SRAM_SIZE - VERSION_MAX_LEN) { - memcpy_fromio(dest, hdev->pcie_bar[SRAM_BAR_ID] + ver_off, - VERSION_MAX_LEN); - } else { - dev_err(hdev->dev, "%s version offset (0x%x) is above SRAM\n", - name, ver_off); - strcpy(dest, "unavailable"); - return -EIO; - } + dynamic_loader->wait_for_bl_timeout = GAUDI_WAIT_FOR_BL_TIMEOUT_USEC; +} - return 0; +static void gaudi_init_static_firmware_loader(struct hl_device *hdev) +{ + struct static_fw_load_mgr *static_loader; + + static_loader = &hdev->fw_loader.static_loader; + + static_loader->preboot_version_max_off = SRAM_SIZE - VERSION_MAX_LEN; + static_loader->boot_fit_version_max_off = SRAM_SIZE - VERSION_MAX_LEN; + static_loader->kmd_msg_to_cpu_reg = mmPSOC_GLOBAL_CONF_KMD_MSG_TO_CPU; + static_loader->cpu_cmd_status_to_host_reg = mmCPU_CMD_STATUS_TO_HOST; + static_loader->cpu_boot_status_reg = mmPSOC_GLOBAL_CONF_CPU_BOOT_STATUS; + static_loader->cpu_boot_dev_status0_reg = mmCPU_BOOT_DEV_STS0; + static_loader->cpu_boot_dev_status1_reg = mmCPU_BOOT_DEV_STS1; + static_loader->boot_err0_reg = mmCPU_BOOT_ERR0; + static_loader->boot_err1_reg = mmCPU_BOOT_ERR1; + static_loader->preboot_version_offset_reg = mmPREBOOT_VER_OFFSET; + static_loader->boot_fit_version_offset_reg = mmUBOOT_VER_OFFSET; + static_loader->sram_offset_mask = ~(lower_32_bits(SRAM_BASE_ADDR)); + static_loader->cpu_reset_wait_msec = hdev->pldm ? + GAUDI_PLDM_RESET_WAIT_MSEC : + GAUDI_CPU_RESET_WAIT_MSEC; +} + +static void gaudi_init_firmware_loader(struct hl_device *hdev) +{ + struct asic_fixed_properties *prop = &hdev->asic_prop; + struct fw_load_mgr *fw_loader = &hdev->fw_loader; + + /* fill common fields */ + fw_loader->linux_loaded = false; + fw_loader->boot_fit_img.image_name = GAUDI_BOOT_FIT_FILE; + fw_loader->linux_img.image_name = GAUDI_LINUX_FW_FILE; + fw_loader->cpu_timeout = GAUDI_CPU_TIMEOUT_USEC; + fw_loader->boot_fit_timeout = GAUDI_BOOT_FIT_REQ_TIMEOUT_USEC; + fw_loader->skip_bmc = !hdev->bmc_enable; + fw_loader->sram_bar_id = SRAM_BAR_ID; + fw_loader->dram_bar_id = HBM_BAR_ID; + + if (prop->dynamic_fw_load) + gaudi_init_dynamic_firmware_loader(hdev); + else + gaudi_init_static_firmware_loader(hdev); } static int gaudi_init_cpu(struct hl_device *hdev) @@ -3744,15 +3861,10 @@ static int gaudi_init_cpu(struct hl_device *hdev) * The device CPU works with 40 bits addresses. * This register sets the extension to 50 bits. */ - if (hdev->asic_prop.fw_security_disabled) + if (!hdev->asic_prop.fw_security_enabled) WREG32(mmCPU_IF_CPU_MSB_ADDR, hdev->cpu_pci_msb_addr); - rc = hl_fw_init_cpu(hdev, mmPSOC_GLOBAL_CONF_CPU_BOOT_STATUS, - mmPSOC_GLOBAL_CONF_KMD_MSG_TO_CPU, - mmCPU_CMD_STATUS_TO_HOST, - mmCPU_BOOT_DEV_STS0, mmCPU_BOOT_ERR0, - !hdev->bmc_enable, GAUDI_CPU_TIMEOUT_USEC, - GAUDI_BOOT_FIT_REQ_TIMEOUT_USEC); + rc = hl_fw_init_cpu(hdev); if (rc) return rc; @@ -3764,10 +3876,12 @@ static int gaudi_init_cpu(struct hl_device *hdev) static int gaudi_init_cpu_queues(struct hl_device *hdev, u32 cpu_timeout) { - struct gaudi_device *gaudi = hdev->asic_specific; + struct cpu_dyn_regs *dyn_regs = + &hdev->fw_loader.dynamic_loader.comm_desc.cpu_dyn_regs; struct asic_fixed_properties *prop = &hdev->asic_prop; + struct gaudi_device *gaudi = hdev->asic_specific; + u32 status, irq_handler_offset; struct hl_eq *eq; - u32 status; struct hl_hw_queue *cpu_pq = &hdev->kernel_queues[GAUDI_QUEUE_ID_CPU_PQ]; int err; @@ -3806,7 +3920,12 @@ static int gaudi_init_cpu_queues(struct hl_device *hdev, u32 cpu_timeout) WREG32(mmCPU_IF_QUEUE_INIT, PQ_INIT_STATUS_READY_FOR_CP_SINGLE_MSI); - WREG32(mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR, GAUDI_EVENT_PI_UPDATE); + irq_handler_offset = prop->gic_interrupts_enable ? + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR : + le32_to_cpu(dyn_regs->gic_host_pi_upd_irq); + + WREG32(irq_handler_offset, + gaudi_irq_map_table[GAUDI_EVENT_PI_UPDATE].cpu_id); err = hl_poll_timeout( hdev, @@ -3823,8 +3942,10 @@ static int gaudi_init_cpu_queues(struct hl_device *hdev, u32 cpu_timeout) } /* update FW application security bits */ - if (prop->fw_security_status_valid) - prop->fw_app_security_map = RREG32(mmCPU_BOOT_DEV_STS0); + if (prop->fw_cpu_boot_dev_sts0_valid) + prop->fw_app_cpu_boot_dev_sts0 = RREG32(mmCPU_BOOT_DEV_STS0); + if (prop->fw_cpu_boot_dev_sts1_valid) + prop->fw_app_cpu_boot_dev_sts1 = RREG32(mmCPU_BOOT_DEV_STS1); gaudi->hw_cap_initialized |= HW_CAP_CPU_Q; return 0; @@ -3835,7 +3956,7 @@ static void gaudi_pre_hw_init(struct hl_device *hdev) /* Perform read from the device to make sure device is up */ RREG32(mmHW_STATE); - if (hdev->asic_prop.fw_security_disabled) { + if (!hdev->asic_prop.fw_security_enabled) { /* Set the access through PCI bars (Linux driver only) as * secured */ @@ -3860,13 +3981,27 @@ static void gaudi_pre_hw_init(struct hl_device *hdev) static int gaudi_hw_init(struct hl_device *hdev) { + struct gaudi_device *gaudi = hdev->asic_specific; int rc; gaudi_pre_hw_init(hdev); - gaudi_init_pci_dma_qmans(hdev); + /* If iATU is done by FW, the HBM bar ALWAYS points to DRAM_PHYS_BASE. + * So we set it here and if anyone tries to move it later to + * a different address, there will be an error + */ + if (hdev->asic_prop.iatu_done_by_fw) + gaudi->hbm_bar_cur_addr = DRAM_PHYS_BASE; - gaudi_init_hbm_dma_qmans(hdev); + /* + * Before pushing u-boot/linux to device, need to set the hbm bar to + * base address of dram + */ + if (gaudi_set_hbm_bar_base(hdev, DRAM_PHYS_BASE) == U64_MAX) { + dev_err(hdev->dev, + "failed to map HBM bar to DRAM base address\n"); + return -EIO; + } rc = gaudi_init_cpu(hdev); if (rc) { @@ -3895,6 +4030,10 @@ static int gaudi_hw_init(struct hl_device *hdev) gaudi_init_security(hdev); + gaudi_init_pci_dma_qmans(hdev); + + gaudi_init_hbm_dma_qmans(hdev); + gaudi_init_mme_qmans(hdev); gaudi_init_tpc_qmans(hdev); @@ -3934,8 +4073,11 @@ disable_queues: static void gaudi_hw_fini(struct hl_device *hdev, bool hard_reset) { + struct cpu_dyn_regs *dyn_regs = + &hdev->fw_loader.dynamic_loader.comm_desc.cpu_dyn_regs; + u32 status, reset_timeout_ms, cpu_timeout_ms, irq_handler_offset; struct gaudi_device *gaudi = hdev->asic_specific; - u32 status, reset_timeout_ms, cpu_timeout_ms; + bool driver_performs_reset; if (!hard_reset) { dev_err(hdev->dev, "GAUDI doesn't support soft-reset\n"); @@ -3950,26 +4092,35 @@ static void gaudi_hw_fini(struct hl_device *hdev, bool hard_reset) cpu_timeout_ms = GAUDI_CPU_RESET_WAIT_MSEC; } + driver_performs_reset = !!(!hdev->asic_prop.fw_security_enabled && + !hdev->asic_prop.hard_reset_done_by_fw); + /* Set device to handle FLR by H/W as we will put the device CPU to * halt mode */ - if (hdev->asic_prop.fw_security_disabled && - !hdev->asic_prop.hard_reset_done_by_fw) + if (driver_performs_reset) WREG32(mmPCIE_AUX_FLR_CTRL, (PCIE_AUX_FLR_CTRL_HW_CTRL_MASK | PCIE_AUX_FLR_CTRL_INT_MASK_MASK)); - /* I don't know what is the state of the CPU so make sure it is - * stopped in any means necessary + /* If linux is loaded in the device CPU we need to communicate with it + * via the GIC. Otherwise, we need to use COMMS or the MSG_TO_CPU + * registers in case of old F/Ws */ - if (hdev->asic_prop.hard_reset_done_by_fw) - WREG32(mmPSOC_GLOBAL_CONF_KMD_MSG_TO_CPU, KMD_MSG_RST_DEV); - else - WREG32(mmPSOC_GLOBAL_CONF_KMD_MSG_TO_CPU, KMD_MSG_GOTO_WFE); + if (hdev->fw_loader.linux_loaded) { + irq_handler_offset = hdev->asic_prop.gic_interrupts_enable ? + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR : + le32_to_cpu(dyn_regs->gic_host_halt_irq); - WREG32(mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR, GAUDI_EVENT_HALT_MACHINE); + WREG32(irq_handler_offset, + gaudi_irq_map_table[GAUDI_EVENT_HALT_MACHINE].cpu_id); + } else { + if (hdev->asic_prop.hard_reset_done_by_fw) + hl_fw_ask_hard_reset_without_linux(hdev); + else + hl_fw_ask_halt_machine_without_linux(hdev); + } - if (hdev->asic_prop.fw_security_disabled && - !hdev->asic_prop.hard_reset_done_by_fw) { + if (driver_performs_reset) { /* Configure the reset registers. Must be done as early as * possible in case we fail during H/W initialization @@ -4003,8 +4154,7 @@ static void gaudi_hw_fini(struct hl_device *hdev, bool hard_reset) WREG32(mmPREBOOT_PCIE_EN, LKD_HARD_RESET_MAGIC); /* Restart BTL/BLR upon hard-reset */ - if (hdev->asic_prop.fw_security_disabled) - WREG32(mmPSOC_GLOBAL_CONF_BOOT_SEQ_RE_START, 1); + WREG32(mmPSOC_GLOBAL_CONF_BOOT_SEQ_RE_START, 1); WREG32(mmPSOC_GLOBAL_CONF_SW_ALL_RST, 1 << PSOC_GLOBAL_CONF_SW_ALL_RST_IND_SHIFT); @@ -4041,6 +4191,8 @@ static void gaudi_hw_fini(struct hl_device *hdev, bool hard_reset) HW_CAP_CLK_GATE); memset(gaudi->events_stat, 0, sizeof(gaudi->events_stat)); + + hdev->device_cpu_is_halted = false; } } @@ -4078,10 +4230,12 @@ static int gaudi_cb_mmap(struct hl_device *hdev, struct vm_area_struct *vma, static void gaudi_ring_doorbell(struct hl_device *hdev, u32 hw_queue_id, u32 pi) { + struct cpu_dyn_regs *dyn_regs = + &hdev->fw_loader.dynamic_loader.comm_desc.cpu_dyn_regs; + u32 db_reg_offset, db_value, dma_qm_offset, q_off, irq_handler_offset; struct gaudi_device *gaudi = hdev->asic_specific; - u32 db_reg_offset, db_value, dma_qm_offset, q_off; - int dma_id; bool invalid_queue = false; + int dma_id; switch (hw_queue_id) { case GAUDI_QUEUE_ID_DMA_0_0...GAUDI_QUEUE_ID_DMA_0_3: @@ -4307,164 +4461,84 @@ static void gaudi_ring_doorbell(struct hl_device *hdev, u32 hw_queue_id, u32 pi) db_reg_offset = mmTPC7_QM_PQ_PI_3; break; - case GAUDI_QUEUE_ID_NIC_0_0: - db_reg_offset = mmNIC0_QM0_PQ_PI_0; - break; - - case GAUDI_QUEUE_ID_NIC_0_1: - db_reg_offset = mmNIC0_QM0_PQ_PI_1; - break; - - case GAUDI_QUEUE_ID_NIC_0_2: - db_reg_offset = mmNIC0_QM0_PQ_PI_2; - break; - - case GAUDI_QUEUE_ID_NIC_0_3: - db_reg_offset = mmNIC0_QM0_PQ_PI_3; - break; - - case GAUDI_QUEUE_ID_NIC_1_0: - db_reg_offset = mmNIC0_QM1_PQ_PI_0; - break; - - case GAUDI_QUEUE_ID_NIC_1_1: - db_reg_offset = mmNIC0_QM1_PQ_PI_1; - break; - - case GAUDI_QUEUE_ID_NIC_1_2: - db_reg_offset = mmNIC0_QM1_PQ_PI_2; - break; - - case GAUDI_QUEUE_ID_NIC_1_3: - db_reg_offset = mmNIC0_QM1_PQ_PI_3; - break; - - case GAUDI_QUEUE_ID_NIC_2_0: - db_reg_offset = mmNIC1_QM0_PQ_PI_0; - break; - - case GAUDI_QUEUE_ID_NIC_2_1: - db_reg_offset = mmNIC1_QM0_PQ_PI_1; - break; - - case GAUDI_QUEUE_ID_NIC_2_2: - db_reg_offset = mmNIC1_QM0_PQ_PI_2; - break; - - case GAUDI_QUEUE_ID_NIC_2_3: - db_reg_offset = mmNIC1_QM0_PQ_PI_3; - break; - - case GAUDI_QUEUE_ID_NIC_3_0: - db_reg_offset = mmNIC1_QM1_PQ_PI_0; - break; - - case GAUDI_QUEUE_ID_NIC_3_1: - db_reg_offset = mmNIC1_QM1_PQ_PI_1; - break; - - case GAUDI_QUEUE_ID_NIC_3_2: - db_reg_offset = mmNIC1_QM1_PQ_PI_2; - break; - - case GAUDI_QUEUE_ID_NIC_3_3: - db_reg_offset = mmNIC1_QM1_PQ_PI_3; - break; - - case GAUDI_QUEUE_ID_NIC_4_0: - db_reg_offset = mmNIC2_QM0_PQ_PI_0; - break; - - case GAUDI_QUEUE_ID_NIC_4_1: - db_reg_offset = mmNIC2_QM0_PQ_PI_1; - break; - - case GAUDI_QUEUE_ID_NIC_4_2: - db_reg_offset = mmNIC2_QM0_PQ_PI_2; - break; - - case GAUDI_QUEUE_ID_NIC_4_3: - db_reg_offset = mmNIC2_QM0_PQ_PI_3; - break; - - case GAUDI_QUEUE_ID_NIC_5_0: - db_reg_offset = mmNIC2_QM1_PQ_PI_0; - break; + case GAUDI_QUEUE_ID_NIC_0_0...GAUDI_QUEUE_ID_NIC_0_3: + if (!(gaudi->hw_cap_initialized & HW_CAP_NIC0)) + invalid_queue = true; - case GAUDI_QUEUE_ID_NIC_5_1: - db_reg_offset = mmNIC2_QM1_PQ_PI_1; + q_off = ((hw_queue_id - 1) & 0x3) * 4; + db_reg_offset = mmNIC0_QM0_PQ_PI_0 + q_off; break; - case GAUDI_QUEUE_ID_NIC_5_2: - db_reg_offset = mmNIC2_QM1_PQ_PI_2; - break; + case GAUDI_QUEUE_ID_NIC_1_0...GAUDI_QUEUE_ID_NIC_1_3: + if (!(gaudi->hw_cap_initialized & HW_CAP_NIC1)) + invalid_queue = true; - case GAUDI_QUEUE_ID_NIC_5_3: - db_reg_offset = mmNIC2_QM1_PQ_PI_3; + q_off = ((hw_queue_id - 1) & 0x3) * 4; + db_reg_offset = mmNIC0_QM1_PQ_PI_0 + q_off; break; - case GAUDI_QUEUE_ID_NIC_6_0: - db_reg_offset = mmNIC3_QM0_PQ_PI_0; - break; + case GAUDI_QUEUE_ID_NIC_2_0...GAUDI_QUEUE_ID_NIC_2_3: + if (!(gaudi->hw_cap_initialized & HW_CAP_NIC2)) + invalid_queue = true; - case GAUDI_QUEUE_ID_NIC_6_1: - db_reg_offset = mmNIC3_QM0_PQ_PI_1; + q_off = ((hw_queue_id - 1) & 0x3) * 4; + db_reg_offset = mmNIC1_QM0_PQ_PI_0 + q_off; break; - case GAUDI_QUEUE_ID_NIC_6_2: - db_reg_offset = mmNIC3_QM0_PQ_PI_2; - break; + case GAUDI_QUEUE_ID_NIC_3_0...GAUDI_QUEUE_ID_NIC_3_3: + if (!(gaudi->hw_cap_initialized & HW_CAP_NIC3)) + invalid_queue = true; - case GAUDI_QUEUE_ID_NIC_6_3: - db_reg_offset = mmNIC3_QM0_PQ_PI_3; + q_off = ((hw_queue_id - 1) & 0x3) * 4; + db_reg_offset = mmNIC1_QM1_PQ_PI_0 + q_off; break; - case GAUDI_QUEUE_ID_NIC_7_0: - db_reg_offset = mmNIC3_QM1_PQ_PI_0; - break; + case GAUDI_QUEUE_ID_NIC_4_0...GAUDI_QUEUE_ID_NIC_4_3: + if (!(gaudi->hw_cap_initialized & HW_CAP_NIC4)) + invalid_queue = true; - case GAUDI_QUEUE_ID_NIC_7_1: - db_reg_offset = mmNIC3_QM1_PQ_PI_1; + q_off = ((hw_queue_id - 1) & 0x3) * 4; + db_reg_offset = mmNIC2_QM0_PQ_PI_0 + q_off; break; - case GAUDI_QUEUE_ID_NIC_7_2: - db_reg_offset = mmNIC3_QM1_PQ_PI_2; - break; + case GAUDI_QUEUE_ID_NIC_5_0...GAUDI_QUEUE_ID_NIC_5_3: + if (!(gaudi->hw_cap_initialized & HW_CAP_NIC5)) + invalid_queue = true; - case GAUDI_QUEUE_ID_NIC_7_3: - db_reg_offset = mmNIC3_QM1_PQ_PI_3; + q_off = ((hw_queue_id - 1) & 0x3) * 4; + db_reg_offset = mmNIC2_QM1_PQ_PI_0 + q_off; break; - case GAUDI_QUEUE_ID_NIC_8_0: - db_reg_offset = mmNIC4_QM0_PQ_PI_0; - break; + case GAUDI_QUEUE_ID_NIC_6_0...GAUDI_QUEUE_ID_NIC_6_3: + if (!(gaudi->hw_cap_initialized & HW_CAP_NIC6)) + invalid_queue = true; - case GAUDI_QUEUE_ID_NIC_8_1: - db_reg_offset = mmNIC4_QM0_PQ_PI_1; + q_off = ((hw_queue_id - 1) & 0x3) * 4; + db_reg_offset = mmNIC3_QM0_PQ_PI_0 + q_off; break; - case GAUDI_QUEUE_ID_NIC_8_2: - db_reg_offset = mmNIC4_QM0_PQ_PI_2; - break; + case GAUDI_QUEUE_ID_NIC_7_0...GAUDI_QUEUE_ID_NIC_7_3: + if (!(gaudi->hw_cap_initialized & HW_CAP_NIC7)) + invalid_queue = true; - case GAUDI_QUEUE_ID_NIC_8_3: - db_reg_offset = mmNIC4_QM0_PQ_PI_3; + q_off = ((hw_queue_id - 1) & 0x3) * 4; + db_reg_offset = mmNIC3_QM1_PQ_PI_0 + q_off; break; - case GAUDI_QUEUE_ID_NIC_9_0: - db_reg_offset = mmNIC4_QM1_PQ_PI_0; - break; + case GAUDI_QUEUE_ID_NIC_8_0...GAUDI_QUEUE_ID_NIC_8_3: + if (!(gaudi->hw_cap_initialized & HW_CAP_NIC8)) + invalid_queue = true; - case GAUDI_QUEUE_ID_NIC_9_1: - db_reg_offset = mmNIC4_QM1_PQ_PI_1; + q_off = ((hw_queue_id - 1) & 0x3) * 4; + db_reg_offset = mmNIC4_QM0_PQ_PI_0 + q_off; break; - case GAUDI_QUEUE_ID_NIC_9_2: - db_reg_offset = mmNIC4_QM1_PQ_PI_2; - break; + case GAUDI_QUEUE_ID_NIC_9_0...GAUDI_QUEUE_ID_NIC_9_3: + if (!(gaudi->hw_cap_initialized & HW_CAP_NIC9)) + invalid_queue = true; - case GAUDI_QUEUE_ID_NIC_9_3: - db_reg_offset = mmNIC4_QM1_PQ_PI_3; + q_off = ((hw_queue_id - 1) & 0x3) * 4; + db_reg_offset = mmNIC4_QM1_PQ_PI_0 + q_off; break; default: @@ -4486,8 +4560,13 @@ static void gaudi_ring_doorbell(struct hl_device *hdev, u32 hw_queue_id, u32 pi) if (hw_queue_id == GAUDI_QUEUE_ID_CPU_PQ) { /* make sure device CPU will read latest data from host */ mb(); - WREG32(mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR, - GAUDI_EVENT_PI_UPDATE); + + irq_handler_offset = hdev->asic_prop.gic_interrupts_enable ? + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR : + le32_to_cpu(dyn_regs->gic_host_pi_upd_irq); + + WREG32(irq_handler_offset, + gaudi_irq_map_table[GAUDI_EVENT_PI_UPDATE].cpu_id); } } @@ -4934,6 +5013,7 @@ already_pinned: return 0; unpin_memory: + list_del(&userptr->job_node); hl_unpin_host_memory(hdev, userptr); free_userptr: kfree(userptr); @@ -6513,7 +6593,7 @@ static void gaudi_mmu_prepare(struct hl_device *hdev, u32 asid) gaudi_mmu_prepare_reg(hdev, mmMME2_ACC_WBC, asid); gaudi_mmu_prepare_reg(hdev, mmMME3_ACC_WBC, asid); - if (hdev->nic_ports_mask & GAUDI_NIC_MASK_NIC0) { + if (gaudi->hw_cap_initialized & HW_CAP_NIC0) { gaudi_mmu_prepare_reg(hdev, mmNIC0_QM0_GLBL_NON_SECURE_PROPS_0, asid); gaudi_mmu_prepare_reg(hdev, mmNIC0_QM0_GLBL_NON_SECURE_PROPS_1, @@ -6526,7 +6606,7 @@ static void gaudi_mmu_prepare(struct hl_device *hdev, u32 asid) asid); } - if (hdev->nic_ports_mask & GAUDI_NIC_MASK_NIC1) { + if (gaudi->hw_cap_initialized & HW_CAP_NIC1) { gaudi_mmu_prepare_reg(hdev, mmNIC0_QM1_GLBL_NON_SECURE_PROPS_0, asid); gaudi_mmu_prepare_reg(hdev, mmNIC0_QM1_GLBL_NON_SECURE_PROPS_1, @@ -6539,7 +6619,7 @@ static void gaudi_mmu_prepare(struct hl_device *hdev, u32 asid) asid); } - if (hdev->nic_ports_mask & GAUDI_NIC_MASK_NIC2) { + if (gaudi->hw_cap_initialized & HW_CAP_NIC2) { gaudi_mmu_prepare_reg(hdev, mmNIC1_QM0_GLBL_NON_SECURE_PROPS_0, asid); gaudi_mmu_prepare_reg(hdev, mmNIC1_QM0_GLBL_NON_SECURE_PROPS_1, @@ -6552,7 +6632,7 @@ static void gaudi_mmu_prepare(struct hl_device *hdev, u32 asid) asid); } - if (hdev->nic_ports_mask & GAUDI_NIC_MASK_NIC3) { + if (gaudi->hw_cap_initialized & HW_CAP_NIC3) { gaudi_mmu_prepare_reg(hdev, mmNIC1_QM1_GLBL_NON_SECURE_PROPS_0, asid); gaudi_mmu_prepare_reg(hdev, mmNIC1_QM1_GLBL_NON_SECURE_PROPS_1, @@ -6565,7 +6645,7 @@ static void gaudi_mmu_prepare(struct hl_device *hdev, u32 asid) asid); } - if (hdev->nic_ports_mask & GAUDI_NIC_MASK_NIC4) { + if (gaudi->hw_cap_initialized & HW_CAP_NIC4) { gaudi_mmu_prepare_reg(hdev, mmNIC2_QM0_GLBL_NON_SECURE_PROPS_0, asid); gaudi_mmu_prepare_reg(hdev, mmNIC2_QM0_GLBL_NON_SECURE_PROPS_1, @@ -6578,7 +6658,7 @@ static void gaudi_mmu_prepare(struct hl_device *hdev, u32 asid) asid); } - if (hdev->nic_ports_mask & GAUDI_NIC_MASK_NIC5) { + if (gaudi->hw_cap_initialized & HW_CAP_NIC5) { gaudi_mmu_prepare_reg(hdev, mmNIC2_QM1_GLBL_NON_SECURE_PROPS_0, asid); gaudi_mmu_prepare_reg(hdev, mmNIC2_QM1_GLBL_NON_SECURE_PROPS_1, @@ -6591,7 +6671,7 @@ static void gaudi_mmu_prepare(struct hl_device *hdev, u32 asid) asid); } - if (hdev->nic_ports_mask & GAUDI_NIC_MASK_NIC6) { + if (gaudi->hw_cap_initialized & HW_CAP_NIC6) { gaudi_mmu_prepare_reg(hdev, mmNIC3_QM0_GLBL_NON_SECURE_PROPS_0, asid); gaudi_mmu_prepare_reg(hdev, mmNIC3_QM0_GLBL_NON_SECURE_PROPS_1, @@ -6604,7 +6684,7 @@ static void gaudi_mmu_prepare(struct hl_device *hdev, u32 asid) asid); } - if (hdev->nic_ports_mask & GAUDI_NIC_MASK_NIC7) { + if (gaudi->hw_cap_initialized & HW_CAP_NIC7) { gaudi_mmu_prepare_reg(hdev, mmNIC3_QM1_GLBL_NON_SECURE_PROPS_0, asid); gaudi_mmu_prepare_reg(hdev, mmNIC3_QM1_GLBL_NON_SECURE_PROPS_1, @@ -6617,7 +6697,7 @@ static void gaudi_mmu_prepare(struct hl_device *hdev, u32 asid) asid); } - if (hdev->nic_ports_mask & GAUDI_NIC_MASK_NIC8) { + if (gaudi->hw_cap_initialized & HW_CAP_NIC8) { gaudi_mmu_prepare_reg(hdev, mmNIC4_QM0_GLBL_NON_SECURE_PROPS_0, asid); gaudi_mmu_prepare_reg(hdev, mmNIC4_QM0_GLBL_NON_SECURE_PROPS_1, @@ -6630,7 +6710,7 @@ static void gaudi_mmu_prepare(struct hl_device *hdev, u32 asid) asid); } - if (hdev->nic_ports_mask & GAUDI_NIC_MASK_NIC9) { + if (gaudi->hw_cap_initialized & HW_CAP_NIC9) { gaudi_mmu_prepare_reg(hdev, mmNIC4_QM1_GLBL_NON_SECURE_PROPS_0, asid); gaudi_mmu_prepare_reg(hdev, mmNIC4_QM1_GLBL_NON_SECURE_PROPS_1, @@ -7044,14 +7124,158 @@ enable_clk_gate: return rc; } +/* + * gaudi_queue_idx_dec - decrement queue index (pi/ci) and handle wrap + * + * @idx: the current pi/ci value + * @q_len: the queue length (power of 2) + * + * @return the cyclically decremented index + */ +static inline u32 gaudi_queue_idx_dec(u32 idx, u32 q_len) +{ + u32 mask = q_len - 1; + + /* + * modular decrement is equivalent to adding (queue_size -1) + * later we take LSBs to make sure the value is in the + * range [0, queue_len - 1] + */ + return (idx + q_len - 1) & mask; +} + +/** + * gaudi_print_sw_config_stream_data - print SW config stream data + * + * @hdev: pointer to the habanalabs device structure + * @stream: the QMAN's stream + * @qman_base: base address of QMAN registers block + */ +static void gaudi_print_sw_config_stream_data(struct hl_device *hdev, u32 stream, + u64 qman_base) +{ + u64 cq_ptr_lo, cq_ptr_hi, cq_tsize, cq_ptr; + u32 cq_ptr_lo_off, size; + + cq_ptr_lo_off = mmTPC0_QM_CQ_PTR_LO_1 - mmTPC0_QM_CQ_PTR_LO_0; + + cq_ptr_lo = qman_base + (mmTPC0_QM_CQ_PTR_LO_0 - mmTPC0_QM_BASE) + + stream * cq_ptr_lo_off; + cq_ptr_hi = cq_ptr_lo + + (mmTPC0_QM_CQ_PTR_HI_0 - mmTPC0_QM_CQ_PTR_LO_0); + cq_tsize = cq_ptr_lo + + (mmTPC0_QM_CQ_TSIZE_0 - mmTPC0_QM_CQ_PTR_LO_0); + + cq_ptr = (((u64) RREG32(cq_ptr_hi)) << 32) | RREG32(cq_ptr_lo); + size = RREG32(cq_tsize); + dev_info(hdev->dev, "stop on err: stream: %u, addr: %#llx, size: %x\n", + stream, cq_ptr, size); +} + +/** + * gaudi_print_last_pqes_on_err - print last PQEs on error + * + * @hdev: pointer to the habanalabs device structure + * @qid_base: first QID of the QMAN (out of 4 streams) + * @stream: the QMAN's stream + * @qman_base: base address of QMAN registers block + * @pr_sw_conf: if true print the SW config stream data (CQ PTR and SIZE) + */ +static void gaudi_print_last_pqes_on_err(struct hl_device *hdev, u32 qid_base, + u32 stream, u64 qman_base, + bool pr_sw_conf) +{ + u32 ci, qm_ci_stream_off, queue_len; + struct hl_hw_queue *q; + u64 pq_ci; + int i; + + q = &hdev->kernel_queues[qid_base + stream]; + + qm_ci_stream_off = mmTPC0_QM_PQ_CI_1 - mmTPC0_QM_PQ_CI_0; + pq_ci = qman_base + (mmTPC0_QM_PQ_CI_0 - mmTPC0_QM_BASE) + + stream * qm_ci_stream_off; + + queue_len = (q->queue_type == QUEUE_TYPE_INT) ? + q->int_queue_len : HL_QUEUE_LENGTH; + + hdev->asic_funcs->hw_queues_lock(hdev); + + if (pr_sw_conf) + gaudi_print_sw_config_stream_data(hdev, stream, qman_base); + + ci = RREG32(pq_ci); + + /* we should start printing form ci -1 */ + ci = gaudi_queue_idx_dec(ci, queue_len); + + for (i = 0; i < PQ_FETCHER_CACHE_SIZE; i++) { + struct hl_bd *bd; + u64 addr; + u32 len; + + bd = q->kernel_address; + bd += ci; + + len = le32_to_cpu(bd->len); + /* len 0 means uninitialized entry- break */ + if (!len) + break; + + addr = le64_to_cpu(bd->ptr); + + dev_info(hdev->dev, "stop on err PQE(stream %u): ci: %u, addr: %#llx, size: %x\n", + stream, ci, addr, len); + + /* get previous ci, wrap if needed */ + ci = gaudi_queue_idx_dec(ci, queue_len); + } + + hdev->asic_funcs->hw_queues_unlock(hdev); +} + +/** + * print_qman_data_on_err - extract QMAN data on error + * + * @hdev: pointer to the habanalabs device structure + * @qid_base: first QID of the QMAN (out of 4 streams) + * @stream: the QMAN's stream + * @qman_base: base address of QMAN registers block + * + * This function attempt to exatract as much data as possible on QMAN error. + * On upper CP print the SW config stream data and last 8 PQEs. + * On lower CP print SW config data and last PQEs of ALL 4 upper CPs + */ +static void print_qman_data_on_err(struct hl_device *hdev, u32 qid_base, + u32 stream, u64 qman_base) +{ + u32 i; + + if (stream != QMAN_STREAMS) { + gaudi_print_last_pqes_on_err(hdev, qid_base, stream, qman_base, + true); + return; + } + + gaudi_print_sw_config_stream_data(hdev, stream, qman_base); + + for (i = 0; i < QMAN_STREAMS; i++) + gaudi_print_last_pqes_on_err(hdev, qid_base, i, qman_base, + false); +} + static void gaudi_handle_qman_err_generic(struct hl_device *hdev, const char *qm_name, - u64 glbl_sts_addr, - u64 arb_err_addr) + u64 qman_base, + u32 qid_base) { u32 i, j, glbl_sts_val, arb_err_val, glbl_sts_clr_val; + u64 glbl_sts_addr, arb_err_addr; char reg_desc[32]; + glbl_sts_addr = qman_base + (mmTPC0_QM_GLBL_STS1_0 - mmTPC0_QM_BASE); + arb_err_addr = qman_base + (mmTPC0_QM_ARB_ERR_CAUSE - mmTPC0_QM_BASE); + /* Iterate through all stream GLBL_STS1 registers + Lower CP */ for (i = 0 ; i < QMAN_STREAMS + 1 ; i++) { glbl_sts_clr_val = 0; @@ -7078,6 +7302,8 @@ static void gaudi_handle_qman_err_generic(struct hl_device *hdev, /* Write 1 clear errors */ if (!hdev->stop_on_err) WREG32(glbl_sts_addr + 4 * i, glbl_sts_clr_val); + else + print_qman_data_on_err(hdev, qid_base, i, qman_base); } arb_err_val = RREG32(arb_err_addr); @@ -7222,90 +7448,88 @@ static void gaudi_handle_ecc_event(struct hl_device *hdev, u16 event_type, static void gaudi_handle_qman_err(struct hl_device *hdev, u16 event_type) { - u64 glbl_sts_addr, arb_err_addr; - u8 index; + u64 qman_base; char desc[32]; + u32 qid_base; + u8 index; switch (event_type) { case GAUDI_EVENT_TPC0_QM ... GAUDI_EVENT_TPC7_QM: index = event_type - GAUDI_EVENT_TPC0_QM; - glbl_sts_addr = - mmTPC0_QM_GLBL_STS1_0 + index * TPC_QMAN_OFFSET; - arb_err_addr = - mmTPC0_QM_ARB_ERR_CAUSE + index * TPC_QMAN_OFFSET; + qid_base = GAUDI_QUEUE_ID_TPC_0_0 + index * QMAN_STREAMS; + qman_base = mmTPC0_QM_BASE + index * TPC_QMAN_OFFSET; snprintf(desc, ARRAY_SIZE(desc), "%s%d", "TPC_QM", index); break; case GAUDI_EVENT_MME0_QM ... GAUDI_EVENT_MME2_QM: index = event_type - GAUDI_EVENT_MME0_QM; - glbl_sts_addr = - mmMME0_QM_GLBL_STS1_0 + index * MME_QMAN_OFFSET; - arb_err_addr = - mmMME0_QM_ARB_ERR_CAUSE + index * MME_QMAN_OFFSET; + qid_base = GAUDI_QUEUE_ID_MME_0_0 + index * QMAN_STREAMS; + qman_base = mmMME0_QM_BASE + index * MME_QMAN_OFFSET; snprintf(desc, ARRAY_SIZE(desc), "%s%d", "MME_QM", index); break; case GAUDI_EVENT_DMA0_QM ... GAUDI_EVENT_DMA7_QM: index = event_type - GAUDI_EVENT_DMA0_QM; - glbl_sts_addr = - mmDMA0_QM_GLBL_STS1_0 + index * DMA_QMAN_OFFSET; - arb_err_addr = - mmDMA0_QM_ARB_ERR_CAUSE + index * DMA_QMAN_OFFSET; + qid_base = GAUDI_QUEUE_ID_DMA_0_0 + index * QMAN_STREAMS; + /* skip GAUDI_QUEUE_ID_CPU_PQ if necessary */ + if (index > 1) + qid_base++; + qman_base = mmDMA0_QM_BASE + index * DMA_QMAN_OFFSET; snprintf(desc, ARRAY_SIZE(desc), "%s%d", "DMA_QM", index); break; case GAUDI_EVENT_NIC0_QM0: - glbl_sts_addr = mmNIC0_QM0_GLBL_STS1_0; - arb_err_addr = mmNIC0_QM0_ARB_ERR_CAUSE; + qid_base = GAUDI_QUEUE_ID_NIC_0_0; + qman_base = mmNIC0_QM0_BASE; snprintf(desc, ARRAY_SIZE(desc), "NIC0_QM0"); break; case GAUDI_EVENT_NIC0_QM1: - glbl_sts_addr = mmNIC0_QM1_GLBL_STS1_0; - arb_err_addr = mmNIC0_QM1_ARB_ERR_CAUSE; + qid_base = GAUDI_QUEUE_ID_NIC_1_0; + qman_base = mmNIC0_QM1_BASE; snprintf(desc, ARRAY_SIZE(desc), "NIC0_QM1"); break; case GAUDI_EVENT_NIC1_QM0: - glbl_sts_addr = mmNIC1_QM0_GLBL_STS1_0; - arb_err_addr = mmNIC1_QM0_ARB_ERR_CAUSE; + qid_base = GAUDI_QUEUE_ID_NIC_2_0; + qman_base = mmNIC1_QM0_BASE; snprintf(desc, ARRAY_SIZE(desc), "NIC1_QM0"); break; case GAUDI_EVENT_NIC1_QM1: - glbl_sts_addr = mmNIC1_QM1_GLBL_STS1_0; - arb_err_addr = mmNIC1_QM1_ARB_ERR_CAUSE; + qid_base = GAUDI_QUEUE_ID_NIC_3_0; + qman_base = mmNIC1_QM1_BASE; snprintf(desc, ARRAY_SIZE(desc), "NIC1_QM1"); break; case GAUDI_EVENT_NIC2_QM0: - glbl_sts_addr = mmNIC2_QM0_GLBL_STS1_0; - arb_err_addr = mmNIC2_QM0_ARB_ERR_CAUSE; + qid_base = GAUDI_QUEUE_ID_NIC_4_0; + qman_base = mmNIC2_QM0_BASE; snprintf(desc, ARRAY_SIZE(desc), "NIC2_QM0"); break; case GAUDI_EVENT_NIC2_QM1: - glbl_sts_addr = mmNIC2_QM1_GLBL_STS1_0; - arb_err_addr = mmNIC2_QM1_ARB_ERR_CAUSE; + qid_base = GAUDI_QUEUE_ID_NIC_5_0; + qman_base = mmNIC2_QM1_BASE; snprintf(desc, ARRAY_SIZE(desc), "NIC2_QM1"); break; case GAUDI_EVENT_NIC3_QM0: - glbl_sts_addr = mmNIC3_QM0_GLBL_STS1_0; - arb_err_addr = mmNIC3_QM0_ARB_ERR_CAUSE; + qid_base = GAUDI_QUEUE_ID_NIC_6_0; + qman_base = mmNIC3_QM0_BASE; snprintf(desc, ARRAY_SIZE(desc), "NIC3_QM0"); break; case GAUDI_EVENT_NIC3_QM1: - glbl_sts_addr = mmNIC3_QM1_GLBL_STS1_0; - arb_err_addr = mmNIC3_QM1_ARB_ERR_CAUSE; + qid_base = GAUDI_QUEUE_ID_NIC_7_0; + qman_base = mmNIC3_QM1_BASE; snprintf(desc, ARRAY_SIZE(desc), "NIC3_QM1"); break; case GAUDI_EVENT_NIC4_QM0: - glbl_sts_addr = mmNIC4_QM0_GLBL_STS1_0; - arb_err_addr = mmNIC4_QM0_ARB_ERR_CAUSE; + qid_base = GAUDI_QUEUE_ID_NIC_8_0; + qman_base = mmNIC4_QM0_BASE; snprintf(desc, ARRAY_SIZE(desc), "NIC4_QM0"); break; case GAUDI_EVENT_NIC4_QM1: - glbl_sts_addr = mmNIC4_QM1_GLBL_STS1_0; - arb_err_addr = mmNIC4_QM1_ARB_ERR_CAUSE; + qid_base = GAUDI_QUEUE_ID_NIC_9_0; + qman_base = mmNIC4_QM1_BASE; snprintf(desc, ARRAY_SIZE(desc), "NIC4_QM1"); break; default: return; } - gaudi_handle_qman_err_generic(hdev, desc, glbl_sts_addr, arb_err_addr); + gaudi_handle_qman_err_generic(hdev, desc, qman_base, qid_base); } static void gaudi_print_irq_info(struct hl_device *hdev, u16 event_type, @@ -7332,6 +7556,16 @@ static void gaudi_print_out_of_sync_info(struct hl_device *hdev, sync_err->pi, sync_err->ci, q->pi, atomic_read(&q->ci)); } +static void gaudi_print_fw_alive_info(struct hl_device *hdev, + struct hl_eq_fw_alive *fw_alive) +{ + dev_err(hdev->dev, + "FW alive report: severity=%s, process_id=%u, thread_id=%u, uptime=%llu seconds\n", + (fw_alive->severity == FW_ALIVE_SEVERITY_MINOR) ? + "Minor" : "Critical", fw_alive->process_id, + fw_alive->thread_id, fw_alive->uptime_seconds); +} + static int gaudi_soft_reset_late_init(struct hl_device *hdev) { struct gaudi_device *gaudi = hdev->asic_specific; @@ -7346,11 +7580,10 @@ static int gaudi_hbm_read_interrupts(struct hl_device *hdev, int device, struct hl_eq_hbm_ecc_data *hbm_ecc_data) { u32 base, val, val2, wr_par, rd_par, ca_par, derr, serr, type, ch; - int err = 0; + int rc = 0; - if (hdev->asic_prop.fw_security_status_valid && - (hdev->asic_prop.fw_app_security_map & - CPU_BOOT_DEV_STS0_HBM_ECC_EN)) { + if (hdev->asic_prop.fw_app_cpu_boot_dev_sts0 & + CPU_BOOT_DEV_STS0_HBM_ECC_EN) { if (!hbm_ecc_data) { dev_err(hdev->dev, "No FW ECC data"); return 0; @@ -7379,13 +7612,10 @@ static int gaudi_hbm_read_interrupts(struct hl_device *hdev, int device, device, ch, hbm_ecc_data->first_addr, type, hbm_ecc_data->sec_cont_cnt, hbm_ecc_data->sec_cnt, hbm_ecc_data->dec_cnt); - - err = 1; - return 0; } - if (!hdev->asic_prop.fw_security_disabled) { + if (hdev->asic_prop.fw_security_enabled) { dev_info(hdev->dev, "Cannot access MC regs for ECC data while security is enabled\n"); return 0; } @@ -7395,7 +7625,7 @@ static int gaudi_hbm_read_interrupts(struct hl_device *hdev, int device, val = RREG32_MASK(base + ch * 0x1000 + 0x06C, 0x0000FFFF); val = (val & 0xFF) | ((val >> 8) & 0xFF); if (val) { - err = 1; + rc = -EIO; dev_err(hdev->dev, "HBM%d pc%d interrupts info: WR_PAR=%d, RD_PAR=%d, CA_PAR=%d, SERR=%d, DERR=%d\n", device, ch * 2, val & 0x1, (val >> 1) & 0x1, @@ -7415,7 +7645,7 @@ static int gaudi_hbm_read_interrupts(struct hl_device *hdev, int device, val = RREG32_MASK(base + ch * 0x1000 + 0x07C, 0x0000FFFF); val = (val & 0xFF) | ((val >> 8) & 0xFF); if (val) { - err = 1; + rc = -EIO; dev_err(hdev->dev, "HBM%d pc%d interrupts info: WR_PAR=%d, RD_PAR=%d, CA_PAR=%d, SERR=%d, DERR=%d\n", device, ch * 2 + 1, val & 0x1, (val >> 1) & 0x1, @@ -7444,7 +7674,7 @@ static int gaudi_hbm_read_interrupts(struct hl_device *hdev, int device, val = RREG32(base + 0x8F30); val2 = RREG32(base + 0x8F34); if (val | val2) { - err = 1; + rc = -EIO; dev_err(hdev->dev, "HBM %d MC SRAM SERR info: Reg 0x8F30=0x%x, Reg 0x8F34=0x%x\n", device, val, val2); @@ -7452,13 +7682,13 @@ static int gaudi_hbm_read_interrupts(struct hl_device *hdev, int device, val = RREG32(base + 0x8F40); val2 = RREG32(base + 0x8F44); if (val | val2) { - err = 1; + rc = -EIO; dev_err(hdev->dev, "HBM %d MC SRAM DERR info: Reg 0x8F40=0x%x, Reg 0x8F44=0x%x\n", device, val, val2); } - return err; + return rc; } static int gaudi_hbm_event_to_dev(u16 hbm_event_type) @@ -7604,6 +7834,7 @@ static void gaudi_handle_eqe(struct hl_device *hdev, case GAUDI_EVENT_DMA_IF0_DERR ... GAUDI_EVENT_DMA_IF3_DERR: case GAUDI_EVENT_HBM_0_DERR ... GAUDI_EVENT_HBM_3_DERR: case GAUDI_EVENT_MMU_DERR: + case GAUDI_EVENT_NIC0_CS_DBG_DERR ... GAUDI_EVENT_NIC4_CS_DBG_DERR: gaudi_print_irq_info(hdev, event_type, true); gaudi_handle_ecc_event(hdev, event_type, &eq_entry->ecc_data); goto reset_device; @@ -7786,6 +8017,11 @@ static void gaudi_handle_eqe(struct hl_device *hdev, gaudi_print_out_of_sync_info(hdev, &eq_entry->pkt_sync_err); goto reset_device; + case GAUDI_EVENT_FW_ALIVE_S: + gaudi_print_irq_info(hdev, event_type, false); + gaudi_print_fw_alive_info(hdev, &eq_entry->fw_alive); + goto reset_device; + default: dev_err(hdev->dev, "Received invalid H/W interrupt %d\n", event_type); @@ -7856,52 +8092,13 @@ static int gaudi_mmu_invalidate_cache(struct hl_device *hdev, bool is_hard, } static int gaudi_mmu_invalidate_cache_range(struct hl_device *hdev, - bool is_hard, u32 asid, u64 va, u64 size) + bool is_hard, u32 flags, + u32 asid, u64 va, u64 size) { - struct gaudi_device *gaudi = hdev->asic_specific; - u32 status, timeout_usec; - u32 inv_data; - u32 pi; - int rc; - - if (!(gaudi->hw_cap_initialized & HW_CAP_MMU) || - hdev->hard_reset_pending) - return 0; - - if (hdev->pldm) - timeout_usec = GAUDI_PLDM_MMU_TIMEOUT_USEC; - else - timeout_usec = MMU_CONFIG_TIMEOUT_USEC; - - /* - * TODO: currently invalidate entire L0 & L1 as in regular hard - * invalidation. Need to apply invalidation of specific cache - * lines with mask of ASID & VA & size. - * Note that L1 with be flushed entirely in any case. + /* Treat as invalidate all because there is no range invalidation + * in Gaudi */ - - /* L0 & L1 invalidation */ - inv_data = RREG32(mmSTLB_CACHE_INV); - /* PI is 8 bit */ - pi = ((inv_data & STLB_CACHE_INV_PRODUCER_INDEX_MASK) + 1) & 0xFF; - WREG32(mmSTLB_CACHE_INV, - (inv_data & STLB_CACHE_INV_INDEX_MASK_MASK) | pi); - - rc = hl_poll_timeout( - hdev, - mmSTLB_INV_CONSUMER_INDEX, - status, - status == pi, - 1000, - timeout_usec); - - if (rc) { - dev_err_ratelimited(hdev->dev, - "MMU cache invalidation timeout\n"); - hl_device_reset(hdev, HL_RESET_HARD); - } - - return rc; + return hdev->asic_funcs->mmu_invalidate_cache(hdev, is_hard, flags); } static int gaudi_mmu_update_asid_hop0_addr(struct hl_device *hdev, @@ -7956,7 +8153,9 @@ static int gaudi_cpucp_info_get(struct hl_device *hdev) if (!(gaudi->hw_cap_initialized & HW_CAP_CPU_Q)) return 0; - rc = hl_fw_cpucp_handshake(hdev, mmCPU_BOOT_DEV_STS0, mmCPU_BOOT_ERR0); + rc = hl_fw_cpucp_handshake(hdev, mmCPU_BOOT_DEV_STS0, + mmCPU_BOOT_DEV_STS1, mmCPU_BOOT_ERR0, + mmCPU_BOOT_ERR1); if (rc) return rc; @@ -8077,7 +8276,7 @@ static bool gaudi_is_device_idle(struct hl_device *hdev, u64 *mask_arr, for (i = 0 ; i < (NIC_NUMBER_OF_ENGINES / 2) ; i++) { offset = i * NIC_MACRO_QMAN_OFFSET; port = 2 * i; - if (hdev->nic_ports_mask & BIT(port)) { + if (gaudi->hw_cap_initialized & BIT(HW_CAP_NIC_SHIFT + port)) { qm_glbl_sts0 = RREG32(mmNIC0_QM0_GLBL_STS0 + offset); qm_cgm_sts = RREG32(mmNIC0_QM0_CGM_STS + offset); is_eng_idle = IS_QM_IDLE(qm_glbl_sts0, qm_cgm_sts); @@ -8092,7 +8291,7 @@ static bool gaudi_is_device_idle(struct hl_device *hdev, u64 *mask_arr, } port = 2 * i + 1; - if (hdev->nic_ports_mask & BIT(port)) { + if (gaudi->hw_cap_initialized & BIT(HW_CAP_NIC_SHIFT + port)) { qm_glbl_sts0 = RREG32(mmNIC0_QM1_GLBL_STS0 + offset); qm_cgm_sts = RREG32(mmNIC0_QM1_CGM_STS + offset); is_eng_idle = IS_QM_IDLE(qm_glbl_sts0, qm_cgm_sts); @@ -8306,8 +8505,10 @@ static int gaudi_internal_cb_pool_init(struct hl_device *hdev, HL_VA_RANGE_TYPE_HOST, HOST_SPACE_INTERNAL_CB_SZ, HL_MMU_VA_ALIGNMENT_NOT_NEEDED); - if (!hdev->internal_cb_va_base) + if (!hdev->internal_cb_va_base) { + rc = -ENOMEM; goto destroy_internal_cb_pool; + } mutex_lock(&ctx->mmu_lock); rc = hl_mmu_map_contiguous(ctx, hdev->internal_cb_va_base, @@ -8749,7 +8950,14 @@ static int gaudi_block_mmap(struct hl_device *hdev, static void gaudi_enable_events_from_fw(struct hl_device *hdev) { - WREG32(mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR, GAUDI_EVENT_INTS_REGISTER); + struct cpu_dyn_regs *dyn_regs = + &hdev->fw_loader.dynamic_loader.comm_desc.cpu_dyn_regs; + u32 irq_handler_offset = hdev->asic_prop.gic_interrupts_enable ? + mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR : + le32_to_cpu(dyn_regs->gic_host_ints_irq); + + WREG32(irq_handler_offset, + gaudi_irq_map_table[GAUDI_EVENT_INTS_REGISTER].cpu_id); } static int gaudi_map_pll_idx_to_fw_idx(u32 pll_idx) @@ -8834,7 +9042,6 @@ static const struct hl_asic_funcs gaudi_funcs = { .ctx_fini = gaudi_ctx_fini, .get_clk_rate = gaudi_get_clk_rate, .get_queue_id_for_cq = gaudi_get_queue_id_for_cq, - .read_device_fw_version = gaudi_read_device_fw_version, .load_firmware_to_device = gaudi_load_firmware_to_device, .load_boot_fit_to_device = gaudi_load_boot_fit_to_device, .get_signal_cb_size = gaudi_get_signal_cb_size, @@ -8853,7 +9060,9 @@ static const struct hl_asic_funcs gaudi_funcs = { .get_hw_block_id = gaudi_get_hw_block_id, .hw_block_mmap = gaudi_block_mmap, .enable_events_from_fw = gaudi_enable_events_from_fw, - .map_pll_idx_to_fw_idx = gaudi_map_pll_idx_to_fw_idx + .map_pll_idx_to_fw_idx = gaudi_map_pll_idx_to_fw_idx, + .init_firmware_loader = gaudi_init_firmware_loader, + .init_cpu_scrambler_dram = gaudi_init_scrambler_hbm }; /** diff --git a/drivers/misc/habanalabs/gaudi/gaudiP.h b/drivers/misc/habanalabs/gaudi/gaudiP.h index 5929be81ec23..957bf3720f70 100644 --- a/drivers/misc/habanalabs/gaudi/gaudiP.h +++ b/drivers/misc/habanalabs/gaudi/gaudiP.h @@ -82,6 +82,7 @@ QMAN_STREAMS) #define QMAN_STREAMS 4 +#define PQ_FETCHER_CACHE_SIZE 8 #define DMA_QMAN_OFFSET (mmDMA1_QM_BASE - mmDMA0_QM_BASE) #define TPC_QMAN_OFFSET (mmTPC1_QM_BASE - mmTPC0_QM_BASE) diff --git a/drivers/misc/habanalabs/gaudi/gaudi_coresight.c b/drivers/misc/habanalabs/gaudi/gaudi_coresight.c index 6e56fa1c6c69..c2a27ed1c4d1 100644 --- a/drivers/misc/habanalabs/gaudi/gaudi_coresight.c +++ b/drivers/misc/habanalabs/gaudi/gaudi_coresight.c @@ -424,7 +424,7 @@ static int gaudi_config_stm(struct hl_device *hdev, if (frequency == 0) frequency = input->frequency; WREG32(base_reg + 0xE8C, frequency); - WREG32(base_reg + 0xE90, 0x7FF); + WREG32(base_reg + 0xE90, 0x1F00); /* SW-2176 - SW WA for HW bug */ if ((CFG_BASE + base_reg) >= mmDMA_CH_0_CS_STM_BASE && @@ -434,7 +434,7 @@ static int gaudi_config_stm(struct hl_device *hdev, WREG32(base_reg + 0xE6C, 0x0); } - WREG32(base_reg + 0xE80, 0x27 | (input->id << 16)); + WREG32(base_reg + 0xE80, 0x23 | (input->id << 16)); } else { WREG32(base_reg + 0xE80, 4); WREG32(base_reg + 0xD64, 0); @@ -634,7 +634,7 @@ static int gaudi_config_etr(struct hl_device *hdev, WREG32(mmPSOC_ETR_BUFWM, 0x3FFC); WREG32(mmPSOC_ETR_RSZ, input->buffer_size); WREG32(mmPSOC_ETR_MODE, input->sink_mode); - if (hdev->asic_prop.fw_security_disabled) { + if (!hdev->asic_prop.fw_security_enabled) { /* make ETR not privileged */ val = FIELD_PREP( PSOC_ETR_AXICTL_PROTCTRLBIT0_MASK, 0); diff --git a/drivers/misc/habanalabs/gaudi/gaudi_security.c b/drivers/misc/habanalabs/gaudi/gaudi_security.c index 9a706c5980ef..0d3240f1f7d7 100644 --- a/drivers/misc/habanalabs/gaudi/gaudi_security.c +++ b/drivers/misc/habanalabs/gaudi/gaudi_security.c @@ -1448,7 +1448,7 @@ static void gaudi_init_dma_protection_bits(struct hl_device *hdev) u32 pb_addr, mask; u8 word_offset; - if (hdev->asic_prop.fw_security_disabled) { + if (!hdev->asic_prop.fw_security_enabled) { gaudi_pb_set_block(hdev, mmDMA_IF_E_S_BASE); gaudi_pb_set_block(hdev, mmDMA_IF_E_S_DOWN_CH0_BASE); gaudi_pb_set_block(hdev, mmDMA_IF_E_S_DOWN_CH1_BASE); @@ -9135,7 +9135,7 @@ static void gaudi_init_tpc_protection_bits(struct hl_device *hdev) u32 pb_addr, mask; u8 word_offset; - if (hdev->asic_prop.fw_security_disabled) { + if (!hdev->asic_prop.fw_security_enabled) { gaudi_pb_set_block(hdev, mmTPC0_E2E_CRED_BASE); gaudi_pb_set_block(hdev, mmTPC1_E2E_CRED_BASE); gaudi_pb_set_block(hdev, mmTPC2_E2E_CRED_BASE); @@ -12818,7 +12818,7 @@ static void gaudi_init_protection_bits(struct hl_device *hdev) * secured */ - if (hdev->asic_prop.fw_security_disabled) { + if (!hdev->asic_prop.fw_security_enabled) { gaudi_pb_set_block(hdev, mmIF_E_PLL_BASE); gaudi_pb_set_block(hdev, mmMESH_W_PLL_BASE); gaudi_pb_set_block(hdev, mmSRAM_W_PLL_BASE); @@ -13023,7 +13023,7 @@ void gaudi_init_security(struct hl_device *hdev) * property configuration of MME SBAB and ACC to be non-privileged and * non-secured */ - if (hdev->asic_prop.fw_security_disabled) { + if (!hdev->asic_prop.fw_security_enabled) { WREG32(mmMME0_SBAB_PROT, 0x2); WREG32(mmMME0_ACC_PROT, 0x2); WREG32(mmMME1_SBAB_PROT, 0x2); @@ -13032,11 +13032,12 @@ void gaudi_init_security(struct hl_device *hdev) WREG32(mmMME2_ACC_PROT, 0x2); WREG32(mmMME3_SBAB_PROT, 0x2); WREG32(mmMME3_ACC_PROT, 0x2); - } - /* On RAZWI, 0 will be returned from RR and 0xBABA0BAD from PB */ - if (hdev->asic_prop.fw_security_disabled) + /* + * On RAZWI, 0 will be returned from RR and 0xBABA0BAD from PB + */ WREG32(0xC01B28, 0x1); + } gaudi_init_range_registers_lbw(hdev); diff --git a/drivers/misc/habanalabs/goya/goya.c b/drivers/misc/habanalabs/goya/goya.c index e0ad2a269779..755e08cf2ecc 100644 --- a/drivers/misc/habanalabs/goya/goya.c +++ b/drivers/misc/habanalabs/goya/goya.c @@ -87,6 +87,7 @@ #define GOYA_PLDM_QMAN0_TIMEOUT_USEC (HL_DEVICE_TIMEOUT_USEC * 30) #define GOYA_BOOT_FIT_REQ_TIMEOUT_USEC 1000000 /* 1s */ #define GOYA_MSG_TO_CPU_TIMEOUT_USEC 4000000 /* 4s */ +#define GOYA_WAIT_FOR_BL_TIMEOUT_USEC 15000000 /* 15s */ #define GOYA_QMAN0_FENCE_VAL 0xD169B243 @@ -354,7 +355,7 @@ static int goya_mmu_set_dram_default_page(struct hl_device *hdev); static int goya_mmu_add_mappings_for_device_cpu(struct hl_device *hdev); static void goya_mmu_prepare(struct hl_device *hdev, u32 asid); -int goya_get_fixed_properties(struct hl_device *hdev) +int goya_set_fixed_properties(struct hl_device *hdev) { struct asic_fixed_properties *prop = &hdev->asic_prop; int i; @@ -460,8 +461,10 @@ int goya_get_fixed_properties(struct hl_device *hdev) for (i = 0 ; i < HL_MAX_DCORES ; i++) prop->first_available_cq[i] = USHRT_MAX; - prop->fw_security_status_valid = false; + prop->fw_cpu_boot_dev_sts0_valid = false; + prop->fw_cpu_boot_dev_sts1_valid = false; prop->hard_reset_done_by_fw = false; + prop->gic_interrupts_enable = true; return 0; } @@ -531,10 +534,8 @@ static int goya_init_iatu(struct hl_device *hdev) struct hl_outbound_pci_region outbound_region; int rc; - if (hdev->asic_prop.iatu_done_by_fw) { - hdev->asic_funcs->set_dma_mask_from_fw(hdev); + if (hdev->asic_prop.iatu_done_by_fw) return 0; - } /* Inbound Region 0 - Bar 0 - Point to SRAM and CFG */ inbound_region.mode = PCI_BAR_MATCH_MODE; @@ -586,7 +587,7 @@ static int goya_early_init(struct hl_device *hdev) u32 fw_boot_status, val; int rc; - rc = goya_get_fixed_properties(hdev); + rc = goya_set_fixed_properties(hdev); if (rc) { dev_err(hdev->dev, "Failed to get fixed properties\n"); return rc; @@ -618,7 +619,7 @@ static int goya_early_init(struct hl_device *hdev) prop->dram_pci_bar_size = pci_resource_len(pdev, DDR_BAR_ID); /* If FW security is enabled at this point it means no access to ELBI */ - if (!hdev->asic_prop.fw_security_disabled) { + if (hdev->asic_prop.fw_security_enabled) { hdev->asic_prop.iatu_done_by_fw = true; goto pci_init; } @@ -642,8 +643,10 @@ pci_init: * version to determine whether we run with a security-enabled firmware */ rc = hl_fw_read_preboot_status(hdev, mmPSOC_GLOBAL_CONF_CPU_BOOT_STATUS, - mmCPU_BOOT_DEV_STS0, mmCPU_BOOT_ERR0, - GOYA_BOOT_FIT_REQ_TIMEOUT_USEC); + mmCPU_BOOT_DEV_STS0, + mmCPU_BOOT_DEV_STS1, mmCPU_BOOT_ERR0, + mmCPU_BOOT_ERR1, + GOYA_BOOT_FIT_REQ_TIMEOUT_USEC); if (rc) { if (hdev->reset_on_preboot_fail) hdev->asic_funcs->hw_fini(hdev, true); @@ -723,7 +726,15 @@ static void goya_fetch_psoc_frequency(struct hl_device *hdev) u16 pll_freq_arr[HL_PLL_NUM_OUTPUTS], freq; int rc; - if (hdev->asic_prop.fw_security_disabled) { + if (hdev->asic_prop.fw_security_enabled) { + rc = hl_fw_cpucp_pll_info_get(hdev, HL_GOYA_PCI_PLL, + pll_freq_arr); + + if (rc) + return; + + freq = pll_freq_arr[1]; + } else { div_fctr = RREG32(mmPSOC_PCI_PLL_DIV_FACTOR_1); div_sel = RREG32(mmPSOC_PCI_PLL_DIV_SEL_1); nr = RREG32(mmPSOC_PCI_PLL_NR); @@ -750,14 +761,6 @@ static void goya_fetch_psoc_frequency(struct hl_device *hdev) div_sel); freq = 0; } - } else { - rc = hl_fw_cpucp_pll_info_get(hdev, HL_GOYA_PCI_PLL, - pll_freq_arr); - - if (rc) - return; - - freq = pll_freq_arr[1]; } prop->psoc_timestamp_frequency = freq; @@ -849,6 +852,39 @@ void goya_late_fini(struct hl_device *hdev) hdev->hl_chip_info->info = NULL; } +static void goya_set_pci_memory_regions(struct hl_device *hdev) +{ + struct asic_fixed_properties *prop = &hdev->asic_prop; + struct pci_mem_region *region; + + /* CFG */ + region = &hdev->pci_mem_region[PCI_REGION_CFG]; + region->region_base = CFG_BASE; + region->region_size = CFG_SIZE; + region->offset_in_bar = CFG_BASE - SRAM_BASE_ADDR; + region->bar_size = CFG_BAR_SIZE; + region->bar_id = SRAM_CFG_BAR_ID; + region->used = 1; + + /* SRAM */ + region = &hdev->pci_mem_region[PCI_REGION_SRAM]; + region->region_base = SRAM_BASE_ADDR; + region->region_size = SRAM_SIZE; + region->offset_in_bar = 0; + region->bar_size = CFG_BAR_SIZE; + region->bar_id = SRAM_CFG_BAR_ID; + region->used = 1; + + /* DRAM */ + region = &hdev->pci_mem_region[PCI_REGION_DRAM]; + region->region_base = DRAM_PHYS_BASE; + region->region_size = hdev->asic_prop.dram_size; + region->offset_in_bar = 0; + region->bar_size = prop->dram_pci_bar_size; + region->bar_id = DDR_BAR_ID; + region->used = 1; +} + /* * goya_sw_init - Goya software initialization code * @@ -918,6 +954,9 @@ static int goya_sw_init(struct hl_device *hdev) spin_lock_init(&goya->hw_queues_lock); hdev->supports_coresight = true; hdev->supports_soft_reset = true; + hdev->allow_external_soft_reset = true; + + goya_set_pci_memory_regions(hdev); return 0; @@ -1263,8 +1302,11 @@ int goya_init_cpu_queues(struct hl_device *hdev) } /* update FW application security bits */ - if (prop->fw_security_status_valid) - prop->fw_app_security_map = RREG32(mmCPU_BOOT_DEV_STS0); + if (prop->fw_cpu_boot_dev_sts0_valid) + prop->fw_app_cpu_boot_dev_sts0 = RREG32(mmCPU_BOOT_DEV_STS0); + + if (prop->fw_cpu_boot_dev_sts1_valid) + prop->fw_app_cpu_boot_dev_sts1 = RREG32(mmCPU_BOOT_DEV_STS1); goya->hw_cap_initialized |= HW_CAP_CPU_Q; return 0; @@ -2402,47 +2444,67 @@ static int goya_load_boot_fit_to_device(struct hl_device *hdev) return hl_fw_load_fw_to_device(hdev, GOYA_BOOT_FIT_FILE, dst, 0, 0); } -/* - * FW component passes an offset from SRAM_BASE_ADDR in SCRATCHPAD_xx. - * The version string should be located by that offset. - */ -static int goya_read_device_fw_version(struct hl_device *hdev, - enum hl_fw_component fwc) -{ - const char *name; - u32 ver_off; - char *dest; - - switch (fwc) { - case FW_COMP_UBOOT: - ver_off = RREG32(mmUBOOT_VER_OFFSET); - dest = hdev->asic_prop.uboot_ver; - name = "U-Boot"; - break; - case FW_COMP_PREBOOT: - ver_off = RREG32(mmPREBOOT_VER_OFFSET); - dest = hdev->asic_prop.preboot_ver; - name = "Preboot"; - break; - default: - dev_warn(hdev->dev, "Undefined FW component: %d\n", fwc); - return -EIO; - } +static void goya_init_dynamic_firmware_loader(struct hl_device *hdev) +{ + struct dynamic_fw_load_mgr *dynamic_loader; + struct cpu_dyn_regs *dyn_regs; - ver_off &= ~((u32)SRAM_BASE_ADDR); + dynamic_loader = &hdev->fw_loader.dynamic_loader; - if (ver_off < SRAM_SIZE - VERSION_MAX_LEN) { - memcpy_fromio(dest, hdev->pcie_bar[SRAM_CFG_BAR_ID] + ver_off, - VERSION_MAX_LEN); - } else { - dev_err(hdev->dev, "%s version offset (0x%x) is above SRAM\n", - name, ver_off); - strcpy(dest, "unavailable"); + /* + * here we update initial values for few specific dynamic regs (as + * before reading the first descriptor from FW those value has to be + * hard-coded) in later stages of the protocol those values will be + * updated automatically by reading the FW descriptor so data there + * will always be up-to-date + */ + dyn_regs = &dynamic_loader->comm_desc.cpu_dyn_regs; + dyn_regs->kmd_msg_to_cpu = + cpu_to_le32(mmPSOC_GLOBAL_CONF_KMD_MSG_TO_CPU); + dyn_regs->cpu_cmd_status_to_host = + cpu_to_le32(mmCPU_CMD_STATUS_TO_HOST); - return -EIO; - } + dynamic_loader->wait_for_bl_timeout = GOYA_WAIT_FOR_BL_TIMEOUT_USEC; +} - return 0; +static void goya_init_static_firmware_loader(struct hl_device *hdev) +{ + struct static_fw_load_mgr *static_loader; + + static_loader = &hdev->fw_loader.static_loader; + + static_loader->preboot_version_max_off = SRAM_SIZE - VERSION_MAX_LEN; + static_loader->boot_fit_version_max_off = SRAM_SIZE - VERSION_MAX_LEN; + static_loader->kmd_msg_to_cpu_reg = mmPSOC_GLOBAL_CONF_KMD_MSG_TO_CPU; + static_loader->cpu_cmd_status_to_host_reg = mmCPU_CMD_STATUS_TO_HOST; + static_loader->cpu_boot_status_reg = mmPSOC_GLOBAL_CONF_CPU_BOOT_STATUS; + static_loader->cpu_boot_dev_status0_reg = mmCPU_BOOT_DEV_STS0; + static_loader->cpu_boot_dev_status1_reg = mmCPU_BOOT_DEV_STS1; + static_loader->boot_err0_reg = mmCPU_BOOT_ERR0; + static_loader->boot_err1_reg = mmCPU_BOOT_ERR1; + static_loader->preboot_version_offset_reg = mmPREBOOT_VER_OFFSET; + static_loader->boot_fit_version_offset_reg = mmUBOOT_VER_OFFSET; + static_loader->sram_offset_mask = ~(lower_32_bits(SRAM_BASE_ADDR)); +} + +static void goya_init_firmware_loader(struct hl_device *hdev) +{ + struct asic_fixed_properties *prop = &hdev->asic_prop; + struct fw_load_mgr *fw_loader = &hdev->fw_loader; + + /* fill common fields */ + fw_loader->boot_fit_img.image_name = GOYA_BOOT_FIT_FILE; + fw_loader->linux_img.image_name = GOYA_LINUX_FW_FILE; + fw_loader->cpu_timeout = GOYA_CPU_TIMEOUT_USEC; + fw_loader->boot_fit_timeout = GOYA_BOOT_FIT_REQ_TIMEOUT_USEC; + fw_loader->skip_bmc = false; + fw_loader->sram_bar_id = SRAM_CFG_BAR_ID; + fw_loader->dram_bar_id = DDR_BAR_ID; + + if (prop->dynamic_fw_load) + goya_init_dynamic_firmware_loader(hdev); + else + goya_init_static_firmware_loader(hdev); } static int goya_init_cpu(struct hl_device *hdev) @@ -2466,12 +2528,7 @@ static int goya_init_cpu(struct hl_device *hdev) return -EIO; } - rc = hl_fw_init_cpu(hdev, mmPSOC_GLOBAL_CONF_CPU_BOOT_STATUS, - mmPSOC_GLOBAL_CONF_UBOOT_MAGIC, - mmCPU_CMD_STATUS_TO_HOST, - mmCPU_BOOT_DEV_STS0, mmCPU_BOOT_ERR0, - false, GOYA_CPU_TIMEOUT_USEC, - GOYA_BOOT_FIT_REQ_TIMEOUT_USEC); + rc = hl_fw_init_cpu(hdev); if (rc) return rc; @@ -2881,7 +2938,7 @@ void *goya_get_int_queue_base(struct hl_device *hdev, u32 queue_id, *dma_handle = hdev->asic_prop.sram_base_address; - base = (void *) hdev->pcie_bar[SRAM_CFG_BAR_ID]; + base = (__force void *) hdev->pcie_bar[SRAM_CFG_BAR_ID]; switch (queue_id) { case GOYA_QUEUE_ID_MME: @@ -3270,6 +3327,7 @@ already_pinned: return 0; unpin_memory: + list_del(&userptr->job_node); hl_unpin_host_memory(hdev, userptr); free_userptr: kfree(userptr); @@ -5169,54 +5227,13 @@ static int goya_mmu_invalidate_cache(struct hl_device *hdev, bool is_hard, } static int goya_mmu_invalidate_cache_range(struct hl_device *hdev, - bool is_hard, u32 asid, u64 va, u64 size) + bool is_hard, u32 flags, + u32 asid, u64 va, u64 size) { - struct goya_device *goya = hdev->asic_specific; - u32 status, timeout_usec, inv_data, pi; - int rc; - - if (!(goya->hw_cap_initialized & HW_CAP_MMU) || - hdev->hard_reset_pending) - return 0; - - /* no need in L1 only invalidation in Goya */ - if (!is_hard) - return 0; - - if (hdev->pldm) - timeout_usec = GOYA_PLDM_MMU_TIMEOUT_USEC; - else - timeout_usec = MMU_CONFIG_TIMEOUT_USEC; - - /* - * TODO: currently invalidate entire L0 & L1 as in regular hard - * invalidation. Need to apply invalidation of specific cache lines with - * mask of ASID & VA & size. - * Note that L1 with be flushed entirely in any case. + /* Treat as invalidate all because there is no range invalidation + * in Goya */ - - /* L0 & L1 invalidation */ - inv_data = RREG32(mmSTLB_CACHE_INV); - /* PI is 8 bit */ - pi = ((inv_data & STLB_CACHE_INV_PRODUCER_INDEX_MASK) + 1) & 0xFF; - WREG32(mmSTLB_CACHE_INV, - (inv_data & STLB_CACHE_INV_INDEX_MASK_MASK) | pi); - - rc = hl_poll_timeout( - hdev, - mmSTLB_INV_CONSUMER_INDEX, - status, - status == pi, - 1000, - timeout_usec); - - if (rc) { - dev_err_ratelimited(hdev->dev, - "MMU cache invalidation timeout\n"); - hl_device_reset(hdev, HL_RESET_HARD); - } - - return rc; + return hdev->asic_funcs->mmu_invalidate_cache(hdev, is_hard, flags); } int goya_send_heartbeat(struct hl_device *hdev) @@ -5239,7 +5256,9 @@ int goya_cpucp_info_get(struct hl_device *hdev) if (!(goya->hw_cap_initialized & HW_CAP_CPU_Q)) return 0; - rc = hl_fw_cpucp_handshake(hdev, mmCPU_BOOT_DEV_STS0, mmCPU_BOOT_ERR0); + rc = hl_fw_cpucp_handshake(hdev, mmCPU_BOOT_DEV_STS0, + mmCPU_BOOT_DEV_STS1, mmCPU_BOOT_ERR0, + mmCPU_BOOT_ERR1); if (rc) return rc; @@ -5385,6 +5404,11 @@ static int goya_get_eeprom_data(struct hl_device *hdev, void *data, return hl_fw_get_eeprom_data(hdev, data, max_size); } +static void goya_cpu_init_scrambler_dram(struct hl_device *hdev) +{ + +} + static int goya_ctx_init(struct hl_ctx *ctx) { if (ctx->asid != HL_KERNEL_ASID_ID) @@ -5565,7 +5589,6 @@ static const struct hl_asic_funcs goya_funcs = { .ctx_fini = goya_ctx_fini, .get_clk_rate = goya_get_clk_rate, .get_queue_id_for_cq = goya_get_queue_id_for_cq, - .read_device_fw_version = goya_read_device_fw_version, .load_firmware_to_device = goya_load_firmware_to_device, .load_boot_fit_to_device = goya_load_boot_fit_to_device, .get_signal_cb_size = goya_get_signal_cb_size, @@ -5584,7 +5607,9 @@ static const struct hl_asic_funcs goya_funcs = { .get_hw_block_id = goya_get_hw_block_id, .hw_block_mmap = goya_block_mmap, .enable_events_from_fw = goya_enable_events_from_fw, - .map_pll_idx_to_fw_idx = goya_map_pll_idx_to_fw_idx + .map_pll_idx_to_fw_idx = goya_map_pll_idx_to_fw_idx, + .init_firmware_loader = goya_init_firmware_loader, + .init_cpu_scrambler_dram = goya_cpu_init_scrambler_dram }; /* diff --git a/drivers/misc/habanalabs/goya/goyaP.h b/drivers/misc/habanalabs/goya/goyaP.h index ef8c6c8b5c8d..0b05da614729 100644 --- a/drivers/misc/habanalabs/goya/goyaP.h +++ b/drivers/misc/habanalabs/goya/goyaP.h @@ -168,7 +168,7 @@ struct goya_device { u8 device_cpu_mmu_mappings_done; }; -int goya_get_fixed_properties(struct hl_device *hdev); +int goya_set_fixed_properties(struct hl_device *hdev); int goya_mmu_init(struct hl_device *hdev); void goya_init_dma_qmans(struct hl_device *hdev); void goya_init_mme_qmans(struct hl_device *hdev); diff --git a/drivers/misc/habanalabs/goya/goya_coresight.c b/drivers/misc/habanalabs/goya/goya_coresight.c index 6b7445cca580..c55c100fdd24 100644 --- a/drivers/misc/habanalabs/goya/goya_coresight.c +++ b/drivers/misc/habanalabs/goya/goya_coresight.c @@ -434,7 +434,7 @@ static int goya_config_etr(struct hl_device *hdev, WREG32(mmPSOC_ETR_BUFWM, 0x3FFC); WREG32(mmPSOC_ETR_RSZ, input->buffer_size); WREG32(mmPSOC_ETR_MODE, input->sink_mode); - if (hdev->asic_prop.fw_security_disabled) { + if (!hdev->asic_prop.fw_security_enabled) { /* make ETR not privileged */ val = FIELD_PREP(PSOC_ETR_AXICTL_PROTCTRLBIT0_MASK, 0); /* make ETR non-secured (inverted logic) */ diff --git a/drivers/misc/habanalabs/include/common/cpucp_if.h b/drivers/misc/habanalabs/include/common/cpucp_if.h index 27cd0ba99aa3..80b1d5a9d9f1 100644 --- a/drivers/misc/habanalabs/include/common/cpucp_if.h +++ b/drivers/misc/habanalabs/include/common/cpucp_if.h @@ -84,6 +84,20 @@ struct hl_eq_sm_sei_data { __u8 pad[3]; }; +enum hl_fw_alive_severity { + FW_ALIVE_SEVERITY_MINOR, + FW_ALIVE_SEVERITY_CRITICAL +}; + +struct hl_eq_fw_alive { + __le64 uptime_seconds; + __le32 process_id; + __le32 thread_id; + /* enum hl_fw_alive_severity */ + __u8 severity; + __u8 pad[7]; +}; + struct hl_eq_entry { struct hl_eq_header hdr; union { @@ -91,6 +105,7 @@ struct hl_eq_entry { struct hl_eq_hbm_ecc_data hbm_ecc_data; struct hl_eq_sm_sei_data sm_sei_data; struct cpucp_pkt_sync_err pkt_sync_err; + struct hl_eq_fw_alive fw_alive; __le64 data[7]; }; }; @@ -103,11 +118,16 @@ struct hl_eq_entry { #define EQ_CTL_EVENT_TYPE_SHIFT 16 #define EQ_CTL_EVENT_TYPE_MASK 0x03FF0000 +#define EQ_CTL_INDEX_SHIFT 0 +#define EQ_CTL_INDEX_MASK 0x0000FFFF + enum pq_init_status { PQ_INIT_STATUS_NA = 0, PQ_INIT_STATUS_READY_FOR_CP, PQ_INIT_STATUS_READY_FOR_HOST, - PQ_INIT_STATUS_READY_FOR_CP_SINGLE_MSI + PQ_INIT_STATUS_READY_FOR_CP_SINGLE_MSI, + PQ_INIT_STATUS_LEN_NOT_POWER_OF_TWO_ERR, + PQ_INIT_STATUS_ILLEGAL_Q_ADDR_ERR }; /* @@ -384,6 +404,20 @@ enum cpucp_packet_id { #define CPUCP_PKT_RES_PLL_OUT3_SHIFT 48 #define CPUCP_PKT_RES_PLL_OUT3_MASK 0xFFFF000000000000ull +#define CPUCP_PKT_VAL_PFC_IN1_SHIFT 0 +#define CPUCP_PKT_VAL_PFC_IN1_MASK 0x0000000000000001ull +#define CPUCP_PKT_VAL_PFC_IN2_SHIFT 1 +#define CPUCP_PKT_VAL_PFC_IN2_MASK 0x000000000000001Eull + +#define CPUCP_PKT_VAL_LPBK_IN1_SHIFT 0 +#define CPUCP_PKT_VAL_LPBK_IN1_MASK 0x0000000000000001ull +#define CPUCP_PKT_VAL_LPBK_IN2_SHIFT 1 +#define CPUCP_PKT_VAL_LPBK_IN2_MASK 0x000000000000001Eull + +/* heartbeat status bits */ +#define CPUCP_PKT_HB_STATUS_EQ_FAULT_SHIFT 0 +#define CPUCP_PKT_HB_STATUS_EQ_FAULT_MASK 0x00000001 + struct cpucp_packet { union { __le64 value; /* For SET packets */ @@ -425,6 +459,12 @@ struct cpucp_packet { /* For get CpuCP info/EEPROM data/NIC info */ __le32 data_max_size; + + /* + * For any general status bitmask. Shall be used whenever the + * result cannot be used to hold general purpose data. + */ + __le32 status_mask; }; __le32 reserved; @@ -629,6 +669,8 @@ struct cpucp_security_info { * @card_name: card name that will be displayed in HWMON subsystem on the host * @sec_info: security information * @pll_map: Bit map of supported PLLs for current ASIC version. + * @mme_binning_mask: MME binning mask, + * (0 = functional, 1 = binned) */ struct cpucp_info { struct cpucp_sensor sensors[CPUCP_MAX_SENSORS]; @@ -651,6 +693,7 @@ struct cpucp_info { struct cpucp_security_info sec_info; __le32 reserved6; __u8 pll_map[PLL_MAP_LEN]; + __le64 mme_binning_mask; }; struct cpucp_mac_addr { diff --git a/drivers/misc/habanalabs/include/common/hl_boot_if.h b/drivers/misc/habanalabs/include/common/hl_boot_if.h index e0a259e0495c..fa8a5ad2d438 100644 --- a/drivers/misc/habanalabs/include/common/hl_boot_if.h +++ b/drivers/misc/habanalabs/include/common/hl_boot_if.h @@ -8,7 +8,7 @@ #ifndef HL_BOOT_IF_H #define HL_BOOT_IF_H -#define LKD_HARD_RESET_MAGIC 0xED7BD694 +#define LKD_HARD_RESET_MAGIC 0xED7BD694 /* deprecated - do not use */ #define HL_POWER9_HOST_MAGIC 0x1DA30009 #define BOOT_FIT_SRAM_OFFSET 0x200000 @@ -99,6 +99,7 @@ #define CPU_BOOT_ERR0_PLL_FAIL (1 << 12) #define CPU_BOOT_ERR0_DEVICE_UNUSABLE_FAIL (1 << 13) #define CPU_BOOT_ERR0_ENABLED (1 << 31) +#define CPU_BOOT_ERR1_ENABLED (1 << 31) /* * BOOT DEVICE STATUS bits in BOOT_DEVICE_STS registers @@ -190,6 +191,24 @@ * PLLs. * Initialized in: linux * + * CPU_BOOT_DEV_STS0_GIC_PRIVILEGED_EN GIC access permission only from + * previleged entity. FW sets this status + * bit for host. If this bit is set then + * GIC can not be accessed from host. + * Initialized in: linux + * + * CPU_BOOT_DEV_STS0_EQ_INDEX_EN Event Queue (EQ) index is a running + * index for each new event sent to host. + * This is used as a method in host to + * identify that the waiting event in + * queue is actually a new event which + * was not served before. + * Initialized in: linux + * + * CPU_BOOT_DEV_STS0_MULTI_IRQ_POLL_EN Use multiple scratchpad interfaces to + * prevent IRQs overriding each other. + * Initialized in: linux + * * CPU_BOOT_DEV_STS0_ENABLED Device status register enabled. * This is a main indication that the * running FW populates the device status @@ -218,7 +237,11 @@ #define CPU_BOOT_DEV_STS0_FW_LD_COM_EN (1 << 16) #define CPU_BOOT_DEV_STS0_FW_IATU_CONF_EN (1 << 17) #define CPU_BOOT_DEV_STS0_DYN_PLL_EN (1 << 19) +#define CPU_BOOT_DEV_STS0_GIC_PRIVILEGED_EN (1 << 20) +#define CPU_BOOT_DEV_STS0_EQ_INDEX_EN (1 << 21) +#define CPU_BOOT_DEV_STS0_MULTI_IRQ_POLL_EN (1 << 22) #define CPU_BOOT_DEV_STS0_ENABLED (1 << 31) +#define CPU_BOOT_DEV_STS1_ENABLED (1 << 31) enum cpu_boot_status { CPU_BOOT_STATUS_NA = 0, /* Default value after reset of chip */ @@ -264,46 +287,98 @@ enum cpu_msg_status { /* communication registers mapping - consider ABI when changing */ struct cpu_dyn_regs { - uint32_t cpu_pq_base_addr_low; - uint32_t cpu_pq_base_addr_high; - uint32_t cpu_pq_length; - uint32_t cpu_pq_init_status; - uint32_t cpu_eq_base_addr_low; - uint32_t cpu_eq_base_addr_high; - uint32_t cpu_eq_length; - uint32_t cpu_eq_ci; - uint32_t cpu_cq_base_addr_low; - uint32_t cpu_cq_base_addr_high; - uint32_t cpu_cq_length; - uint32_t cpu_pf_pq_pi; - uint32_t cpu_boot_dev_sts0; - uint32_t cpu_boot_dev_sts1; - uint32_t cpu_boot_err0; - uint32_t cpu_boot_err1; - uint32_t cpu_boot_status; - uint32_t fw_upd_sts; - uint32_t fw_upd_cmd; - uint32_t fw_upd_pending_sts; - uint32_t fuse_ver_offset; - uint32_t preboot_ver_offset; - uint32_t uboot_ver_offset; - uint32_t hw_state; - uint32_t kmd_msg_to_cpu; - uint32_t cpu_cmd_status_to_host; - uint32_t reserved1[32]; /* reserve for future use */ + __le32 cpu_pq_base_addr_low; + __le32 cpu_pq_base_addr_high; + __le32 cpu_pq_length; + __le32 cpu_pq_init_status; + __le32 cpu_eq_base_addr_low; + __le32 cpu_eq_base_addr_high; + __le32 cpu_eq_length; + __le32 cpu_eq_ci; + __le32 cpu_cq_base_addr_low; + __le32 cpu_cq_base_addr_high; + __le32 cpu_cq_length; + __le32 cpu_pf_pq_pi; + __le32 cpu_boot_dev_sts0; + __le32 cpu_boot_dev_sts1; + __le32 cpu_boot_err0; + __le32 cpu_boot_err1; + __le32 cpu_boot_status; + __le32 fw_upd_sts; + __le32 fw_upd_cmd; + __le32 fw_upd_pending_sts; + __le32 fuse_ver_offset; + __le32 preboot_ver_offset; + __le32 uboot_ver_offset; + __le32 hw_state; + __le32 kmd_msg_to_cpu; + __le32 cpu_cmd_status_to_host; + union { + __le32 gic_host_irq_ctrl; + __le32 gic_host_pi_upd_irq; + }; + __le32 gic_tpc_qm_irq_ctrl; + __le32 gic_mme_qm_irq_ctrl; + __le32 gic_dma_qm_irq_ctrl; + __le32 gic_nic_qm_irq_ctrl; + __le32 gic_dma_core_irq_ctrl; + __le32 gic_host_halt_irq; + __le32 gic_host_ints_irq; + __le32 reserved1[24]; /* reserve for future use */ }; +/* TODO: remove the desc magic after the code is updated to use message */ /* HCDM - Habana Communications Descriptor Magic */ #define HL_COMMS_DESC_MAGIC 0x4843444D #define HL_COMMS_DESC_VER 1 +/* HCMv - Habana Communications Message + header version */ +#define HL_COMMS_MSG_MAGIC_VALUE 0x48434D00 +#define HL_COMMS_MSG_MAGIC_MASK 0xFFFFFF00 +#define HL_COMMS_MSG_MAGIC_VER_MASK 0xFF + +#define HL_COMMS_MSG_MAGIC_VER(ver) (HL_COMMS_MSG_MAGIC_VALUE | \ + ((ver) & HL_COMMS_MSG_MAGIC_VER_MASK)) +#define HL_COMMS_MSG_MAGIC_V0 HL_COMMS_DESC_MAGIC +#define HL_COMMS_MSG_MAGIC_V1 HL_COMMS_MSG_MAGIC_VER(1) + +#define HL_COMMS_MSG_MAGIC HL_COMMS_MSG_MAGIC_V1 + +#define HL_COMMS_MSG_MAGIC_VALIDATE_MAGIC(magic) \ + (((magic) & HL_COMMS_MSG_MAGIC_MASK) == \ + HL_COMMS_MSG_MAGIC_VALUE) + +#define HL_COMMS_MSG_MAGIC_VALIDATE_VERSION(magic, ver) \ + (((magic) & HL_COMMS_MSG_MAGIC_VER_MASK) >= \ + ((ver) & HL_COMMS_MSG_MAGIC_VER_MASK)) + +#define HL_COMMS_MSG_MAGIC_VALIDATE(magic, ver) \ + (HL_COMMS_MSG_MAGIC_VALIDATE_MAGIC((magic)) && \ + HL_COMMS_MSG_MAGIC_VALIDATE_VERSION((magic), (ver))) + +enum comms_msg_type { + HL_COMMS_DESC_TYPE = 0, + HL_COMMS_RESET_CAUSE_TYPE = 1, +}; + +/* TODO: remove this struct after the code is updated to use message */ /* this is the comms descriptor header - meta data */ struct comms_desc_header { - uint32_t magic; /* magic for validation */ - uint32_t crc32; /* CRC32 of the descriptor w/o header */ - uint16_t size; /* size of the descriptor w/o header */ - uint8_t version; /* descriptor version */ - uint8_t reserved[5]; /* pad to 64 bit */ + __le32 magic; /* magic for validation */ + __le32 crc32; /* CRC32 of the descriptor w/o header */ + __le16 size; /* size of the descriptor w/o header */ + __u8 version; /* descriptor version */ + __u8 reserved[5]; /* pad to 64 bit */ +}; + +/* this is the comms message header - meta data */ +struct comms_msg_header { + __le32 magic; /* magic for validation */ + __le32 crc32; /* CRC32 of the message w/o header */ + __le16 size; /* size of the message w/o header */ + __u8 version; /* message payload version */ + __u8 type; /* message type */ + __u8 reserved[4]; /* pad to 64 bit */ }; /* this is the main FW descriptor - consider ABI when changing */ @@ -314,7 +389,36 @@ struct lkd_fw_comms_desc { char cur_fw_ver[VERSION_MAX_LEN]; /* can be used for 1 more version w/o ABI change */ char reserved0[VERSION_MAX_LEN]; - uint64_t img_addr; /* address for next FW component load */ + __le64 img_addr; /* address for next FW component load */ +}; + +enum comms_reset_cause { + HL_RESET_CAUSE_UNKNOWN = 0, + HL_RESET_CAUSE_HEARTBEAT = 1, + HL_RESET_CAUSE_TDR = 2, +}; + +/* TODO: remove define after struct name is aligned on all projects */ +#define lkd_msg_comms lkd_fw_comms_msg + +/* this is the comms message descriptor */ +struct lkd_fw_comms_msg { + struct comms_msg_header header; + /* union for future expantions of new messages */ + union { + struct { + struct cpu_dyn_regs cpu_dyn_regs; + char fuse_ver[VERSION_MAX_LEN]; + char cur_fw_ver[VERSION_MAX_LEN]; + /* can be used for 1 more version w/o ABI change */ + char reserved0[VERSION_MAX_LEN]; + /* address for next FW component load */ + __le64 img_addr; + }; + struct { + __u8 reset_cause; + }; + }; }; /* @@ -386,11 +490,11 @@ enum comms_cmd { struct comms_command { union { /* bit fields are only for FW use */ struct { - unsigned int size :25; /* 32MB max. */ - unsigned int reserved :2; + u32 size :25; /* 32MB max. */ + u32 reserved :2; enum comms_cmd cmd :5; /* 32 commands */ }; - unsigned int val; + __le32 val; }; }; @@ -449,11 +553,11 @@ enum comms_ram_types { struct comms_status { union { /* bit fields are only for FW use */ struct { - unsigned int offset :26; - unsigned int ram_type :2; + u32 offset :26; + enum comms_ram_types ram_type :2; enum comms_sts status :4; /* 16 statuses */ }; - unsigned int val; + __le32 val; }; }; diff --git a/drivers/misc/habanalabs/include/gaudi/gaudi_async_events.h b/drivers/misc/habanalabs/include/gaudi/gaudi_async_events.h index e8651abf84f2..d966bd4dfea6 100644 --- a/drivers/misc/habanalabs/include/gaudi/gaudi_async_events.h +++ b/drivers/misc/habanalabs/include/gaudi/gaudi_async_events.h @@ -252,10 +252,11 @@ enum gaudi_async_event_id { GAUDI_EVENT_HBM3_SPI_0 = 407, GAUDI_EVENT_HBM3_SPI_1 = 408, GAUDI_EVENT_PSOC_GPIO_U16_0 = 421, - GAUDI_EVENT_PI_UPDATE = 484, - GAUDI_EVENT_HALT_MACHINE = 485, - GAUDI_EVENT_INTS_REGISTER = 486, - GAUDI_EVENT_SOFT_RESET = 487, + GAUDI_EVENT_NIC0_CS_DBG_DERR = 483, + GAUDI_EVENT_NIC1_CS_DBG_DERR = 487, + GAUDI_EVENT_NIC2_CS_DBG_DERR = 491, + GAUDI_EVENT_NIC3_CS_DBG_DERR = 495, + GAUDI_EVENT_NIC4_CS_DBG_DERR = 499, GAUDI_EVENT_RAZWI_OR_ADC = 548, GAUDI_EVENT_TPC0_QM = 572, GAUDI_EVENT_TPC1_QM = 573, @@ -303,6 +304,11 @@ enum gaudi_async_event_id { GAUDI_EVENT_NIC3_QP1 = 619, GAUDI_EVENT_NIC4_QP0 = 620, GAUDI_EVENT_NIC4_QP1 = 621, + GAUDI_EVENT_PI_UPDATE = 635, + GAUDI_EVENT_HALT_MACHINE = 636, + GAUDI_EVENT_INTS_REGISTER = 637, + GAUDI_EVENT_SOFT_RESET = 638, + GAUDI_EVENT_FW_ALIVE_S = 645, GAUDI_EVENT_DEV_RESET_REQ = 646, GAUDI_EVENT_PKT_QUEUE_OUT_SYNC = 647, GAUDI_EVENT_FIX_POWER_ENV_S = 658, diff --git a/drivers/misc/habanalabs/include/gaudi/gaudi_async_ids_map_extended.h b/drivers/misc/habanalabs/include/gaudi/gaudi_async_ids_map_extended.h index 3dc79c131805..479b6b038254 100644 --- a/drivers/misc/habanalabs/include/gaudi/gaudi_async_ids_map_extended.h +++ b/drivers/misc/habanalabs/include/gaudi/gaudi_async_ids_map_extended.h @@ -507,23 +507,28 @@ static struct gaudi_async_events_ids_map gaudi_irq_map_table[] = { { .fc_id = 480, .cpu_id = 329, .valid = 0, .name = "" }, { .fc_id = 481, .cpu_id = 330, .valid = 0, .name = "" }, { .fc_id = 482, .cpu_id = 331, .valid = 0, .name = "" }, - { .fc_id = 483, .cpu_id = 332, .valid = 0, .name = "" }, - { .fc_id = 484, .cpu_id = 333, .valid = 1, .name = "PI_UPDATE" }, - { .fc_id = 485, .cpu_id = 334, .valid = 1, .name = "HALT_MACHINE" }, - { .fc_id = 486, .cpu_id = 335, .valid = 1, .name = "INTS_REGISTER" }, - { .fc_id = 487, .cpu_id = 336, .valid = 1, .name = "SOFT_RESET" }, + { .fc_id = 483, .cpu_id = 332, .valid = 1, + .name = "NIC0_CS_DBG_DERR" }, + { .fc_id = 484, .cpu_id = 333, .valid = 0, .name = "" }, + { .fc_id = 485, .cpu_id = 334, .valid = 0, .name = "" }, + { .fc_id = 486, .cpu_id = 335, .valid = 0, .name = "" }, + { .fc_id = 487, .cpu_id = 336, .valid = 1, + .name = "NIC1_CS_DBG_DERR" }, { .fc_id = 488, .cpu_id = 337, .valid = 0, .name = "" }, { .fc_id = 489, .cpu_id = 338, .valid = 0, .name = "" }, { .fc_id = 490, .cpu_id = 339, .valid = 0, .name = "" }, - { .fc_id = 491, .cpu_id = 340, .valid = 0, .name = "" }, + { .fc_id = 491, .cpu_id = 340, .valid = 1, + .name = "NIC2_CS_DBG_DERR" }, { .fc_id = 492, .cpu_id = 341, .valid = 0, .name = "" }, { .fc_id = 493, .cpu_id = 342, .valid = 0, .name = "" }, { .fc_id = 494, .cpu_id = 343, .valid = 0, .name = "" }, - { .fc_id = 495, .cpu_id = 344, .valid = 0, .name = "" }, + { .fc_id = 495, .cpu_id = 344, .valid = 1, + .name = "NIC3_CS_DBG_DERR" }, { .fc_id = 496, .cpu_id = 345, .valid = 0, .name = "" }, { .fc_id = 497, .cpu_id = 346, .valid = 0, .name = "" }, { .fc_id = 498, .cpu_id = 347, .valid = 0, .name = "" }, - { .fc_id = 499, .cpu_id = 348, .valid = 0, .name = "" }, + { .fc_id = 499, .cpu_id = 348, .valid = 1, + .name = "NIC4_CS_DBG_DERR" }, { .fc_id = 500, .cpu_id = 349, .valid = 0, .name = "" }, { .fc_id = 501, .cpu_id = 350, .valid = 0, .name = "" }, { .fc_id = 502, .cpu_id = 351, .valid = 0, .name = "" }, @@ -659,17 +664,17 @@ static struct gaudi_async_events_ids_map gaudi_irq_map_table[] = { { .fc_id = 632, .cpu_id = 481, .valid = 0, .name = "" }, { .fc_id = 633, .cpu_id = 482, .valid = 0, .name = "" }, { .fc_id = 634, .cpu_id = 483, .valid = 0, .name = "" }, - { .fc_id = 635, .cpu_id = 484, .valid = 0, .name = "" }, - { .fc_id = 636, .cpu_id = 485, .valid = 0, .name = "" }, - { .fc_id = 637, .cpu_id = 486, .valid = 0, .name = "" }, - { .fc_id = 638, .cpu_id = 487, .valid = 0, .name = "" }, + { .fc_id = 635, .cpu_id = 484, .valid = 1, .name = "PI_UPDATE" }, + { .fc_id = 636, .cpu_id = 485, .valid = 1, .name = "HALT_MACHINE" }, + { .fc_id = 637, .cpu_id = 486, .valid = 1, .name = "INTS_REGISTER" }, + { .fc_id = 638, .cpu_id = 487, .valid = 1, .name = "SOFT_RESET" }, { .fc_id = 639, .cpu_id = 488, .valid = 0, .name = "" }, { .fc_id = 640, .cpu_id = 489, .valid = 0, .name = "" }, { .fc_id = 641, .cpu_id = 490, .valid = 0, .name = "" }, { .fc_id = 642, .cpu_id = 491, .valid = 0, .name = "" }, { .fc_id = 643, .cpu_id = 492, .valid = 0, .name = "" }, { .fc_id = 644, .cpu_id = 493, .valid = 0, .name = "" }, - { .fc_id = 645, .cpu_id = 494, .valid = 0, .name = "" }, + { .fc_id = 645, .cpu_id = 494, .valid = 1, .name = "FW_ALIVE_S" }, { .fc_id = 646, .cpu_id = 495, .valid = 1, .name = "DEV_RESET_REQ" }, { .fc_id = 647, .cpu_id = 496, .valid = 1, .name = "PKT_QUEUE_OUT_SYNC" }, diff --git a/drivers/misc/habanalabs/include/gaudi/gaudi_fw_if.h b/drivers/misc/habanalabs/include/gaudi/gaudi_fw_if.h index a9f51f9f9e92..34ca4fe50d91 100644 --- a/drivers/misc/habanalabs/include/gaudi/gaudi_fw_if.h +++ b/drivers/misc/habanalabs/include/gaudi/gaudi_fw_if.h @@ -20,6 +20,9 @@ #define UBOOT_FW_OFFSET 0x100000 /* 1MB in SRAM */ #define LINUX_FW_OFFSET 0x800000 /* 8MB in HBM */ +/* HBM thermal delta in [Deg] added to composite (CTemp) */ +#define HBM_TEMP_ADJUST_COEFF 6 + enum gaudi_nic_axi_error { RXB, RXE, @@ -27,6 +30,7 @@ enum gaudi_nic_axi_error { TXE, QPC_RESP, NON_AXI_ERR, + TMR, }; /* @@ -42,6 +46,48 @@ struct eq_nic_sei_event { __u8 pad[6]; }; +/* + * struct gaudi_nic_status - describes the status of a NIC port. + * @port: NIC port index. + * @bad_format_cnt: e.g. CRC. + * @responder_out_of_sequence_psn_cnt: e.g NAK. + * @high_ber_reinit_cnt: link reinit due to high BER. + * @correctable_err_cnt: e.g. bit-flip. + * @uncorrectable_err_cnt: e.g. MAC errors. + * @retraining_cnt: re-training counter. + * @up: is port up. + * @pcs_link: has PCS link. + * @phy_ready: is PHY ready. + * @auto_neg: is Autoneg enabled. + * @timeout_retransmission_cnt: timeout retransmission events + * @high_ber_cnt: high ber events + */ +struct gaudi_nic_status { + __u32 port; + __u32 bad_format_cnt; + __u32 responder_out_of_sequence_psn_cnt; + __u32 high_ber_reinit; + __u32 correctable_err_cnt; + __u32 uncorrectable_err_cnt; + __u32 retraining_cnt; + __u8 up; + __u8 pcs_link; + __u8 phy_ready; + __u8 auto_neg; + __u32 timeout_retransmission_cnt; + __u32 high_ber_cnt; +}; + +struct gaudi_flops_2_data { + union { + struct { + __u32 spsram_init_done : 1; + __u32 reserved : 31; + }; + __u32 data; + }; +}; + #define GAUDI_PLL_FREQ_LOW 200000000 /* 200 MHz */ #endif /* GAUDI_FW_IF_H */ diff --git a/drivers/misc/habanalabs/include/gaudi/gaudi_masks.h b/drivers/misc/habanalabs/include/gaudi/gaudi_masks.h index b53aeda9a982..9aea7e996654 100644 --- a/drivers/misc/habanalabs/include/gaudi/gaudi_masks.h +++ b/drivers/misc/habanalabs/include/gaudi/gaudi_masks.h @@ -66,7 +66,8 @@ #define PCI_DMA_QMAN_GLBL_ERR_CFG_STOP_ON_ERR_EN_MASK (\ (FIELD_PREP(DMA0_QM_GLBL_ERR_CFG_PQF_STOP_ON_ERR_MASK, 0xF)) | \ (FIELD_PREP(DMA0_QM_GLBL_ERR_CFG_CQF_STOP_ON_ERR_MASK, 0xF)) | \ - (FIELD_PREP(DMA0_QM_GLBL_ERR_CFG_CP_STOP_ON_ERR_MASK, 0xF))) + (FIELD_PREP(DMA0_QM_GLBL_ERR_CFG_CP_STOP_ON_ERR_MASK, 0xF)) | \ + (FIELD_PREP(DMA0_QM_GLBL_ERR_CFG_ARB_STOP_ON_ERR_MASK, 0x1))) #define HBM_DMA_QMAN_GLBL_ERR_CFG_MSG_EN_MASK (\ (FIELD_PREP(DMA0_QM_GLBL_ERR_CFG_PQF_ERR_MSG_EN_MASK, 0xF)) | \ @@ -76,7 +77,8 @@ #define HBM_DMA_QMAN_GLBL_ERR_CFG_STOP_ON_ERR_EN_MASK (\ (FIELD_PREP(DMA0_QM_GLBL_ERR_CFG_PQF_STOP_ON_ERR_MASK, 0xF)) | \ (FIELD_PREP(DMA0_QM_GLBL_ERR_CFG_CQF_STOP_ON_ERR_MASK, 0x1F)) | \ - (FIELD_PREP(DMA0_QM_GLBL_ERR_CFG_CP_STOP_ON_ERR_MASK, 0x1F))) + (FIELD_PREP(DMA0_QM_GLBL_ERR_CFG_CP_STOP_ON_ERR_MASK, 0x1F)) | \ + (FIELD_PREP(DMA0_QM_GLBL_ERR_CFG_ARB_STOP_ON_ERR_MASK, 0x1))) #define TPC_QMAN_GLBL_ERR_CFG_MSG_EN_MASK (\ (FIELD_PREP(TPC0_QM_GLBL_ERR_CFG_PQF_ERR_MSG_EN_MASK, 0xF)) | \ @@ -86,7 +88,8 @@ #define TPC_QMAN_GLBL_ERR_CFG_STOP_ON_ERR_EN_MASK (\ (FIELD_PREP(TPC0_QM_GLBL_ERR_CFG_PQF_STOP_ON_ERR_MASK, 0xF)) | \ (FIELD_PREP(TPC0_QM_GLBL_ERR_CFG_CQF_STOP_ON_ERR_MASK, 0x1F)) | \ - (FIELD_PREP(TPC0_QM_GLBL_ERR_CFG_CP_STOP_ON_ERR_MASK, 0x1F))) + (FIELD_PREP(TPC0_QM_GLBL_ERR_CFG_CP_STOP_ON_ERR_MASK, 0x1F)) | \ + (FIELD_PREP(TPC0_QM_GLBL_ERR_CFG_ARB_STOP_ON_ERR_MASK, 0x1))) #define MME_QMAN_GLBL_ERR_CFG_MSG_EN_MASK (\ (FIELD_PREP(MME0_QM_GLBL_ERR_CFG_PQF_ERR_MSG_EN_MASK, 0xF)) | \ @@ -96,7 +99,8 @@ #define MME_QMAN_GLBL_ERR_CFG_STOP_ON_ERR_EN_MASK (\ (FIELD_PREP(MME0_QM_GLBL_ERR_CFG_PQF_STOP_ON_ERR_MASK, 0xF)) | \ (FIELD_PREP(MME0_QM_GLBL_ERR_CFG_CQF_STOP_ON_ERR_MASK, 0x1F)) | \ - (FIELD_PREP(MME0_QM_GLBL_ERR_CFG_CP_STOP_ON_ERR_MASK, 0x1F))) + (FIELD_PREP(MME0_QM_GLBL_ERR_CFG_CP_STOP_ON_ERR_MASK, 0x1F)) | \ + (FIELD_PREP(MME0_QM_GLBL_ERR_CFG_ARB_STOP_ON_ERR_MASK, 0x1))) #define NIC_QMAN_GLBL_ERR_CFG_MSG_EN_MASK (\ (FIELD_PREP(NIC0_QM0_GLBL_ERR_CFG_PQF_ERR_MSG_EN_MASK, 0xF)) | \ @@ -106,7 +110,8 @@ #define NIC_QMAN_GLBL_ERR_CFG_STOP_ON_ERR_EN_MASK (\ (FIELD_PREP(NIC0_QM0_GLBL_ERR_CFG_PQF_STOP_ON_ERR_MASK, 0xF)) | \ (FIELD_PREP(NIC0_QM0_GLBL_ERR_CFG_CQF_STOP_ON_ERR_MASK, 0xF)) | \ - (FIELD_PREP(NIC0_QM0_GLBL_ERR_CFG_CP_STOP_ON_ERR_MASK, 0xF))) + (FIELD_PREP(NIC0_QM0_GLBL_ERR_CFG_CP_STOP_ON_ERR_MASK, 0xF)) | \ + (FIELD_PREP(NIC0_QM0_GLBL_ERR_CFG_ARB_STOP_ON_ERR_MASK, 0x1))) #define QMAN_CGM1_PWR_GATE_EN (FIELD_PREP(DMA0_QM_CGM_CFG1_MASK_TH_MASK, 0xA)) diff --git a/drivers/misc/habanalabs/include/gaudi/gaudi_reg_map.h b/drivers/misc/habanalabs/include/gaudi/gaudi_reg_map.h index 137afedf5f15..d95d4162ae2c 100644 --- a/drivers/misc/habanalabs/include/gaudi/gaudi_reg_map.h +++ b/drivers/misc/habanalabs/include/gaudi/gaudi_reg_map.h @@ -12,6 +12,16 @@ * PSOC scratch-pad registers */ #define mmHW_STATE mmPSOC_GLOBAL_CONF_SCRATCHPAD_0 +/* TODO: remove mmGIC_HOST_IRQ_CTRL_POLL_REG */ +#define mmGIC_HOST_IRQ_CTRL_POLL_REG mmPSOC_GLOBAL_CONF_SCRATCHPAD_1 +#define mmGIC_HOST_PI_UPD_IRQ_POLL_REG mmPSOC_GLOBAL_CONF_SCRATCHPAD_1 +#define mmGIC_TPC_QM_IRQ_CTRL_POLL_REG mmPSOC_GLOBAL_CONF_SCRATCHPAD_2 +#define mmGIC_MME_QM_IRQ_CTRL_POLL_REG mmPSOC_GLOBAL_CONF_SCRATCHPAD_3 +#define mmGIC_DMA_QM_IRQ_CTRL_POLL_REG mmPSOC_GLOBAL_CONF_SCRATCHPAD_4 +#define mmGIC_NIC_QM_IRQ_CTRL_POLL_REG mmPSOC_GLOBAL_CONF_SCRATCHPAD_5 +#define mmGIC_DMA_CR_IRQ_CTRL_POLL_REG mmPSOC_GLOBAL_CONF_SCRATCHPAD_6 +#define mmGIC_HOST_HALT_IRQ_POLL_REG mmPSOC_GLOBAL_CONF_SCRATCHPAD_7 +#define mmGIC_HOST_INTS_IRQ_POLL_REG mmPSOC_GLOBAL_CONF_SCRATCHPAD_8 #define mmCPU_BOOT_DEV_STS0 mmPSOC_GLOBAL_CONF_SCRATCHPAD_20 #define mmCPU_BOOT_DEV_STS1 mmPSOC_GLOBAL_CONF_SCRATCHPAD_21 #define mmFUSE_VER_OFFSET mmPSOC_GLOBAL_CONF_SCRATCHPAD_22 diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c index fea3ae9d8686..8d00df9243c4 100644 --- a/drivers/misc/hpilo.c +++ b/drivers/misc/hpilo.c @@ -693,6 +693,8 @@ static int ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw) { int bar; unsigned long off; + u8 pci_rev_id; + int rc; /* map the memory mapped i/o registers */ hw->mmio_vaddr = pci_iomap(pdev, 1, 0); @@ -702,7 +704,13 @@ static int ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw) } /* map the adapter shared memory region */ - if (pdev->subsystem_device == 0x00E4) { + rc = pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev_id); + if (rc != 0) { + dev_err(&pdev->dev, "Error reading PCI rev id: %d\n", rc); + goto out; + } + + if (pci_rev_id >= PCI_REV_ID_NECHES) { bar = 5; /* Last 8k is reserved for CCBs */ off = pci_resource_len(pdev, bar) - 0x2000; diff --git a/drivers/misc/hpilo.h b/drivers/misc/hpilo.h index f69ff645cac9..d57c34680b09 100644 --- a/drivers/misc/hpilo.h +++ b/drivers/misc/hpilo.h @@ -10,6 +10,9 @@ #define ILO_NAME "hpilo" +/* iLO ASIC PCI revision id */ +#define PCI_REV_ID_NECHES 7 + /* max number of open channel control blocks per device, hw limited to 32 */ #define MAX_CCB 24 /* min number of open channel control blocks per device, hw limited to 32 */ diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c index 4edad6c445d3..dc8a06c06c63 100644 --- a/drivers/misc/ibmasm/module.c +++ b/drivers/misc/ibmasm/module.c @@ -111,7 +111,7 @@ static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id) result = ibmasm_init_remote_input_dev(sp); if (result) { dev_err(sp->dev, "Failed to initialize remote queue\n"); - goto error_send_message; + goto error_init_remote; } result = ibmasm_send_driver_vpd(sp); @@ -131,8 +131,9 @@ static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return 0; error_send_message: - disable_sp_interrupts(sp->base_address); ibmasm_free_remote_input_dev(sp); +error_init_remote: + disable_sp_interrupts(sp->base_address); free_irq(sp->irq, (void *)sp); error_request_irq: iounmap(sp->base_address); diff --git a/drivers/misc/ibmasm/remote.h b/drivers/misc/ibmasm/remote.h index 8d364462aeea..ec4e78ec5a67 100644 --- a/drivers/misc/ibmasm/remote.h +++ b/drivers/misc/ibmasm/remote.h @@ -43,7 +43,7 @@ #define REMOTE_BUTTON_MIDDLE 0x02 #define REMOTE_BUTTON_RIGHT 0x04 -/* size of keysym/keycode translation matricies */ +/* size of keysym/keycode translation matrices */ #define XLATE_SIZE 256 struct mouse_input { diff --git a/drivers/misc/lattice-ecp3-config.c b/drivers/misc/lattice-ecp3-config.c index 5eaf74447ca1..0f54730c7ed5 100644 --- a/drivers/misc/lattice-ecp3-config.c +++ b/drivers/misc/lattice-ecp3-config.c @@ -198,7 +198,7 @@ static int lattice_ecp3_probe(struct spi_device *spi) spi_set_drvdata(spi, data); init_completion(&data->fw_loaded); - err = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, + err = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, FIRMWARE_NAME, &spi->dev, GFP_KERNEL, spi, firmware_load); if (err) { diff --git a/drivers/misc/lkdtm/bugs.c b/drivers/misc/lkdtm/bugs.c index a164896dc6d4..88c218a9f8b3 100644 --- a/drivers/misc/lkdtm/bugs.c +++ b/drivers/misc/lkdtm/bugs.c @@ -161,6 +161,9 @@ void lkdtm_UNALIGNED_LOAD_STORE_WRITE(void) if (*p == 0) val = 0x87654321; *p = val; + + if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) + pr_err("XFAIL: arch has CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS\n"); } void lkdtm_SOFTLOCKUP(void) @@ -300,8 +303,10 @@ void lkdtm_CORRUPT_LIST_ADD(void) if (target[0] == NULL && target[1] == NULL) pr_err("Overwrite did not happen, but no BUG?!\n"); - else + else { pr_err("list_add() corruption not detected!\n"); + pr_expected_config(CONFIG_DEBUG_LIST); + } } void lkdtm_CORRUPT_LIST_DEL(void) @@ -325,8 +330,10 @@ void lkdtm_CORRUPT_LIST_DEL(void) if (target[0] == NULL && target[1] == NULL) pr_err("Overwrite did not happen, but no BUG?!\n"); - else + else { pr_err("list_del() corruption not detected!\n"); + pr_expected_config(CONFIG_DEBUG_LIST); + } } /* Test that VMAP_STACK is actually allocating with a leading guard page */ diff --git a/drivers/misc/lkdtm/cfi.c b/drivers/misc/lkdtm/cfi.c index e73ebdbfa806..c9aeddef1044 100644 --- a/drivers/misc/lkdtm/cfi.c +++ b/drivers/misc/lkdtm/cfi.c @@ -38,5 +38,6 @@ void lkdtm_CFI_FORWARD_PROTO(void) func = (void *)lkdtm_increment_int; func(&called_count); - pr_info("Fail: survived mismatched prototype function call!\n"); + pr_err("FAIL: survived mismatched prototype function call!\n"); + pr_expected_config(CONFIG_CFI_CLANG); } diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c index 8024b6a5cc7f..9dda87c6b54a 100644 --- a/drivers/misc/lkdtm/core.c +++ b/drivers/misc/lkdtm/core.c @@ -26,6 +26,7 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/debugfs.h> +#include <linux/init.h> #define DEFAULT_COUNT 10 @@ -120,11 +121,14 @@ static const struct crashtype crashtypes[] = { CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE), CRASHTYPE(FORTIFY_OBJECT), CRASHTYPE(FORTIFY_SUBOBJECT), - CRASHTYPE(OVERWRITE_ALLOCATION), + CRASHTYPE(SLAB_LINEAR_OVERFLOW), + CRASHTYPE(VMALLOC_LINEAR_OVERFLOW), CRASHTYPE(WRITE_AFTER_FREE), CRASHTYPE(READ_AFTER_FREE), CRASHTYPE(WRITE_BUDDY_AFTER_FREE), CRASHTYPE(READ_BUDDY_AFTER_FREE), + CRASHTYPE(SLAB_INIT_ON_ALLOC), + CRASHTYPE(BUDDY_INIT_ON_ALLOC), CRASHTYPE(SLAB_FREE_DOUBLE), CRASHTYPE(SLAB_FREE_CROSS), CRASHTYPE(SLAB_FREE_PAGE), @@ -177,9 +181,7 @@ static const struct crashtype crashtypes[] = { CRASHTYPE(STACKLEAK_ERASING), CRASHTYPE(CFI_FORWARD_PROTO), CRASHTYPE(FORTIFIED_STRSCPY), -#ifdef CONFIG_X86_32 CRASHTYPE(DOUBLE_FAULT), -#endif #ifdef CONFIG_PPC_BOOK3S_64 CRASHTYPE(PPC_SLB_MULTIHIT), #endif @@ -399,6 +401,56 @@ static ssize_t direct_entry(struct file *f, const char __user *user_buf, return count; } +#ifndef MODULE +/* + * To avoid needing to export parse_args(), just don't use this code + * when LKDTM is built as a module. + */ +struct check_cmdline_args { + const char *param; + int value; +}; + +static int lkdtm_parse_one(char *param, char *val, + const char *unused, void *arg) +{ + struct check_cmdline_args *args = arg; + + /* short circuit if we already found a value. */ + if (args->value != -ESRCH) + return 0; + if (strncmp(param, args->param, strlen(args->param)) == 0) { + bool bool_result; + int ret; + + ret = kstrtobool(val, &bool_result); + if (ret == 0) + args->value = bool_result; + } + return 0; +} + +int lkdtm_check_bool_cmdline(const char *param) +{ + char *command_line; + struct check_cmdline_args args = { + .param = param, + .value = -ESRCH, + }; + + command_line = kstrdup(saved_command_line, GFP_KERNEL); + if (!command_line) + return -ENOMEM; + + parse_args("Setting sysctl args", command_line, + NULL, 0, -1, -1, &args, lkdtm_parse_one); + + kfree(command_line); + + return args.value; +} +#endif + static struct dentry *lkdtm_debugfs_root; static int __init lkdtm_module_init(void) diff --git a/drivers/misc/lkdtm/fortify.c b/drivers/misc/lkdtm/fortify.c index faf29cf04baa..0f51d31b57ca 100644 --- a/drivers/misc/lkdtm/fortify.c +++ b/drivers/misc/lkdtm/fortify.c @@ -76,7 +76,8 @@ void lkdtm_FORTIFIED_STRSCPY(void) */ strscpy(dst, src, strlen(src)); - pr_warn("FAIL: No overflow in above strscpy()\n"); + pr_err("FAIL: strscpy() overflow not detected!\n"); + pr_expected_config(CONFIG_FORTIFY_SOURCE); kfree(src); } diff --git a/drivers/misc/lkdtm/heap.c b/drivers/misc/lkdtm/heap.c index 1323bc16f113..3d9aae5821a0 100644 --- a/drivers/misc/lkdtm/heap.c +++ b/drivers/misc/lkdtm/heap.c @@ -5,6 +5,7 @@ */ #include "lkdtm.h" #include <linux/slab.h> +#include <linux/vmalloc.h> #include <linux/sched.h> static struct kmem_cache *double_free_cache; @@ -12,17 +13,36 @@ static struct kmem_cache *a_cache; static struct kmem_cache *b_cache; /* + * If there aren't guard pages, it's likely that a consecutive allocation will + * let us overflow into the second allocation without overwriting something real. + */ +void lkdtm_VMALLOC_LINEAR_OVERFLOW(void) +{ + char *one, *two; + + one = vzalloc(PAGE_SIZE); + two = vzalloc(PAGE_SIZE); + + pr_info("Attempting vmalloc linear overflow ...\n"); + memset(one, 0xAA, PAGE_SIZE + 1); + + vfree(two); + vfree(one); +} + +/* * This tries to stay within the next largest power-of-2 kmalloc cache * to avoid actually overwriting anything important if it's not detected * correctly. */ -void lkdtm_OVERWRITE_ALLOCATION(void) +void lkdtm_SLAB_LINEAR_OVERFLOW(void) { size_t len = 1020; u32 *data = kmalloc(len, GFP_KERNEL); if (!data) return; + pr_info("Attempting slab linear overflow ...\n"); data[1024 / sizeof(u32)] = 0x12345678; kfree(data); } @@ -89,9 +109,10 @@ void lkdtm_READ_AFTER_FREE(void) if (saw != *val) { /* Good! Poisoning happened, so declare a win. */ pr_info("Memory correctly poisoned (%x)\n", saw); - BUG(); + } else { + pr_err("FAIL: Memory was not poisoned!\n"); + pr_expected_config_param(CONFIG_INIT_ON_FREE_DEFAULT_ON, "init_on_free"); } - pr_info("Memory was not poisoned\n"); kfree(val); } @@ -145,13 +166,79 @@ void lkdtm_READ_BUDDY_AFTER_FREE(void) if (saw != *val) { /* Good! Poisoning happened, so declare a win. */ pr_info("Memory correctly poisoned (%x)\n", saw); - BUG(); + } else { + pr_err("FAIL: Buddy page was not poisoned!\n"); + pr_expected_config_param(CONFIG_INIT_ON_FREE_DEFAULT_ON, "init_on_free"); + } + + kfree(val); +} + +void lkdtm_SLAB_INIT_ON_ALLOC(void) +{ + u8 *first; + u8 *val; + + first = kmalloc(512, GFP_KERNEL); + if (!first) { + pr_info("Unable to allocate 512 bytes the first time.\n"); + return; + } + + memset(first, 0xAB, 512); + kfree(first); + + val = kmalloc(512, GFP_KERNEL); + if (!val) { + pr_info("Unable to allocate 512 bytes the second time.\n"); + return; + } + if (val != first) { + pr_warn("Reallocation missed clobbered memory.\n"); } - pr_info("Buddy page was not poisoned\n"); + if (memchr(val, 0xAB, 512) == NULL) { + pr_info("Memory appears initialized (%x, no earlier values)\n", *val); + } else { + pr_err("FAIL: Slab was not initialized\n"); + pr_expected_config_param(CONFIG_INIT_ON_ALLOC_DEFAULT_ON, "init_on_alloc"); + } kfree(val); } +void lkdtm_BUDDY_INIT_ON_ALLOC(void) +{ + u8 *first; + u8 *val; + + first = (u8 *)__get_free_page(GFP_KERNEL); + if (!first) { + pr_info("Unable to allocate first free page\n"); + return; + } + + memset(first, 0xAB, PAGE_SIZE); + free_page((unsigned long)first); + + val = (u8 *)__get_free_page(GFP_KERNEL); + if (!val) { + pr_info("Unable to allocate second free page\n"); + return; + } + + if (val != first) { + pr_warn("Reallocation missed clobbered memory.\n"); + } + + if (memchr(val, 0xAB, PAGE_SIZE) == NULL) { + pr_info("Memory appears initialized (%x, no earlier values)\n", *val); + } else { + pr_err("FAIL: Slab was not initialized\n"); + pr_expected_config_param(CONFIG_INIT_ON_ALLOC_DEFAULT_ON, "init_on_alloc"); + } + free_page((unsigned long)val); +} + void lkdtm_SLAB_FREE_DOUBLE(void) { int *val; diff --git a/drivers/misc/lkdtm/lkdtm.h b/drivers/misc/lkdtm/lkdtm.h index 99f90d3e5e9c..6a30b60519f3 100644 --- a/drivers/misc/lkdtm/lkdtm.h +++ b/drivers/misc/lkdtm/lkdtm.h @@ -6,6 +6,47 @@ #include <linux/kernel.h> +#define pr_expected_config(kconfig) \ +{ \ + if (IS_ENABLED(kconfig)) \ + pr_err("Unexpected! This kernel was built with " #kconfig "=y\n"); \ + else \ + pr_warn("This is probably expected, since this kernel was built *without* " #kconfig "=y\n"); \ +} + +#ifndef MODULE +int lkdtm_check_bool_cmdline(const char *param); +#define pr_expected_config_param(kconfig, param) \ +{ \ + if (IS_ENABLED(kconfig)) { \ + switch (lkdtm_check_bool_cmdline(param)) { \ + case 0: \ + pr_warn("This is probably expected, since this kernel was built with " #kconfig "=y but booted with '" param "=N'\n"); \ + break; \ + case 1: \ + pr_err("Unexpected! This kernel was built with " #kconfig "=y and booted with '" param "=Y'\n"); \ + break; \ + default: \ + pr_err("Unexpected! This kernel was built with " #kconfig "=y (and booted without '" param "' specified)\n"); \ + } \ + } else { \ + switch (lkdtm_check_bool_cmdline(param)) { \ + case 0: \ + pr_warn("This is probably expected, as kernel was built *without* " #kconfig "=y and booted with '" param "=N'\n"); \ + break; \ + case 1: \ + pr_err("Unexpected! This kernel was built *without* " #kconfig "=y but booted with '" param "=Y'\n"); \ + break; \ + default: \ + pr_err("This is probably expected, since this kernel was built *without* " #kconfig "=y (and booted without '" param "' specified)\n"); \ + break; \ + } \ + } \ +} +#else +#define pr_expected_config_param(kconfig, param) pr_expected_config(kconfig) +#endif + /* bugs.c */ void __init lkdtm_bugs_init(int *recur_param); void lkdtm_PANIC(void); @@ -39,11 +80,14 @@ void lkdtm_FORTIFY_SUBOBJECT(void); /* heap.c */ void __init lkdtm_heap_init(void); void __exit lkdtm_heap_exit(void); -void lkdtm_OVERWRITE_ALLOCATION(void); +void lkdtm_VMALLOC_LINEAR_OVERFLOW(void); +void lkdtm_SLAB_LINEAR_OVERFLOW(void); void lkdtm_WRITE_AFTER_FREE(void); void lkdtm_READ_AFTER_FREE(void); void lkdtm_WRITE_BUDDY_AFTER_FREE(void); void lkdtm_READ_BUDDY_AFTER_FREE(void); +void lkdtm_SLAB_INIT_ON_ALLOC(void); +void lkdtm_BUDDY_INIT_ON_ALLOC(void); void lkdtm_SLAB_FREE_DOUBLE(void); void lkdtm_SLAB_FREE_CROSS(void); void lkdtm_SLAB_FREE_PAGE(void); diff --git a/drivers/misc/lkdtm/stackleak.c b/drivers/misc/lkdtm/stackleak.c index d1a5c0705be3..00db21ff115e 100644 --- a/drivers/misc/lkdtm/stackleak.c +++ b/drivers/misc/lkdtm/stackleak.c @@ -74,8 +74,8 @@ void lkdtm_STACKLEAK_ERASING(void) end: if (test_failed) { - pr_err("FAIL: the thread stack is NOT properly erased\n"); - dump_stack(); + pr_err("FAIL: the thread stack is NOT properly erased!\n"); + pr_expected_config(CONFIG_GCC_PLUGIN_STACKLEAK); } else { pr_info("OK: the rest of the thread stack is properly erased\n"); } diff --git a/drivers/misc/lkdtm/usercopy.c b/drivers/misc/lkdtm/usercopy.c index 15d220ef35a5..9161ce7ed47a 100644 --- a/drivers/misc/lkdtm/usercopy.c +++ b/drivers/misc/lkdtm/usercopy.c @@ -173,6 +173,8 @@ static void do_usercopy_heap_size(bool to_user) goto free_user; } } + pr_err("FAIL: bad usercopy not detected!\n"); + pr_expected_config_param(CONFIG_HARDENED_USERCOPY, "hardened_usercopy"); free_user: vm_munmap(user_addr, PAGE_SIZE); @@ -248,6 +250,8 @@ static void do_usercopy_heap_whitelist(bool to_user) goto free_user; } } + pr_err("FAIL: bad usercopy not detected!\n"); + pr_expected_config_param(CONFIG_HARDENED_USERCOPY, "hardened_usercopy"); free_user: vm_munmap(user_alloc, PAGE_SIZE); @@ -319,7 +323,8 @@ void lkdtm_USERCOPY_KERNEL(void) pr_warn("copy_to_user failed, but lacked Oops\n"); goto free_user; } - pr_err("FAIL: survived bad copy_to_user()\n"); + pr_err("FAIL: bad copy_to_user() not detected!\n"); + pr_expected_config_param(CONFIG_HARDENED_USERCOPY, "hardened_usercopy"); free_user: vm_munmap(user_addr, PAGE_SIZE); diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c index d8e760b11ae3..67844089db21 100644 --- a/drivers/misc/mei/bus-fixup.c +++ b/drivers/misc/mei/bus-fixup.c @@ -498,7 +498,7 @@ static struct mei_fixup { }; /** - * mei_cldev_fixup - run fixup handlers + * mei_cl_bus_dev_fixup - run fixup handlers * * @cldev: me client device */ diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 2cc370adb238..96f4e59c32a5 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -326,7 +326,7 @@ void mei_io_cb_free(struct mei_cl_cb *cb) } /** - * mei_tx_cb_queue - queue tx callback + * mei_tx_cb_enqueue - queue tx callback * * Locking: called under "dev->device_lock" lock * @@ -1726,12 +1726,15 @@ nortpm: return rets; } -static inline u8 mei_ext_hdr_set_vtag(struct mei_ext_hdr *ext, u8 vtag) +static inline u8 mei_ext_hdr_set_vtag(void *ext, u8 vtag) { - ext->type = MEI_EXT_HDR_VTAG; - ext->ext_payload[0] = vtag; - ext->length = mei_data2slots(sizeof(*ext)); - return ext->length; + struct mei_ext_hdr_vtag *vtag_hdr = ext; + + vtag_hdr->hdr.type = MEI_EXT_HDR_VTAG; + vtag_hdr->hdr.length = mei_data2slots(sizeof(*vtag_hdr)); + vtag_hdr->vtag = vtag; + vtag_hdr->reserved = 0; + return vtag_hdr->hdr.length; } /** @@ -1745,7 +1748,6 @@ static struct mei_msg_hdr *mei_msg_hdr_init(const struct mei_cl_cb *cb) { size_t hdr_len; struct mei_ext_meta_hdr *meta; - struct mei_ext_hdr *ext; struct mei_msg_hdr *mei_hdr; bool is_ext, is_vtag; @@ -1764,7 +1766,7 @@ static struct mei_msg_hdr *mei_msg_hdr_init(const struct mei_cl_cb *cb) hdr_len += sizeof(*meta); if (is_vtag) - hdr_len += sizeof(*ext); + hdr_len += sizeof(struct mei_ext_hdr_vtag); setup_hdr: mei_hdr = kzalloc(hdr_len, GFP_KERNEL); @@ -2250,7 +2252,7 @@ static void mei_cl_dma_free(struct mei_cl *cl) } /** - * mei_cl_alloc_and_map - send client dma map request + * mei_cl_dma_alloc_and_map - send client dma map request * * @cl: host client * @fp: pointer to file structure @@ -2349,7 +2351,7 @@ out: } /** - * mei_cl_unmap_and_free - send client dma unmap request + * mei_cl_dma_unmap - send client dma unmap request * * @cl: host client * @fp: pointer to file structure diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index d0277c7fed10..99b5c1ecc444 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -853,7 +853,7 @@ out: } /** - * mei_hbm_cl_flow_control_res - flow control response from me + * mei_hbm_cl_tx_flow_ctrl_creds_res - flow control response from me * * @dev: the device structure * @fctrl: flow control response bus message diff --git a/drivers/misc/mei/hdcp/Kconfig b/drivers/misc/mei/hdcp/Kconfig index 95b2d6d37f10..54e1c9526909 100644 --- a/drivers/misc/mei/hdcp/Kconfig +++ b/drivers/misc/mei/hdcp/Kconfig @@ -1,4 +1,3 @@ - # SPDX-License-Identifier: GPL-2.0 # Copyright (c) 2019, Intel Corporation. All rights reserved. # diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index cda0829ac589..d3a6c0728645 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -1380,7 +1380,7 @@ static bool mei_me_fw_type_nm(const struct pci_dev *pdev) .quirk_probe = mei_me_fw_type_nm /** - * mei_me_fw_sku_sps_4() - check for sps 4.0 sku + * mei_me_fw_type_sps_4() - check for sps 4.0 sku * * Read ME FW Status register to check for SPS Firmware. * The SPS FW is only signaled in the PCI function 0. @@ -1405,7 +1405,7 @@ static bool mei_me_fw_type_sps_4(const struct pci_dev *pdev) .quirk_probe = mei_me_fw_type_sps_4 /** - * mei_me_fw_sku_sps() - check for sps sku + * mei_me_fw_type_sps() - check for sps sku * * Read ME FW Status register to check for SPS Firmware. * The SPS FW is only signaled in pci function 0 diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h index b10606550613..dfd60c916da0 100644 --- a/drivers/misc/mei/hw.h +++ b/drivers/misc/mei/hw.h @@ -235,9 +235,8 @@ enum mei_ext_hdr_type { struct mei_ext_hdr { u8 type; u8 length; - u8 ext_payload[2]; - u8 hdr[]; -}; + u8 data[]; +} __packed; /** * struct mei_ext_meta_hdr - extend header meta data @@ -250,8 +249,21 @@ struct mei_ext_meta_hdr { u8 count; u8 size; u8 reserved[2]; - struct mei_ext_hdr hdrs[]; -}; + u8 hdrs[]; +} __packed; + +/** + * struct mei_ext_hdr_vtag - extend header for vtag + * + * @hdr: standard extend header + * @vtag: virtual tag + * @reserved: reserved + */ +struct mei_ext_hdr_vtag { + struct mei_ext_hdr hdr; + u8 vtag; + u8 reserved; +} __packed; /* * Extended header iterator functions @@ -266,7 +278,7 @@ struct mei_ext_meta_hdr { */ static inline struct mei_ext_hdr *mei_ext_begin(struct mei_ext_meta_hdr *meta) { - return meta->hdrs; + return (struct mei_ext_hdr *)meta->hdrs; } /** @@ -284,7 +296,7 @@ static inline bool mei_ext_last(struct mei_ext_meta_hdr *meta, } /** - *mei_ext_next - following extended header on the TLV list + * mei_ext_next - following extended header on the TLV list * * @ext: current extend header * @@ -295,7 +307,7 @@ static inline bool mei_ext_last(struct mei_ext_meta_hdr *meta, */ static inline struct mei_ext_hdr *mei_ext_next(struct mei_ext_hdr *ext) { - return (struct mei_ext_hdr *)(ext->hdr + (ext->length * 4)); + return (struct mei_ext_hdr *)((u8 *)ext + (ext->length * 4)); } /** diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index aab3ebfa9fc4..a67f4f2d33a9 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -123,13 +123,13 @@ static int mei_cl_irq_read_msg(struct mei_cl *cl, if (mei_hdr->extended) { struct mei_ext_hdr *ext; - struct mei_ext_hdr *vtag = NULL; + struct mei_ext_hdr_vtag *vtag_hdr = NULL; ext = mei_ext_begin(meta); do { switch (ext->type) { case MEI_EXT_HDR_VTAG: - vtag = ext; + vtag_hdr = (struct mei_ext_hdr_vtag *)ext; break; case MEI_EXT_HDR_NONE: fallthrough; @@ -141,20 +141,20 @@ static int mei_cl_irq_read_msg(struct mei_cl *cl, ext = mei_ext_next(ext); } while (!mei_ext_last(meta, ext)); - if (!vtag) { + if (!vtag_hdr) { cl_dbg(dev, cl, "vtag not found in extended header.\n"); cb->status = -EPROTO; goto discard; } - cl_dbg(dev, cl, "vtag: %d\n", vtag->ext_payload[0]); - if (cb->vtag && cb->vtag != vtag->ext_payload[0]) { + cl_dbg(dev, cl, "vtag: %d\n", vtag_hdr->vtag); + if (cb->vtag && cb->vtag != vtag_hdr->vtag) { cl_err(dev, cl, "mismatched tag: %d != %d\n", - cb->vtag, vtag->ext_payload[0]); + cb->vtag, vtag_hdr->vtag); cb->status = -EPROTO; goto discard; } - cb->vtag = vtag->ext_payload[0]; + cb->vtag = vtag_hdr->vtag; } if (!mei_cl_is_connected(cl)) { @@ -331,7 +331,6 @@ int mei_irq_read_handler(struct mei_device *dev, struct mei_ext_meta_hdr *meta_hdr = NULL; struct mei_cl *cl; int ret; - u32 ext_meta_hdr_u32; u32 hdr_size_left; u32 hdr_size_ext; int i; @@ -367,14 +366,12 @@ int mei_irq_read_handler(struct mei_device *dev, if (mei_hdr->extended) { if (!dev->rd_msg_hdr[1]) { - ext_meta_hdr_u32 = mei_read_hdr(dev); - dev->rd_msg_hdr[1] = ext_meta_hdr_u32; + dev->rd_msg_hdr[1] = mei_read_hdr(dev); dev->rd_msg_hdr_count++; (*slots)--; - dev_dbg(dev->dev, "extended header is %08x\n", - ext_meta_hdr_u32); + dev_dbg(dev->dev, "extended header is %08x\n", dev->rd_msg_hdr[1]); } - meta_hdr = ((struct mei_ext_meta_hdr *)dev->rd_msg_hdr + 1); + meta_hdr = ((struct mei_ext_meta_hdr *)&dev->rd_msg_hdr[1]); if (check_add_overflow((u32)sizeof(*meta_hdr), mei_slots2data(meta_hdr->size), &hdr_size_ext)) { diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 28937b6e7e0c..786f7c8f7f61 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -50,8 +50,6 @@ static int mei_open(struct inode *inode, struct file *file) int err; dev = container_of(inode->i_cdev, struct mei_device, cdev); - if (!dev) - return -ENODEV; mutex_lock(&dev->device_lock); @@ -1104,7 +1102,7 @@ static ssize_t dev_state_show(struct device *device, static DEVICE_ATTR_RO(dev_state); /** - * dev_set_devstate: set to new device state and notify sysfs file. + * mei_set_devstate: set to new device state and notify sysfs file. * * @dev: mei_device * @state: new device state diff --git a/drivers/misc/mei/mei-trace.h b/drivers/misc/mei/mei-trace.h index df758033dc93..fe46ff2b9d69 100644 --- a/drivers/misc/mei/mei-trace.h +++ b/drivers/misc/mei/mei-trace.h @@ -26,7 +26,7 @@ TRACE_EVENT(mei_reg_read, __field(u32, val) ), TP_fast_assign( - __assign_str(dev, dev_name(dev)) + __assign_str(dev, dev_name(dev)); __entry->reg = reg; __entry->offs = offs; __entry->val = val; @@ -45,7 +45,7 @@ TRACE_EVENT(mei_reg_write, __field(u32, val) ), TP_fast_assign( - __assign_str(dev, dev_name(dev)) + __assign_str(dev, dev_name(dev)); __entry->reg = reg; __entry->offs = offs; __entry->val = val; @@ -64,7 +64,7 @@ TRACE_EVENT(mei_pci_cfg_read, __field(u32, val) ), TP_fast_assign( - __assign_str(dev, dev_name(dev)) + __assign_str(dev, dev_name(dev)); __entry->reg = reg; __entry->offs = offs; __entry->val = val; diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c index 4bf26ce61044..aec0483b8e72 100644 --- a/drivers/misc/mei/pci-txe.c +++ b/drivers/misc/mei/pci-txe.c @@ -156,7 +156,7 @@ end: } /** - * mei_txe_remove - Device Shutdown Routine + * mei_txe_shutdown- Device Shutdown Routine * * @pdev: PCI device structure * diff --git a/drivers/misc/pvpanic/pvpanic-mmio.c b/drivers/misc/pvpanic/pvpanic-mmio.c index 4c0841776087..be4016084979 100644 --- a/drivers/misc/pvpanic/pvpanic-mmio.c +++ b/drivers/misc/pvpanic/pvpanic-mmio.c @@ -93,7 +93,7 @@ static int pvpanic_mmio_probe(struct platform_device *pdev) return -EINVAL; } - pi = kmalloc(sizeof(*pi), GFP_ATOMIC); + pi = devm_kmalloc(dev, sizeof(*pi), GFP_KERNEL); if (!pi) return -ENOMEM; @@ -104,19 +104,7 @@ static int pvpanic_mmio_probe(struct platform_device *pdev) pi->capability &= ioread8(base); pi->events = pi->capability; - dev_set_drvdata(dev, pi); - - return pvpanic_probe(pi); -} - -static int pvpanic_mmio_remove(struct platform_device *pdev) -{ - struct pvpanic_instance *pi = dev_get_drvdata(&pdev->dev); - - pvpanic_remove(pi); - kfree(pi); - - return 0; + return devm_pvpanic_probe(dev, pi); } static const struct of_device_id pvpanic_mmio_match[] = { @@ -139,6 +127,5 @@ static struct platform_driver pvpanic_mmio_driver = { .dev_groups = pvpanic_mmio_dev_groups, }, .probe = pvpanic_mmio_probe, - .remove = pvpanic_mmio_remove, }; module_platform_driver(pvpanic_mmio_driver); diff --git a/drivers/misc/pvpanic/pvpanic-pci.c b/drivers/misc/pvpanic/pvpanic-pci.c index 9ecc4e8559d5..a43c401017ae 100644 --- a/drivers/misc/pvpanic/pvpanic-pci.c +++ b/drivers/misc/pvpanic/pvpanic-pci.c @@ -73,20 +73,19 @@ ATTRIBUTE_GROUPS(pvpanic_pci_dev); static int pvpanic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - struct device *dev = &pdev->dev; struct pvpanic_instance *pi; void __iomem *base; int ret; - ret = pci_enable_device(pdev); + ret = pcim_enable_device(pdev); if (ret < 0) return ret; - base = pci_iomap(pdev, 0, 0); + base = pcim_iomap(pdev, 0, 0); if (!base) return -ENOMEM; - pi = kmalloc(sizeof(*pi), GFP_ATOMIC); + pi = devm_kmalloc(&pdev->dev, sizeof(*pi), GFP_KERNEL); if (!pi) return -ENOMEM; @@ -97,26 +96,13 @@ static int pvpanic_pci_probe(struct pci_dev *pdev, pi->capability &= ioread8(base); pi->events = pi->capability; - dev_set_drvdata(dev, pi); - - return pvpanic_probe(pi); -} - -static void pvpanic_pci_remove(struct pci_dev *pdev) -{ - struct pvpanic_instance *pi = dev_get_drvdata(&pdev->dev); - - pvpanic_remove(pi); - iounmap(pi->base); - kfree(pi); - pci_disable_device(pdev); + return devm_pvpanic_probe(&pdev->dev, pi); } static struct pci_driver pvpanic_pci_driver = { .name = "pvpanic-pci", .id_table = pvpanic_pci_id_tbl, .probe = pvpanic_pci_probe, - .remove = pvpanic_pci_remove, .driver = { .dev_groups = pvpanic_pci_dev_groups, }, diff --git a/drivers/misc/pvpanic/pvpanic.c b/drivers/misc/pvpanic/pvpanic.c index 793ea0c01193..02b807c788c9 100644 --- a/drivers/misc/pvpanic/pvpanic.c +++ b/drivers/misc/pvpanic/pvpanic.c @@ -61,25 +61,10 @@ static struct notifier_block pvpanic_panic_nb = { .priority = 1, /* let this called before broken drm_fb_helper */ }; -int pvpanic_probe(struct pvpanic_instance *pi) -{ - if (!pi || !pi->base) - return -EINVAL; - - spin_lock(&pvpanic_lock); - list_add(&pi->list, &pvpanic_list); - spin_unlock(&pvpanic_lock); - - return 0; -} -EXPORT_SYMBOL_GPL(pvpanic_probe); - -void pvpanic_remove(struct pvpanic_instance *pi) +static void pvpanic_remove(void *param) { struct pvpanic_instance *pi_cur, *pi_next; - - if (!pi) - return; + struct pvpanic_instance *pi = param; spin_lock(&pvpanic_lock); list_for_each_entry_safe(pi_cur, pi_next, &pvpanic_list, list) { @@ -90,7 +75,19 @@ void pvpanic_remove(struct pvpanic_instance *pi) } spin_unlock(&pvpanic_lock); } -EXPORT_SYMBOL_GPL(pvpanic_remove); + +int devm_pvpanic_probe(struct device *dev, struct pvpanic_instance *pi) +{ + if (!pi || !pi->base) + return -EINVAL; + + spin_lock(&pvpanic_lock); + list_add(&pi->list, &pvpanic_list); + spin_unlock(&pvpanic_lock); + + return devm_add_action_or_reset(dev, pvpanic_remove, pi); +} +EXPORT_SYMBOL_GPL(devm_pvpanic_probe); static int pvpanic_init(void) { diff --git a/drivers/misc/pvpanic/pvpanic.h b/drivers/misc/pvpanic/pvpanic.h index 1afccc2e9fec..493545951754 100644 --- a/drivers/misc/pvpanic/pvpanic.h +++ b/drivers/misc/pvpanic/pvpanic.h @@ -15,7 +15,6 @@ struct pvpanic_instance { struct list_head list; }; -int pvpanic_probe(struct pvpanic_instance *pi); -void pvpanic_remove(struct pvpanic_instance *pi); +int devm_pvpanic_probe(struct device *dev, struct pvpanic_instance *pi); #endif /* PVPANIC_H_ */ diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c index 202bf951e909..93638ae2753a 100644 --- a/drivers/misc/sram.c +++ b/drivers/misc/sram.c @@ -341,6 +341,7 @@ static int sram_probe(struct platform_device *pdev) { struct sram_dev *sram; int ret; + struct resource *res; int (*init_func)(void); sram = devm_kzalloc(&pdev->dev, sizeof(*sram), GFP_KERNEL); @@ -349,10 +350,11 @@ static int sram_probe(struct platform_device *pdev) sram->dev = &pdev->dev; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (of_property_read_bool(pdev->dev.of_node, "no-memory-wc")) - sram->virt_base = devm_platform_ioremap_resource(pdev, 0); + sram->virt_base = devm_ioremap_resource(&pdev->dev, res); else - sram->virt_base = devm_platform_ioremap_resource_wc(pdev, 0); + sram->virt_base = devm_ioremap_resource_wc(&pdev->dev, res); if (IS_ERR(sram->virt_base)) { dev_err(&pdev->dev, "could not map SRAM registers\n"); return PTR_ERR(sram->virt_base); diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c index 071844b58073..7f6976a9f508 100644 --- a/drivers/misc/ti-st/st_core.c +++ b/drivers/misc/ti-st/st_core.c @@ -52,13 +52,12 @@ static void remove_channel_from_table(struct st_data_s *st_gdata, */ int st_get_uart_wr_room(struct st_data_s *st_gdata) { - struct tty_struct *tty; if (unlikely(st_gdata == NULL || st_gdata->tty == NULL)) { pr_err("tty unavailable to perform write"); return -1; } - tty = st_gdata->tty; - return tty->ops->write_room(tty); + + return tty_write_room(st_gdata->tty); } /* @@ -798,7 +797,7 @@ static void st_tty_close(struct tty_struct *tty) } static void st_tty_receive(struct tty_struct *tty, const unsigned char *data, - char *tty_flags, int count) + const char *tty_flags, int count) { #ifdef VERBOSE print_hex_dump(KERN_DEBUG, ">in>", DUMP_PREFIX_NONE, @@ -845,6 +844,7 @@ static void st_tty_flush_buffer(struct tty_struct *tty) } static struct tty_ldisc_ops st_ldisc_ops = { + .num = N_TI_WL, .name = "n_st", .open = st_tty_open, .close = st_tty_close, @@ -860,7 +860,7 @@ int st_core_init(struct st_data_s **core_data) struct st_data_s *st_gdata; long err; - err = tty_register_ldisc(N_TI_WL, &st_ldisc_ops); + err = tty_register_ldisc(&st_ldisc_ops); if (err) { pr_err("error registering %d line discipline %ld", N_TI_WL, err); @@ -871,11 +871,8 @@ int st_core_init(struct st_data_s **core_data) st_gdata = kzalloc(sizeof(struct st_data_s), GFP_KERNEL); if (!st_gdata) { pr_err("memory allocation failed"); - err = tty_unregister_ldisc(N_TI_WL); - if (err) - pr_err("unable to un-register ldisc %ld", err); err = -ENOMEM; - return err; + goto err_unreg_ldisc; } /* Initialize ST TxQ and Tx waitQ queue head. All BT/FM/GPS module skb's @@ -890,17 +887,18 @@ int st_core_init(struct st_data_s **core_data) err = st_ll_init(st_gdata); if (err) { pr_err("error during st_ll initialization(%ld)", err); - kfree(st_gdata); - err = tty_unregister_ldisc(N_TI_WL); - if (err) - pr_err("unable to un-register ldisc"); - return err; + goto err_free_gdata; } INIT_WORK(&st_gdata->work_write_wakeup, work_fn_write_wakeup); *core_data = st_gdata; return 0; +err_free_gdata: + kfree(st_gdata); +err_unreg_ldisc: + tty_unregister_ldisc(&st_ldisc_ops); + return err; } void st_core_exit(struct st_data_s *st_gdata) @@ -918,9 +916,7 @@ void st_core_exit(struct st_data_s *st_gdata) kfree_skb(st_gdata->rx_skb); kfree_skb(st_gdata->tx_skb); /* TTY ldisc cleanup */ - err = tty_unregister_ldisc(N_TI_WL); - if (err) - pr_err("unable to un-register ldisc %ld", err); + tty_unregister_ldisc(&st_ldisc_ops); /* free the global data pointer */ kfree(st_gdata); } diff --git a/drivers/misc/uacce/uacce.c b/drivers/misc/uacce/uacce.c index bae18ef03dcb..488eeb2811ae 100644 --- a/drivers/misc/uacce/uacce.c +++ b/drivers/misc/uacce/uacce.c @@ -387,15 +387,22 @@ static void uacce_release(struct device *dev) static unsigned int uacce_enable_sva(struct device *parent, unsigned int flags) { + int ret; + if (!(flags & UACCE_DEV_SVA)) return flags; flags &= ~UACCE_DEV_SVA; - if (iommu_dev_enable_feature(parent, IOMMU_DEV_FEAT_IOPF)) + ret = iommu_dev_enable_feature(parent, IOMMU_DEV_FEAT_IOPF); + if (ret) { + dev_err(parent, "failed to enable IOPF feature! ret = %pe\n", ERR_PTR(ret)); return flags; + } - if (iommu_dev_enable_feature(parent, IOMMU_DEV_FEAT_SVA)) { + ret = iommu_dev_enable_feature(parent, IOMMU_DEV_FEAT_SVA); + if (ret) { + dev_err(parent, "failed to enable SVA feature! ret = %pe\n", ERR_PTR(ret)); iommu_dev_disable_feature(parent, IOMMU_DEV_FEAT_IOPF); return flags; } diff --git a/drivers/misc/vmw_vmci/vmci_context.c b/drivers/misc/vmw_vmci/vmci_context.c index 26ff49fdf0f7..c0b5e339d5a1 100644 --- a/drivers/misc/vmw_vmci/vmci_context.c +++ b/drivers/misc/vmw_vmci/vmci_context.c @@ -107,7 +107,7 @@ struct vmci_ctx *vmci_ctx_create(u32 cid, u32 priv_flags, context = kzalloc(sizeof(*context), GFP_KERNEL); if (!context) { pr_warn("Failed to allocate memory for VMCI context\n"); - error = -EINVAL; + error = -ENOMEM; goto err_out; } diff --git a/drivers/misc/xilinx_sdfec.c b/drivers/misc/xilinx_sdfec.c index 23c8448a9c3b..d6e3c650bd11 100644 --- a/drivers/misc/xilinx_sdfec.c +++ b/drivers/misc/xilinx_sdfec.c @@ -1013,9 +1013,6 @@ static __poll_t xsdfec_poll(struct file *file, poll_table *wait) xsdfec = container_of(file->private_data, struct xsdfec_dev, miscdev); - if (!xsdfec) - return EPOLLNVAL | EPOLLHUP; - poll_wait(file, &xsdfec->waitq, wait); /* XSDFEC ISR detected an error */ diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 88f4c215caa6..9890a1532cb0 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -202,7 +202,7 @@ static void mmc_blk_put(struct mmc_blk_data *md) md->usage--; if (md->usage == 0) { int devidx = mmc_get_devidx(md->disk); - blk_put_queue(md->queue.queue); + ida_simple_remove(&mmc_blk_ida, devidx); put_disk(md->disk); kfree(md); @@ -2319,39 +2319,22 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, */ md->read_only = mmc_blk_readonly(card); - md->disk = alloc_disk(perdev_minors); - if (md->disk == NULL) { - ret = -ENOMEM; + md->disk = mmc_init_queue(&md->queue, card); + if (IS_ERR(md->disk)) { + ret = PTR_ERR(md->disk); goto err_kfree; } INIT_LIST_HEAD(&md->part); INIT_LIST_HEAD(&md->rpmbs); md->usage = 1; - - ret = mmc_init_queue(&md->queue, card); - if (ret) - goto err_putdisk; - md->queue.blkdata = md; - /* - * Keep an extra reference to the queue so that we can shutdown the - * queue (i.e. call blk_cleanup_queue()) while there are still - * references to the 'md'. The corresponding blk_put_queue() is in - * mmc_blk_put(). - */ - if (!blk_get_queue(md->queue.queue)) { - mmc_cleanup_queue(&md->queue); - ret = -ENODEV; - goto err_putdisk; - } - md->disk->major = MMC_BLOCK_MAJOR; + md->disk->minors = perdev_minors; md->disk->first_minor = devidx * perdev_minors; md->disk->fops = &mmc_bdops; md->disk->private_data = md; - md->disk->queue = md->queue.queue; md->parent = parent; set_disk_ro(md->disk, md->read_only || default_ro); md->disk->flags = GENHD_FL_EXT_DEVT; @@ -2400,8 +2383,6 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, return md; - err_putdisk: - put_disk(md->disk); err_kfree: kfree(md); out: diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index b039dcff17f8..95fedcf56e4a 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -937,11 +937,14 @@ int mmc_execute_tuning(struct mmc_card *card) err = host->ops->execute_tuning(host, opcode); - if (err) + if (err) { pr_err("%s: tuning execution failed: %d\n", mmc_hostname(host), err); - else + } else { + host->retune_now = 0; + host->need_retune = 0; mmc_retune_enable(host); + } return err; } diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c index d600e0a4a460..cc3261777637 100644 --- a/drivers/mmc/core/queue.c +++ b/drivers/mmc/core/queue.c @@ -424,9 +424,10 @@ static inline bool mmc_merge_capable(struct mmc_host *host) * * Initialise a MMC card request queue. */ -int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card) +struct gendisk *mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card) { struct mmc_host *host = card->host; + struct gendisk *disk; int ret; mq->card = card; @@ -464,26 +465,22 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card) ret = blk_mq_alloc_tag_set(&mq->tag_set); if (ret) - return ret; + return ERR_PTR(ret); + - mq->queue = blk_mq_init_queue(&mq->tag_set); - if (IS_ERR(mq->queue)) { - ret = PTR_ERR(mq->queue); - goto free_tag_set; + disk = blk_mq_alloc_disk(&mq->tag_set, mq); + if (IS_ERR(disk)) { + blk_mq_free_tag_set(&mq->tag_set); + return disk; } + mq->queue = disk->queue; if (mmc_host_is_spi(host) && host->use_spi_crc) blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, mq->queue); - - mq->queue->queuedata = mq; blk_queue_rq_timeout(mq->queue, 60 * HZ); mmc_setup_queue(mq, card); - return 0; - -free_tag_set: - blk_mq_free_tag_set(&mq->tag_set); - return ret; + return disk; } void mmc_queue_suspend(struct mmc_queue *mq) diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h index 3319d8ab57d0..9ade3bcbb714 100644 --- a/drivers/mmc/core/queue.h +++ b/drivers/mmc/core/queue.h @@ -94,7 +94,7 @@ struct mmc_queue { struct work_struct complete_work; }; -extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *); +struct gendisk *mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card); extern void mmc_cleanup_queue(struct mmc_queue *); extern void mmc_queue_suspend(struct mmc_queue *); extern void mmc_queue_resume(struct mmc_queue *); diff --git a/drivers/mmc/core/sdio_uart.c b/drivers/mmc/core/sdio_uart.c index be4067281caa..c36242b86b1d 100644 --- a/drivers/mmc/core/sdio_uart.c +++ b/drivers/mmc/core/sdio_uart.c @@ -439,7 +439,7 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port) tty = tty_port_tty_get(&port->port); if (tty == NULL || !kfifo_len(xmit) || - tty->stopped || tty->hw_stopped) { + tty->flow.stopped || tty->hw_stopped) { sdio_uart_stop_tx(port); tty_kref_put(tty); return; @@ -797,13 +797,13 @@ static int sdio_uart_write(struct tty_struct *tty, const unsigned char *buf, return ret; } -static int sdio_uart_write_room(struct tty_struct *tty) +static unsigned int sdio_uart_write_room(struct tty_struct *tty) { struct sdio_uart_port *port = tty->driver_data; return FIFO_SIZE - kfifo_len(&port->xmit_fifo); } -static int sdio_uart_chars_in_buffer(struct tty_struct *tty) +static unsigned int sdio_uart_chars_in_buffer(struct tty_struct *tty) { struct sdio_uart_port *port = tty->driver_data; return kfifo_len(&port->xmit_fifo); diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index 839965f7c717..0e7c07ed9690 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -1542,6 +1542,8 @@ static int sdhci_arasan_probe(struct platform_device *pdev) } } + sdhci_get_of_property(pdev); + sdhci_arasan->clk_ahb = devm_clk_get(dev, "clk_ahb"); if (IS_ERR(sdhci_arasan->clk_ahb)) { ret = dev_err_probe(dev, PTR_ERR(sdhci_arasan->clk_ahb), @@ -1561,14 +1563,22 @@ static int sdhci_arasan_probe(struct platform_device *pdev) goto err_pltfm_free; } + /* If clock-frequency property is set, use the provided value */ + if (pltfm_host->clock && + pltfm_host->clock != clk_get_rate(clk_xin)) { + ret = clk_set_rate(clk_xin, pltfm_host->clock); + if (ret) { + dev_err(&pdev->dev, "Failed to set SD clock rate\n"); + goto clk_dis_ahb; + } + } + ret = clk_prepare_enable(clk_xin); if (ret) { dev_err(dev, "Unable to enable SD clock.\n"); goto clk_dis_ahb; } - sdhci_get_of_property(pdev); - if (of_property_read_bool(np, "xlnx,fails-without-test-cd")) sdhci_arasan->quirks |= SDHCI_ARASAN_QUIRK_FORCE_CDTEST; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 6aaf5c3ce34c..aba6e10b8605 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1812,6 +1812,10 @@ static u16 sdhci_get_preset_value(struct sdhci_host *host) u16 preset = 0; switch (host->timing) { + case MMC_TIMING_MMC_HS: + case MMC_TIMING_SD_HS: + preset = sdhci_readw(host, SDHCI_PRESET_FOR_HIGH_SPEED); + break; case MMC_TIMING_UHS_SDR12: preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12); break; @@ -4072,9 +4076,13 @@ static void sdhci_allocate_bounce_buffer(struct sdhci_host *host) bounce_size, DMA_BIDIRECTIONAL); ret = dma_mapping_error(mmc_dev(mmc), host->bounce_addr); - if (ret) + if (ret) { + devm_kfree(mmc_dev(mmc), host->bounce_buffer); + host->bounce_buffer = NULL; /* Again fall back to max_segs == 1 */ return; + } + host->bounce_buffer_size = bounce_size; /* Lie about this since we're bouncing */ diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index c35ed4be75b7..074dc182b184 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -255,6 +255,7 @@ /* 60-FB reserved */ +#define SDHCI_PRESET_FOR_HIGH_SPEED 0x64 #define SDHCI_PRESET_FOR_SDR12 0x66 #define SDHCI_PRESET_FOR_SDR25 0x68 #define SDHCI_PRESET_FOR_SDR50 0x6A diff --git a/drivers/mtd/chips/chipreg.c b/drivers/mtd/chips/chipreg.c index ff86373d7d24..a05e103682a4 100644 --- a/drivers/mtd/chips/chipreg.c +++ b/drivers/mtd/chips/chipreg.c @@ -31,14 +31,11 @@ void unregister_mtd_chip_driver(struct mtd_chip_driver *drv) static struct mtd_chip_driver *get_mtd_chip_driver (const char *name) { - struct list_head *pos; struct mtd_chip_driver *ret = NULL, *this; spin_lock(&chip_drvs_lock); - list_for_each(pos, &chip_drvs_list) { - this = list_entry(pos, typeof(*this), list); - + list_for_each_entry(this, &chip_drvs_list, list) { if (!strcmp(this->name, name)) { ret = this; break; diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 0f4c2d823de8..79cb981ececc 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -89,6 +89,12 @@ config MTD_MCHP23K256 platform data, or a device tree description if you want to specify device partitioning +config MTD_MCHP48L640 + tristate "Microchip 48L640 EERAM" + depends on SPI_MASTER + help + This enables access to Microchip 48L640 EERAM chips, using SPI. + config MTD_SPEAR_SMI tristate "SPEAR MTD NOR Support through SMI controller" depends on PLAT_SPEAR || COMPILE_TEST diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index 991c8d12c016..0362cf6bdc67 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_MTD_LART) += lart.o obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o obj-$(CONFIG_MTD_MCHP23K256) += mchp23k256.o +obj-$(CONFIG_MTD_MCHP48L640) += mchp48l640.o obj-$(CONFIG_MTD_SPEAR_SMI) += spear_smi.o obj-$(CONFIG_MTD_SST25L) += sst25l.o obj-$(CONFIG_MTD_BCM47XXSFLASH) += bcm47xxsflash.o diff --git a/drivers/mtd/devices/mchp48l640.c b/drivers/mtd/devices/mchp48l640.c new file mode 100644 index 000000000000..efc2003bd13a --- /dev/null +++ b/drivers/mtd/devices/mchp48l640.c @@ -0,0 +1,373 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for Microchip 48L640 64 Kb SPI Serial EERAM + * + * Copyright Heiko Schocher <hs@denx.de> + * + * datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/20006055B.pdf + * + * we set continuous mode but reading/writing more bytes than + * pagesize seems to bring chip into state where readden values + * are wrong ... no idea why. + * + */ +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/jiffies.h> +#include <linux/module.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> +#include <linux/mutex.h> +#include <linux/sched.h> +#include <linux/sizes.h> +#include <linux/spi/flash.h> +#include <linux/spi/spi.h> +#include <linux/of_device.h> + +struct mchp48_caps { + unsigned int size; + unsigned int page_size; +}; + +struct mchp48l640_flash { + struct spi_device *spi; + struct mutex lock; + struct mtd_info mtd; + const struct mchp48_caps *caps; +}; + +#define MCHP48L640_CMD_WREN 0x06 +#define MCHP48L640_CMD_WRDI 0x04 +#define MCHP48L640_CMD_WRITE 0x02 +#define MCHP48L640_CMD_READ 0x03 +#define MCHP48L640_CMD_WRSR 0x01 +#define MCHP48L640_CMD_RDSR 0x05 + +#define MCHP48L640_STATUS_RDY 0x01 +#define MCHP48L640_STATUS_WEL 0x02 +#define MCHP48L640_STATUS_BP0 0x04 +#define MCHP48L640_STATUS_BP1 0x08 +#define MCHP48L640_STATUS_SWM 0x10 +#define MCHP48L640_STATUS_PRO 0x20 +#define MCHP48L640_STATUS_ASE 0x40 + +#define MCHP48L640_TIMEOUT 100 + +#define MAX_CMD_SIZE 0x10 + +#define to_mchp48l640_flash(x) container_of(x, struct mchp48l640_flash, mtd) + +static int mchp48l640_mkcmd(struct mchp48l640_flash *flash, u8 cmd, loff_t addr, char *buf) +{ + buf[0] = cmd; + buf[1] = addr >> 8; + buf[2] = addr; + + return 3; +} + +static int mchp48l640_read_status(struct mchp48l640_flash *flash, int *status) +{ + unsigned char cmd[2]; + int ret; + + cmd[0] = MCHP48L640_CMD_RDSR; + cmd[1] = 0x00; + mutex_lock(&flash->lock); + ret = spi_write_then_read(flash->spi, &cmd[0], 1, &cmd[1], 1); + mutex_unlock(&flash->lock); + if (!ret) + *status = cmd[1]; + dev_dbg(&flash->spi->dev, "read status ret: %d status: %x", ret, *status); + + return ret; +} + +static int mchp48l640_waitforbit(struct mchp48l640_flash *flash, int bit, bool set) +{ + int ret, status; + unsigned long deadline; + + deadline = jiffies + msecs_to_jiffies(MCHP48L640_TIMEOUT); + do { + ret = mchp48l640_read_status(flash, &status); + dev_dbg(&flash->spi->dev, "read status ret: %d bit: %x %sset status: %x", + ret, bit, (set ? "" : "not"), status); + if (ret) + return ret; + + if (set) { + if ((status & bit) == bit) + return 0; + } else { + if ((status & bit) == 0) + return 0; + } + + usleep_range(1000, 2000); + } while (!time_after_eq(jiffies, deadline)); + + dev_err(&flash->spi->dev, "Timeout waiting for bit %x %s set in status register.", + bit, (set ? "" : "not")); + return -ETIMEDOUT; +} + +static int mchp48l640_write_prepare(struct mchp48l640_flash *flash, bool enable) +{ + unsigned char cmd[2]; + int ret; + + if (enable) + cmd[0] = MCHP48L640_CMD_WREN; + else + cmd[0] = MCHP48L640_CMD_WRDI; + + mutex_lock(&flash->lock); + ret = spi_write(flash->spi, cmd, 1); + mutex_unlock(&flash->lock); + + if (ret) + dev_err(&flash->spi->dev, "write %sable failed ret: %d", + (enable ? "en" : "dis"), ret); + + dev_dbg(&flash->spi->dev, "write %sable success ret: %d", + (enable ? "en" : "dis"), ret); + if (enable) + return mchp48l640_waitforbit(flash, MCHP48L640_STATUS_WEL, true); + + return ret; +} + +static int mchp48l640_set_mode(struct mchp48l640_flash *flash) +{ + unsigned char cmd[2]; + int ret; + + ret = mchp48l640_write_prepare(flash, true); + if (ret) + return ret; + + cmd[0] = MCHP48L640_CMD_WRSR; + cmd[1] = MCHP48L640_STATUS_PRO; + + mutex_lock(&flash->lock); + ret = spi_write(flash->spi, cmd, 2); + mutex_unlock(&flash->lock); + if (ret) + dev_err(&flash->spi->dev, "Could not set continuous mode ret: %d", ret); + + return mchp48l640_waitforbit(flash, MCHP48L640_STATUS_PRO, true); +} + +static int mchp48l640_wait_rdy(struct mchp48l640_flash *flash) +{ + return mchp48l640_waitforbit(flash, MCHP48L640_STATUS_RDY, false); +}; + +static int mchp48l640_write_page(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const unsigned char *buf) +{ + struct mchp48l640_flash *flash = to_mchp48l640_flash(mtd); + unsigned char *cmd; + int ret; + int cmdlen; + + cmd = kmalloc((3 + len), GFP_KERNEL | GFP_DMA); + if (!cmd) + return -ENOMEM; + + ret = mchp48l640_wait_rdy(flash); + if (ret) + goto fail; + + ret = mchp48l640_write_prepare(flash, true); + if (ret) + goto fail; + + mutex_lock(&flash->lock); + cmdlen = mchp48l640_mkcmd(flash, MCHP48L640_CMD_WRITE, to, cmd); + memcpy(&cmd[cmdlen], buf, len); + ret = spi_write(flash->spi, cmd, cmdlen + len); + mutex_unlock(&flash->lock); + if (!ret) + *retlen += len; + else + goto fail; + + ret = mchp48l640_waitforbit(flash, MCHP48L640_STATUS_WEL, false); + if (ret) + goto fail; + + kfree(cmd); + return 0; +fail: + kfree(cmd); + dev_err(&flash->spi->dev, "write fail with: %d", ret); + return ret; +}; + +static int mchp48l640_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const unsigned char *buf) +{ + struct mchp48l640_flash *flash = to_mchp48l640_flash(mtd); + int ret; + size_t wlen = 0; + loff_t woff = to; + size_t ws; + size_t page_sz = flash->caps->page_size; + + /* + * we set PRO bit (page rollover), but writing length > page size + * does result in total chaos, so write in 32 byte chunks. + */ + while (wlen < len) { + ws = min((len - wlen), page_sz); + ret = mchp48l640_write_page(mtd, woff, ws, retlen, &buf[wlen]); + if (ret) + return ret; + wlen += ws; + woff += ws; + } + + return ret; +} + +static int mchp48l640_read_page(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, unsigned char *buf) +{ + struct mchp48l640_flash *flash = to_mchp48l640_flash(mtd); + unsigned char *cmd; + int ret; + int cmdlen; + + cmd = kmalloc((3 + len), GFP_KERNEL | GFP_DMA); + if (!cmd) + return -ENOMEM; + + ret = mchp48l640_wait_rdy(flash); + if (ret) + goto fail; + + mutex_lock(&flash->lock); + cmdlen = mchp48l640_mkcmd(flash, MCHP48L640_CMD_READ, from, cmd); + ret = spi_write_then_read(flash->spi, cmd, cmdlen, buf, len); + mutex_unlock(&flash->lock); + if (!ret) + *retlen += len; + + return ret; + +fail: + kfree(cmd); + dev_err(&flash->spi->dev, "read fail with: %d", ret); + return ret; +} + +static int mchp48l640_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, unsigned char *buf) +{ + struct mchp48l640_flash *flash = to_mchp48l640_flash(mtd); + int ret; + size_t wlen = 0; + loff_t woff = from; + size_t ws; + size_t page_sz = flash->caps->page_size; + + /* + * we set PRO bit (page rollover), but if read length > page size + * does result in total chaos in result ... + */ + while (wlen < len) { + ws = min((len - wlen), page_sz); + ret = mchp48l640_read_page(mtd, woff, ws, retlen, &buf[wlen]); + if (ret) + return ret; + wlen += ws; + woff += ws; + } + + return ret; +}; + +static const struct mchp48_caps mchp48l640_caps = { + .size = SZ_8K, + .page_size = 32, +}; + +static int mchp48l640_probe(struct spi_device *spi) +{ + struct mchp48l640_flash *flash; + struct flash_platform_data *data; + int err; + int status; + + flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL); + if (!flash) + return -ENOMEM; + + flash->spi = spi; + mutex_init(&flash->lock); + spi_set_drvdata(spi, flash); + + err = mchp48l640_read_status(flash, &status); + if (err) + return err; + + err = mchp48l640_set_mode(flash); + if (err) + return err; + + data = dev_get_platdata(&spi->dev); + + flash->caps = of_device_get_match_data(&spi->dev); + if (!flash->caps) + flash->caps = &mchp48l640_caps; + + mtd_set_of_node(&flash->mtd, spi->dev.of_node); + flash->mtd.dev.parent = &spi->dev; + flash->mtd.type = MTD_RAM; + flash->mtd.flags = MTD_CAP_RAM; + flash->mtd.writesize = flash->caps->page_size; + flash->mtd.size = flash->caps->size; + flash->mtd._read = mchp48l640_read; + flash->mtd._write = mchp48l640_write; + + err = mtd_device_register(&flash->mtd, data ? data->parts : NULL, + data ? data->nr_parts : 0); + if (err) + return err; + + return 0; +} + +static int mchp48l640_remove(struct spi_device *spi) +{ + struct mchp48l640_flash *flash = spi_get_drvdata(spi); + + return mtd_device_unregister(&flash->mtd); +} + +static const struct of_device_id mchp48l640_of_table[] = { + { + .compatible = "microchip,48l640", + .data = &mchp48l640_caps, + }, + {} +}; +MODULE_DEVICE_TABLE(of, mchp48l640_of_table); + +static struct spi_driver mchp48l640_driver = { + .driver = { + .name = "mchp48l640", + .of_match_table = of_match_ptr(mchp48l640_of_table), + }, + .probe = mchp48l640_probe, + .remove = mchp48l640_remove, +}; + +module_spi_driver(mchp48l640_driver); + +MODULE_DESCRIPTION("MTD SPI driver for Microchip 48l640 EERAM chips"); +MODULE_AUTHOR("Heiko Schocher <hs@denx.de>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:mchp48l640"); diff --git a/drivers/mtd/devices/ms02-nv.c b/drivers/mtd/devices/ms02-nv.c index fb4a6aa24543..08f76ff839a7 100644 --- a/drivers/mtd/devices/ms02-nv.c +++ b/drivers/mtd/devices/ms02-nv.c @@ -286,7 +286,6 @@ static int __init ms02nv_init(void) break; default: return -ENODEV; - break; } for (i = 0; i < ARRAY_SIZE(ms02nv_addrs); i++) diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index 5b04ae6c3057..6ed6c51fac69 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c @@ -270,6 +270,7 @@ static int phram_setup(const char *val) if (len == 0 || erasesize == 0 || erasesize > len || erasesize > UINT_MAX || rem) { parse_err("illegal erasesize or len\n"); + ret = -EINVAL; goto error; } diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c index af16d3485de0..6276daa296da 100644 --- a/drivers/mtd/inftlmount.c +++ b/drivers/mtd/inftlmount.c @@ -259,20 +259,13 @@ static int find_boot_record(struct INFTLrecord *inftl) /* Memory alloc */ inftl->PUtable = kmalloc_array(inftl->nb_blocks, sizeof(u16), GFP_KERNEL); - if (!inftl->PUtable) { - printk(KERN_WARNING "INFTL: allocation of PUtable " - "failed (%zd bytes)\n", - inftl->nb_blocks * sizeof(u16)); + if (!inftl->PUtable) return -ENOMEM; - } inftl->VUtable = kmalloc_array(inftl->nb_blocks, sizeof(u16), GFP_KERNEL); if (!inftl->VUtable) { kfree(inftl->PUtable); - printk(KERN_WARNING "INFTL: allocation of VUtable " - "failed (%zd bytes)\n", - inftl->nb_blocks * sizeof(u16)); return -ENOMEM; } @@ -330,7 +323,7 @@ static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address, buf = kmalloc(SECTORSIZE + mtd->oobsize, GFP_KERNEL); if (!buf) - return -1; + return -ENOMEM; ret = -1; for (i = 0; i < len; i += SECTORSIZE) { @@ -558,12 +551,8 @@ int INFTL_mount(struct INFTLrecord *s) /* Temporary buffer to store ANAC numbers. */ ANACtable = kcalloc(s->nb_blocks, sizeof(u8), GFP_KERNEL); - if (!ANACtable) { - printk(KERN_WARNING "INFTL: allocation of ANACtable " - "failed (%zd bytes)\n", - s->nb_blocks * sizeof(u8)); + if (!ANACtable) return -ENOMEM; - } /* * First pass is to explore each physical unit, and construct the diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c index 42a95ba40f2c..281fcbaa74e7 100644 --- a/drivers/mtd/maps/amd76xrom.c +++ b/drivers/mtd/maps/amd76xrom.c @@ -189,10 +189,8 @@ static int amd76xrom_init_one(struct pci_dev *pdev, if (!map) { map = kmalloc(sizeof(*map), GFP_KERNEL); - } - if (!map) { - printk(KERN_ERR MOD_NAME ": kmalloc failed"); - goto out; + if (!map) + goto out; } memset(map, 0, sizeof(*map)); INIT_LIST_HEAD(&map->list); diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c index 460494212f6a..c0216bc740cc 100644 --- a/drivers/mtd/maps/ck804xrom.c +++ b/drivers/mtd/maps/ck804xrom.c @@ -217,12 +217,10 @@ static int __init ck804xrom_init_one(struct pci_dev *pdev, unsigned long offset; int i; - if (!map) - map = kmalloc(sizeof(*map), GFP_KERNEL); - if (!map) { - printk(KERN_ERR MOD_NAME ": kmalloc failed"); - goto out; + map = kmalloc(sizeof(*map), GFP_KERNEL); + if (!map) + goto out; } memset(map, 0, sizeof(*map)); INIT_LIST_HEAD(&map->list); diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c index 85e14150a073..15d5b76ff504 100644 --- a/drivers/mtd/maps/esb2rom.c +++ b/drivers/mtd/maps/esb2rom.c @@ -277,11 +277,10 @@ static int __init esb2rom_init_one(struct pci_dev *pdev, unsigned long offset; int i; - if (!map) - map = kmalloc(sizeof(*map), GFP_KERNEL); if (!map) { - printk(KERN_ERR MOD_NAME ": kmalloc failed"); - goto out; + map = kmalloc(sizeof(*map), GFP_KERNEL); + if (!map) + goto out; } memset(map, 0, sizeof(*map)); INIT_LIST_HEAD(&map->list); diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c index fda72c5fd8f9..c8b2793691db 100644 --- a/drivers/mtd/maps/ichxrom.c +++ b/drivers/mtd/maps/ichxrom.c @@ -213,10 +213,8 @@ static int __init ichxrom_init_one(struct pci_dev *pdev, if (!map) { map = kmalloc(sizeof(*map), GFP_KERNEL); - } - if (!map) { - printk(KERN_ERR MOD_NAME ": kmalloc failed"); - goto out; + if (!map) + goto out; } memset(map, 0, sizeof(*map)); INIT_LIST_HEAD(&map->list); diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 0bec7c791d17..cedd8ef9a6bf 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c @@ -127,7 +127,6 @@ static int platram_probe(struct platform_device *pdev) info->map.virt = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(info->map.virt)) { err = PTR_ERR(info->map.virt); - dev_err(&pdev->dev, "failed to ioremap() region\n"); goto exit_free; } diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c index f9cfb084c029..6c0c91bfec05 100644 --- a/drivers/mtd/maps/sun_uflash.c +++ b/drivers/mtd/maps/sun_uflash.c @@ -62,10 +62,8 @@ int uflash_devinit(struct platform_device *op, struct device_node *dp) } up = kzalloc(sizeof(struct uflash_dev), GFP_KERNEL); - if (!up) { - printk(KERN_ERR PFX "Cannot allocate struct uflash_dev\n"); + if (!up) return -ENOMEM; - } /* copy defaults and tweak parameters */ memcpy(&up->map, &uflash_map_templ, sizeof(uflash_map_templ)); diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 9aaeadd53eb4..b5ccd3037788 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -96,6 +96,12 @@ static void mtd_release(struct device *dev) device_destroy(&mtd_class, index + 1); } +#define MTD_DEVICE_ATTR_RO(name) \ +static DEVICE_ATTR(name, 0444, mtd_##name##_show, NULL) + +#define MTD_DEVICE_ATTR_RW(name) \ +static DEVICE_ATTR(name, 0644, mtd_##name##_show, mtd_##name##_store) + static ssize_t mtd_type_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -131,46 +137,45 @@ static ssize_t mtd_type_show(struct device *dev, type = "unknown"; } - return snprintf(buf, PAGE_SIZE, "%s\n", type); + return sysfs_emit(buf, "%s\n", type); } -static DEVICE_ATTR(type, S_IRUGO, mtd_type_show, NULL); +MTD_DEVICE_ATTR_RO(type); static ssize_t mtd_flags_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mtd_info *mtd = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "0x%lx\n", (unsigned long)mtd->flags); + return sysfs_emit(buf, "0x%lx\n", (unsigned long)mtd->flags); } -static DEVICE_ATTR(flags, S_IRUGO, mtd_flags_show, NULL); +MTD_DEVICE_ATTR_RO(flags); static ssize_t mtd_size_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mtd_info *mtd = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%llu\n", - (unsigned long long)mtd->size); + return sysfs_emit(buf, "%llu\n", (unsigned long long)mtd->size); } -static DEVICE_ATTR(size, S_IRUGO, mtd_size_show, NULL); +MTD_DEVICE_ATTR_RO(size); static ssize_t mtd_erasesize_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mtd_info *mtd = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->erasesize); + return sysfs_emit(buf, "%lu\n", (unsigned long)mtd->erasesize); } -static DEVICE_ATTR(erasesize, S_IRUGO, mtd_erasesize_show, NULL); +MTD_DEVICE_ATTR_RO(erasesize); static ssize_t mtd_writesize_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mtd_info *mtd = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->writesize); + return sysfs_emit(buf, "%lu\n", (unsigned long)mtd->writesize); } -static DEVICE_ATTR(writesize, S_IRUGO, mtd_writesize_show, NULL); +MTD_DEVICE_ATTR_RO(writesize); static ssize_t mtd_subpagesize_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -178,55 +183,54 @@ static ssize_t mtd_subpagesize_show(struct device *dev, struct mtd_info *mtd = dev_get_drvdata(dev); unsigned int subpagesize = mtd->writesize >> mtd->subpage_sft; - return snprintf(buf, PAGE_SIZE, "%u\n", subpagesize); + return sysfs_emit(buf, "%u\n", subpagesize); } -static DEVICE_ATTR(subpagesize, S_IRUGO, mtd_subpagesize_show, NULL); +MTD_DEVICE_ATTR_RO(subpagesize); static ssize_t mtd_oobsize_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mtd_info *mtd = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->oobsize); + return sysfs_emit(buf, "%lu\n", (unsigned long)mtd->oobsize); } -static DEVICE_ATTR(oobsize, S_IRUGO, mtd_oobsize_show, NULL); +MTD_DEVICE_ATTR_RO(oobsize); static ssize_t mtd_oobavail_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mtd_info *mtd = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%u\n", mtd->oobavail); + return sysfs_emit(buf, "%u\n", mtd->oobavail); } -static DEVICE_ATTR(oobavail, S_IRUGO, mtd_oobavail_show, NULL); +MTD_DEVICE_ATTR_RO(oobavail); static ssize_t mtd_numeraseregions_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mtd_info *mtd = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%u\n", mtd->numeraseregions); + return sysfs_emit(buf, "%u\n", mtd->numeraseregions); } -static DEVICE_ATTR(numeraseregions, S_IRUGO, mtd_numeraseregions_show, - NULL); +MTD_DEVICE_ATTR_RO(numeraseregions); static ssize_t mtd_name_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mtd_info *mtd = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%s\n", mtd->name); + return sysfs_emit(buf, "%s\n", mtd->name); } -static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL); +MTD_DEVICE_ATTR_RO(name); static ssize_t mtd_ecc_strength_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mtd_info *mtd = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%u\n", mtd->ecc_strength); + return sysfs_emit(buf, "%u\n", mtd->ecc_strength); } -static DEVICE_ATTR(ecc_strength, S_IRUGO, mtd_ecc_strength_show, NULL); +MTD_DEVICE_ATTR_RO(ecc_strength); static ssize_t mtd_bitflip_threshold_show(struct device *dev, struct device_attribute *attr, @@ -234,7 +238,7 @@ static ssize_t mtd_bitflip_threshold_show(struct device *dev, { struct mtd_info *mtd = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%u\n", mtd->bitflip_threshold); + return sysfs_emit(buf, "%u\n", mtd->bitflip_threshold); } static ssize_t mtd_bitflip_threshold_store(struct device *dev, @@ -252,60 +256,57 @@ static ssize_t mtd_bitflip_threshold_store(struct device *dev, mtd->bitflip_threshold = bitflip_threshold; return count; } -static DEVICE_ATTR(bitflip_threshold, S_IRUGO | S_IWUSR, - mtd_bitflip_threshold_show, - mtd_bitflip_threshold_store); +MTD_DEVICE_ATTR_RW(bitflip_threshold); static ssize_t mtd_ecc_step_size_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mtd_info *mtd = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%u\n", mtd->ecc_step_size); + return sysfs_emit(buf, "%u\n", mtd->ecc_step_size); } -static DEVICE_ATTR(ecc_step_size, S_IRUGO, mtd_ecc_step_size_show, NULL); +MTD_DEVICE_ATTR_RO(ecc_step_size); -static ssize_t mtd_ecc_stats_corrected_show(struct device *dev, +static ssize_t mtd_corrected_bits_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mtd_info *mtd = dev_get_drvdata(dev); struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats; - return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->corrected); + return sysfs_emit(buf, "%u\n", ecc_stats->corrected); } -static DEVICE_ATTR(corrected_bits, S_IRUGO, - mtd_ecc_stats_corrected_show, NULL); +MTD_DEVICE_ATTR_RO(corrected_bits); /* ecc stats corrected */ -static ssize_t mtd_ecc_stats_errors_show(struct device *dev, +static ssize_t mtd_ecc_failures_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mtd_info *mtd = dev_get_drvdata(dev); struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats; - return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->failed); + return sysfs_emit(buf, "%u\n", ecc_stats->failed); } -static DEVICE_ATTR(ecc_failures, S_IRUGO, mtd_ecc_stats_errors_show, NULL); +MTD_DEVICE_ATTR_RO(ecc_failures); /* ecc stats errors */ -static ssize_t mtd_badblocks_show(struct device *dev, +static ssize_t mtd_bad_blocks_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mtd_info *mtd = dev_get_drvdata(dev); struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats; - return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->badblocks); + return sysfs_emit(buf, "%u\n", ecc_stats->badblocks); } -static DEVICE_ATTR(bad_blocks, S_IRUGO, mtd_badblocks_show, NULL); +MTD_DEVICE_ATTR_RO(bad_blocks); -static ssize_t mtd_bbtblocks_show(struct device *dev, +static ssize_t mtd_bbt_blocks_show(struct device *dev, struct device_attribute *attr, char *buf) { struct mtd_info *mtd = dev_get_drvdata(dev); struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats; - return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->bbtblocks); + return sysfs_emit(buf, "%u\n", ecc_stats->bbtblocks); } -static DEVICE_ATTR(bbt_blocks, S_IRUGO, mtd_bbtblocks_show, NULL); +MTD_DEVICE_ATTR_RO(bbt_blocks); static struct attribute *mtd_attrs[] = { &dev_attr_type.attr, @@ -361,6 +362,7 @@ static struct dentry *dfs_dir_mtd; static void mtd_debugfs_populate(struct mtd_info *mtd) { + struct mtd_info *master = mtd_get_master(mtd); struct device *dev = &mtd->dev; struct dentry *root; @@ -370,12 +372,12 @@ static void mtd_debugfs_populate(struct mtd_info *mtd) root = debugfs_create_dir(dev_name(dev), dfs_dir_mtd); mtd->dbg.dfs_dir = root; - if (mtd->dbg.partid) - debugfs_create_file("partid", 0400, root, mtd, + if (master->dbg.partid) + debugfs_create_file("partid", 0400, root, master, &mtd_partid_debug_fops); - if (mtd->dbg.partname) - debugfs_create_file("partname", 0400, root, mtd, + if (master->dbg.partname) + debugfs_create_file("partname", 0400, root, master, &mtd_partname_debug_fops); } @@ -777,6 +779,148 @@ static void mtd_set_dev_defaults(struct mtd_info *mtd) mutex_init(&mtd->master.chrdev_lock); } +static ssize_t mtd_otp_size(struct mtd_info *mtd, bool is_user) +{ + struct otp_info *info; + ssize_t size = 0; + unsigned int i; + size_t retlen; + int ret; + + info = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!info) + return -ENOMEM; + + if (is_user) + ret = mtd_get_user_prot_info(mtd, PAGE_SIZE, &retlen, info); + else + ret = mtd_get_fact_prot_info(mtd, PAGE_SIZE, &retlen, info); + if (ret) + goto err; + + for (i = 0; i < retlen / sizeof(*info); i++) + size += info[i].length; + + kfree(info); + return size; + +err: + kfree(info); + return ret; +} + +static struct nvmem_device *mtd_otp_nvmem_register(struct mtd_info *mtd, + const char *compatible, + int size, + nvmem_reg_read_t reg_read) +{ + struct nvmem_device *nvmem = NULL; + struct nvmem_config config = {}; + struct device_node *np; + + /* DT binding is optional */ + np = of_get_compatible_child(mtd->dev.of_node, compatible); + + /* OTP nvmem will be registered on the physical device */ + config.dev = mtd->dev.parent; + /* just reuse the compatible as name */ + config.name = compatible; + config.id = NVMEM_DEVID_NONE; + config.owner = THIS_MODULE; + config.type = NVMEM_TYPE_OTP; + config.root_only = true; + config.reg_read = reg_read; + config.size = size; + config.of_node = np; + config.priv = mtd; + + nvmem = nvmem_register(&config); + /* Just ignore if there is no NVMEM support in the kernel */ + if (IS_ERR(nvmem) && PTR_ERR(nvmem) == -EOPNOTSUPP) + nvmem = NULL; + + of_node_put(np); + + return nvmem; +} + +static int mtd_nvmem_user_otp_reg_read(void *priv, unsigned int offset, + void *val, size_t bytes) +{ + struct mtd_info *mtd = priv; + size_t retlen; + int ret; + + ret = mtd_read_user_prot_reg(mtd, offset, bytes, &retlen, val); + if (ret) + return ret; + + return retlen == bytes ? 0 : -EIO; +} + +static int mtd_nvmem_fact_otp_reg_read(void *priv, unsigned int offset, + void *val, size_t bytes) +{ + struct mtd_info *mtd = priv; + size_t retlen; + int ret; + + ret = mtd_read_fact_prot_reg(mtd, offset, bytes, &retlen, val); + if (ret) + return ret; + + return retlen == bytes ? 0 : -EIO; +} + +static int mtd_otp_nvmem_add(struct mtd_info *mtd) +{ + struct nvmem_device *nvmem; + ssize_t size; + int err; + + if (mtd->_get_user_prot_info && mtd->_read_user_prot_reg) { + size = mtd_otp_size(mtd, true); + if (size < 0) + return size; + + if (size > 0) { + nvmem = mtd_otp_nvmem_register(mtd, "user-otp", size, + mtd_nvmem_user_otp_reg_read); + if (IS_ERR(nvmem)) { + dev_err(&mtd->dev, "Failed to register OTP NVMEM device\n"); + return PTR_ERR(nvmem); + } + mtd->otp_user_nvmem = nvmem; + } + } + + if (mtd->_get_fact_prot_info && mtd->_read_fact_prot_reg) { + size = mtd_otp_size(mtd, false); + if (size < 0) { + err = size; + goto err; + } + + if (size > 0) { + nvmem = mtd_otp_nvmem_register(mtd, "factory-otp", size, + mtd_nvmem_fact_otp_reg_read); + if (IS_ERR(nvmem)) { + dev_err(&mtd->dev, "Failed to register OTP NVMEM device\n"); + err = PTR_ERR(nvmem); + goto err; + } + mtd->otp_factory_nvmem = nvmem; + } + } + + return 0; + +err: + if (mtd->otp_user_nvmem) + nvmem_unregister(mtd->otp_user_nvmem); + return err; +} + /** * mtd_device_parse_register - parse partitions and register an MTD device. * @@ -852,6 +996,8 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types, register_reboot_notifier(&mtd->reboot_notifier); } + ret = mtd_otp_nvmem_add(mtd); + out: if (ret && device_is_registered(&mtd->dev)) del_mtd_device(mtd); @@ -873,6 +1019,12 @@ int mtd_device_unregister(struct mtd_info *master) if (master->_reboot) unregister_reboot_notifier(&master->reboot_notifier); + if (master->otp_user_nvmem) + nvmem_unregister(master->otp_user_nvmem); + + if (master->otp_factory_nvmem) + nvmem_unregister(master->otp_factory_nvmem); + err = del_mtd_partitions(master); if (err) return err; diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c index 862c4a889234..227df24387df 100644 --- a/drivers/mtd/mtdoops.c +++ b/drivers/mtd/mtdoops.c @@ -401,10 +401,8 @@ static int __init mtdoops_init(void) cxt->mtd_index = mtd_index; cxt->oops_buf = vmalloc(record_size); - if (!cxt->oops_buf) { - printk(KERN_ERR "mtdoops: failed to allocate buffer workspace\n"); + if (!cxt->oops_buf) return -ENOMEM; - } memset(cxt->oops_buf, 0xff, record_size); cxt->oops_buf_busy = 0; diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 665fd9020b76..04af12b66110 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -212,15 +212,14 @@ out_register: return child; } -static ssize_t mtd_partition_offset_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t offset_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct mtd_info *mtd = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%lld\n", mtd->part.offset); + return sysfs_emit(buf, "%lld\n", mtd->part.offset); } - -static DEVICE_ATTR(offset, S_IRUGO, mtd_partition_offset_show, NULL); +static DEVICE_ATTR_RO(offset); /* mtd partition offset */ static const struct attribute *mtd_partition_attrs[] = { &dev_attr_offset.attr, diff --git a/drivers/mtd/nand/bbt.c b/drivers/mtd/nand/bbt.c index 044adf913854..64af6898131d 100644 --- a/drivers/mtd/nand/bbt.c +++ b/drivers/mtd/nand/bbt.c @@ -123,7 +123,7 @@ int nanddev_bbt_set_block_status(struct nand_device *nand, unsigned int entry, unsigned int rbits = bits_per_block + offs - BITS_PER_LONG; pos[1] &= ~GENMASK(rbits - 1, 0); - pos[1] |= val >> rbits; + pos[1] |= val >> (bits_per_block - rbits); } return 0; diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index 30f061939560..630728de4b7c 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -453,6 +453,14 @@ config MTD_NAND_ROCKCHIP NFC v800: RK3308, RV1108 NFC v900: PX30, RK3326 +config MTD_NAND_PL35X + tristate "ARM PL35X NAND controller" + depends on OF || COMPILE_TEST + depends on PL353_SMC + help + Enables support for PrimeCell SMC PL351 and PL353 NAND + controller found on Zynq7000. + comment "Misc" config MTD_SM_COMMON diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile index d011c6c53f8f..2f97958c3a33 100644 --- a/drivers/mtd/nand/raw/Makefile +++ b/drivers/mtd/nand/raw/Makefile @@ -57,6 +57,7 @@ obj-$(CONFIG_MTD_NAND_CADENCE) += cadence-nand-controller.o obj-$(CONFIG_MTD_NAND_ARASAN) += arasan-nand-controller.o obj-$(CONFIG_MTD_NAND_INTEL_LGM) += intel-nand-controller.o obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o +obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-nand-controller.o nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o nand-objs += nand_onfi.o diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c index 549aac00228e..9cbcc698c64d 100644 --- a/drivers/mtd/nand/raw/arasan-nand-controller.c +++ b/drivers/mtd/nand/raw/arasan-nand-controller.c @@ -15,6 +15,7 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/dma-mapping.h> +#include <linux/gpio/consumer.h> #include <linux/interrupt.h> #include <linux/iopoll.h> #include <linux/module.h> @@ -53,6 +54,7 @@ #define PROG_RST BIT(8) #define PROG_GET_FEATURE BIT(9) #define PROG_SET_FEATURE BIT(10) +#define PROG_CHG_RD_COL_ENH BIT(14) #define INTR_STS_EN_REG 0x14 #define INTR_SIG_EN_REG 0x18 @@ -70,6 +72,15 @@ #define FLASH_STS_REG 0x28 +#define TIMING_REG 0x2C +#define TCCS_TIME_500NS 0 +#define TCCS_TIME_300NS 3 +#define TCCS_TIME_200NS 2 +#define TCCS_TIME_100NS 1 +#define FAST_TCAD BIT(2) +#define DQS_BUFF_SEL_IN(x) FIELD_PREP(GENMASK(6, 3), (x)) +#define DQS_BUFF_SEL_OUT(x) FIELD_PREP(GENMASK(18, 15), (x)) + #define DATA_PORT_REG 0x30 #define ECC_CONF_REG 0x34 @@ -91,7 +102,7 @@ #define DATA_INTERFACE_REG 0x6C #define DIFACE_SDR_MODE(x) FIELD_PREP(GENMASK(2, 0), (x)) -#define DIFACE_DDR_MODE(x) FIELD_PREP(GENMASK(5, 3), (X)) +#define DIFACE_DDR_MODE(x) FIELD_PREP(GENMASK(5, 3), (x)) #define DIFACE_SDR 0 #define DIFACE_NVDDR BIT(9) @@ -107,6 +118,8 @@ #define ANFC_XLNX_SDR_DFLT_CORE_CLK 100000000 #define ANFC_XLNX_SDR_HS_CORE_CLK 80000000 +static struct gpio_desc *anfc_default_cs_array[2] = {NULL, NULL}; + /** * struct anfc_op - Defines how to execute an operation * @pkt_reg: Packet register @@ -137,11 +150,11 @@ struct anfc_op { * struct anand - Defines the NAND chip related information * @node: Used to store NAND chips into a list * @chip: NAND chip information structure - * @cs: Chip select line * @rb: Ready-busy line * @page_sz: Register value of the page_sz field to use * @clk: Expected clock frequency to use - * @timings: Data interface timing mode to use + * @data_iface: Data interface timing mode to use + * @timings: NV-DDR specific timings to use * @ecc_conf: Hardware ECC configuration value * @strength: Register value of the ECC strength * @raddr_cycles: Row address cycle information @@ -151,14 +164,17 @@ struct anfc_op { * @errloc: Array of errors located with soft BCH * @hw_ecc: Buffer to store syndromes computed by hardware * @bch: BCH structure + * @cs_idx: Array of chip-select for this device, values are indexes + * of the controller structure @gpio_cs array + * @ncs_idx: Size of the @cs_idx array */ struct anand { struct list_head node; struct nand_chip chip; - unsigned int cs; unsigned int rb; unsigned int page_sz; unsigned long clk; + u32 data_iface; u32 timings; u32 ecc_conf; u32 strength; @@ -169,6 +185,8 @@ struct anand { unsigned int *errloc; u8 *hw_ecc; struct bch_control *bch; + int *cs_idx; + int ncs_idx; }; /** @@ -179,8 +197,14 @@ struct anand { * @bus_clk: Pointer to the flash clock * @controller: Base controller structure * @chips: List of all NAND chips attached to the controller - * @assigned_cs: Bitmask describing already assigned CS lines * @cur_clk: Current clock rate + * @cs_array: CS array. Native CS are left empty, the other cells are + * populated with their corresponding GPIO descriptor. + * @ncs: Size of @cs_array + * @cur_cs: Index in @cs_array of the currently in use CS + * @native_cs: Currently selected native CS + * @spare_cs: Native CS that is not wired (may be selected when a GPIO + * CS is in use) */ struct arasan_nfc { struct device *dev; @@ -189,8 +213,12 @@ struct arasan_nfc { struct clk *bus_clk; struct nand_controller controller; struct list_head chips; - unsigned long assigned_cs; unsigned int cur_clk; + struct gpio_desc **cs_array; + unsigned int ncs; + int cur_cs; + unsigned int native_cs; + unsigned int spare_cs; }; static struct anand *to_anand(struct nand_chip *nand) @@ -273,6 +301,72 @@ static int anfc_pkt_len_config(unsigned int len, unsigned int *steps, return 0; } +static bool anfc_is_gpio_cs(struct arasan_nfc *nfc, int nfc_cs) +{ + return nfc_cs >= 0 && nfc->cs_array[nfc_cs]; +} + +static int anfc_relative_to_absolute_cs(struct anand *anand, int num) +{ + return anand->cs_idx[num]; +} + +static void anfc_assert_cs(struct arasan_nfc *nfc, unsigned int nfc_cs_idx) +{ + /* CS did not change: do nothing */ + if (nfc->cur_cs == nfc_cs_idx) + return; + + /* Deassert the previous CS if it was a GPIO */ + if (anfc_is_gpio_cs(nfc, nfc->cur_cs)) + gpiod_set_value_cansleep(nfc->cs_array[nfc->cur_cs], 1); + + /* Assert the new one */ + if (anfc_is_gpio_cs(nfc, nfc_cs_idx)) { + nfc->native_cs = nfc->spare_cs; + gpiod_set_value_cansleep(nfc->cs_array[nfc_cs_idx], 0); + } else { + nfc->native_cs = nfc_cs_idx; + } + + nfc->cur_cs = nfc_cs_idx; +} + +static int anfc_select_target(struct nand_chip *chip, int target) +{ + struct anand *anand = to_anand(chip); + struct arasan_nfc *nfc = to_anfc(chip->controller); + unsigned int nfc_cs_idx = anfc_relative_to_absolute_cs(anand, target); + int ret; + + anfc_assert_cs(nfc, nfc_cs_idx); + + /* Update the controller timings and the potential ECC configuration */ + writel_relaxed(anand->data_iface, nfc->base + DATA_INTERFACE_REG); + writel_relaxed(anand->timings, nfc->base + TIMING_REG); + + /* Update clock frequency */ + if (nfc->cur_clk != anand->clk) { + clk_disable_unprepare(nfc->controller_clk); + ret = clk_set_rate(nfc->controller_clk, anand->clk); + if (ret) { + dev_err(nfc->dev, "Failed to change clock rate\n"); + return ret; + } + + ret = clk_prepare_enable(nfc->controller_clk); + if (ret) { + dev_err(nfc->dev, + "Failed to re-enable the controller clock\n"); + return ret; + } + + nfc->cur_clk = anand->clk; + } + + return 0; +} + /* * When using the embedded hardware ECC engine, the controller is in charge of * feeding the engine with, first, the ECC residue present in the data array. @@ -315,7 +409,7 @@ static int anfc_read_page_hw_ecc(struct nand_chip *chip, u8 *buf, .addr2_reg = ((page >> 16) & 0xFF) | ADDR2_STRENGTH(anand->strength) | - ADDR2_CS(anand->cs), + ADDR2_CS(nfc->native_cs), .cmd_reg = CMD_1(NAND_CMD_READ0) | CMD_2(NAND_CMD_READSTART) | @@ -401,6 +495,18 @@ static int anfc_read_page_hw_ecc(struct nand_chip *chip, u8 *buf, return 0; } +static int anfc_sel_read_page_hw_ecc(struct nand_chip *chip, u8 *buf, + int oob_required, int page) +{ + int ret; + + ret = anfc_select_target(chip, chip->cur_cs); + if (ret) + return ret; + + return anfc_read_page_hw_ecc(chip, buf, oob_required, page); +}; + static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { @@ -420,7 +526,7 @@ static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf, .addr2_reg = ((page >> 16) & 0xFF) | ADDR2_STRENGTH(anand->strength) | - ADDR2_CS(anand->cs), + ADDR2_CS(nfc->native_cs), .cmd_reg = CMD_1(NAND_CMD_SEQIN) | CMD_2(NAND_CMD_PAGEPROG) | @@ -461,11 +567,24 @@ static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf, return ret; } +static int anfc_sel_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf, + int oob_required, int page) +{ + int ret; + + ret = anfc_select_target(chip, chip->cur_cs); + if (ret) + return ret; + + return anfc_write_page_hw_ecc(chip, buf, oob_required, page); +}; + /* NAND framework ->exec_op() hooks and related helpers */ static int anfc_parse_instructions(struct nand_chip *chip, const struct nand_subop *subop, struct anfc_op *nfc_op) { + struct arasan_nfc *nfc = to_anfc(chip->controller); struct anand *anand = to_anand(chip); const struct nand_op_instr *instr = NULL; bool first_cmd = true; @@ -473,7 +592,7 @@ static int anfc_parse_instructions(struct nand_chip *chip, int ret, i; memset(nfc_op, 0, sizeof(*nfc_op)); - nfc_op->addr2_reg = ADDR2_CS(anand->cs); + nfc_op->addr2_reg = ADDR2_CS(nfc->native_cs); nfc_op->cmd_reg = CMD_PAGE_SIZE(anand->page_sz); for (op_id = 0; op_id < subop->ninstrs; op_id++) { @@ -622,7 +741,23 @@ static int anfc_param_read_type_exec(struct nand_chip *chip, static int anfc_data_read_type_exec(struct nand_chip *chip, const struct nand_subop *subop) { - return anfc_misc_data_type_exec(chip, subop, PROG_PGRD); + u32 prog_reg = PROG_PGRD; + + /* + * Experience shows that while in SDR mode sending a CHANGE READ COLUMN + * command through the READ PAGE "type" always works fine, when in + * NV-DDR mode the same command simply fails. However, it was also + * spotted that any CHANGE READ COLUMN command sent through the CHANGE + * READ COLUMN ENHANCED "type" would correctly work in both cases (SDR + * and NV-DDR). So, for simplicity, let's program the controller with + * the CHANGE READ COLUMN ENHANCED "type" whenever we are requested to + * perform a CHANGE READ COLUMN operation. + */ + if (subop->instrs[0].ctx.cmd.opcode == NAND_CMD_RNDOUT && + subop->instrs[2].ctx.cmd.opcode == NAND_CMD_RNDOUTSTART) + prog_reg = PROG_CHG_RD_COL_ENH; + + return anfc_misc_data_type_exec(chip, subop, prog_reg); } static int anfc_param_write_type_exec(struct nand_chip *chip, @@ -753,37 +888,6 @@ static const struct nand_op_parser anfc_op_parser = NAND_OP_PARSER( NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)), ); -static int anfc_select_target(struct nand_chip *chip, int target) -{ - struct anand *anand = to_anand(chip); - struct arasan_nfc *nfc = to_anfc(chip->controller); - int ret; - - /* Update the controller timings and the potential ECC configuration */ - writel_relaxed(anand->timings, nfc->base + DATA_INTERFACE_REG); - - /* Update clock frequency */ - if (nfc->cur_clk != anand->clk) { - clk_disable_unprepare(nfc->controller_clk); - ret = clk_set_rate(nfc->controller_clk, anand->clk); - if (ret) { - dev_err(nfc->dev, "Failed to change clock rate\n"); - return ret; - } - - ret = clk_prepare_enable(nfc->controller_clk); - if (ret) { - dev_err(nfc->dev, - "Failed to re-enable the controller clock\n"); - return ret; - } - - nfc->cur_clk = anand->clk; - } - - return 0; -} - static int anfc_check_op(struct nand_chip *chip, const struct nand_operation *op) { @@ -861,21 +965,79 @@ static int anfc_setup_interface(struct nand_chip *chip, int target, struct anand *anand = to_anand(chip); struct arasan_nfc *nfc = to_anfc(chip->controller); struct device_node *np = nfc->dev->of_node; + const struct nand_sdr_timings *sdr; + const struct nand_nvddr_timings *nvddr; + unsigned int tccs_min, dqs_mode, fast_tcad; + + if (nand_interface_is_nvddr(conf)) { + nvddr = nand_get_nvddr_timings(conf); + if (IS_ERR(nvddr)) + return PTR_ERR(nvddr); + } else { + sdr = nand_get_sdr_timings(conf); + if (IS_ERR(sdr)) + return PTR_ERR(sdr); + } if (target < 0) return 0; - anand->timings = DIFACE_SDR | DIFACE_SDR_MODE(conf->timings.mode); + if (nand_interface_is_sdr(conf)) { + anand->data_iface = DIFACE_SDR | + DIFACE_SDR_MODE(conf->timings.mode); + anand->timings = 0; + } else { + anand->data_iface = DIFACE_NVDDR | + DIFACE_DDR_MODE(conf->timings.mode); + + if (conf->timings.nvddr.tCCS_min <= 100000) + tccs_min = TCCS_TIME_100NS; + else if (conf->timings.nvddr.tCCS_min <= 200000) + tccs_min = TCCS_TIME_200NS; + else if (conf->timings.nvddr.tCCS_min <= 300000) + tccs_min = TCCS_TIME_300NS; + else + tccs_min = TCCS_TIME_500NS; + + fast_tcad = 0; + if (conf->timings.nvddr.tCAD_min < 45000) + fast_tcad = FAST_TCAD; + + switch (conf->timings.mode) { + case 5: + case 4: + dqs_mode = 2; + break; + case 3: + dqs_mode = 3; + break; + case 2: + dqs_mode = 4; + break; + case 1: + dqs_mode = 5; + break; + case 0: + default: + dqs_mode = 6; + break; + } + + anand->timings = tccs_min | fast_tcad | + DQS_BUFF_SEL_IN(dqs_mode) | + DQS_BUFF_SEL_OUT(dqs_mode); + } + anand->clk = ANFC_XLNX_SDR_DFLT_CORE_CLK; /* * Due to a hardware bug in the ZynqMP SoC, SDR timing modes 0-1 work * with f > 90MHz (default clock is 100MHz) but signals are unstable * with higher modes. Hence we decrease a little bit the clock rate to - * 80MHz when using modes 2-5 with this SoC. + * 80MHz when using SDR modes 2-5 with this SoC. */ if (of_device_is_compatible(np, "xlnx,zynqmp-nand-controller") && - conf->timings.mode >= 2) + nand_interface_is_sdr(conf) && conf->timings.mode >= 2) anand->clk = ANFC_XLNX_SDR_HS_CORE_CLK; return 0; @@ -1007,8 +1169,8 @@ static int anfc_init_hw_ecc_controller(struct arasan_nfc *nfc, if (!anand->bch) return -EINVAL; - ecc->read_page = anfc_read_page_hw_ecc; - ecc->write_page = anfc_write_page_hw_ecc; + ecc->read_page = anfc_sel_read_page_hw_ecc; + ecc->write_page = anfc_sel_write_page_hw_ecc; return 0; } @@ -1094,37 +1256,43 @@ static int anfc_chip_init(struct arasan_nfc *nfc, struct device_node *np) struct anand *anand; struct nand_chip *chip; struct mtd_info *mtd; - int cs, rb, ret; + int rb, ret, i; anand = devm_kzalloc(nfc->dev, sizeof(*anand), GFP_KERNEL); if (!anand) return -ENOMEM; - /* We do not support multiple CS per chip yet */ - if (of_property_count_elems_of_size(np, "reg", sizeof(u32)) != 1) { + /* Chip-select init */ + anand->ncs_idx = of_property_count_elems_of_size(np, "reg", sizeof(u32)); + if (anand->ncs_idx <= 0 || anand->ncs_idx > nfc->ncs) { dev_err(nfc->dev, "Invalid reg property\n"); return -EINVAL; } - ret = of_property_read_u32(np, "reg", &cs); - if (ret) - return ret; + anand->cs_idx = devm_kcalloc(nfc->dev, anand->ncs_idx, + sizeof(*anand->cs_idx), GFP_KERNEL); + if (!anand->cs_idx) + return -ENOMEM; + for (i = 0; i < anand->ncs_idx; i++) { + ret = of_property_read_u32_index(np, "reg", i, + &anand->cs_idx[i]); + if (ret) { + dev_err(nfc->dev, "invalid CS property: %d\n", ret); + return ret; + } + } + + /* Ready-busy init */ ret = of_property_read_u32(np, "nand-rb", &rb); if (ret) return ret; - if (cs >= ANFC_MAX_CS || rb >= ANFC_MAX_CS) { - dev_err(nfc->dev, "Wrong CS %d or RB %d\n", cs, rb); - return -EINVAL; - } - - if (test_and_set_bit(cs, &nfc->assigned_cs)) { - dev_err(nfc->dev, "Already assigned CS %d\n", cs); + if (rb >= ANFC_MAX_CS) { + dev_err(nfc->dev, "Wrong RB %d\n", rb); return -EINVAL; } - anand->cs = cs; anand->rb = rb; chip = &anand->chip; @@ -1140,7 +1308,7 @@ static int anfc_chip_init(struct arasan_nfc *nfc, struct device_node *np) return -EINVAL; } - ret = nand_scan(chip, 1); + ret = nand_scan(chip, anand->ncs_idx); if (ret) { dev_err(nfc->dev, "Scan operation failed\n"); return ret; @@ -1178,7 +1346,7 @@ static int anfc_chips_init(struct arasan_nfc *nfc) int nchips = of_get_child_count(np); int ret; - if (!nchips || nchips > ANFC_MAX_CS) { + if (!nchips) { dev_err(nfc->dev, "Incorrect number of NAND chips (%d)\n", nchips); return -EINVAL; @@ -1203,6 +1371,47 @@ static void anfc_reset(struct arasan_nfc *nfc) /* Enable interrupt status */ writel_relaxed(EVENT_MASK, nfc->base + INTR_STS_EN_REG); + + nfc->cur_cs = -1; +} + +static int anfc_parse_cs(struct arasan_nfc *nfc) +{ + int ret; + + /* Check the gpio-cs property */ + ret = rawnand_dt_parse_gpio_cs(nfc->dev, &nfc->cs_array, &nfc->ncs); + if (ret) + return ret; + + /* + * The controller native CS cannot be both disabled at the same time. + * Hence, only one native CS can be used if GPIO CS are needed, so that + * the other is selected when a non-native CS must be asserted (not + * wired physically or configured as GPIO instead of NAND CS). In this + * case, the "not" chosen CS is assigned to nfc->spare_cs and selected + * whenever a GPIO CS must be asserted. + */ + if (nfc->cs_array && nfc->ncs > 2) { + if (!nfc->cs_array[0] && !nfc->cs_array[1]) { + dev_err(nfc->dev, + "Assign a single native CS when using GPIOs\n"); + return -EINVAL; + } + + if (nfc->cs_array[0]) + nfc->spare_cs = 0; + else + nfc->spare_cs = 1; + } + + if (!nfc->cs_array) { + nfc->cs_array = anfc_default_cs_array; + nfc->ncs = ANFC_MAX_CS; + return 0; + } + + return 0; } static int anfc_probe(struct platform_device *pdev) @@ -1241,6 +1450,14 @@ static int anfc_probe(struct platform_device *pdev) if (ret) goto disable_controller_clk; + ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); + if (ret) + goto disable_bus_clk; + + ret = anfc_parse_cs(nfc); + if (ret) + goto disable_bus_clk; + ret = anfc_chips_init(nfc); if (ret) goto disable_bus_clk; diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index 8aab1017b460..f3276ee9e4fe 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -1246,7 +1246,7 @@ static int atmel_smc_nand_prepare_smcconf(struct atmel_nand *nand, nc = to_nand_controller(nand->base.controller); /* DDR interface not supported. */ - if (conf->type != NAND_SDR_IFACE) + if (!nand_interface_is_sdr(conf)) return -ENOTSUPP; /* @@ -1524,8 +1524,13 @@ static int atmel_nand_setup_interface(struct nand_chip *chip, int csline, const struct nand_interface_config *conf) { struct atmel_nand *nand = to_atmel_nand(chip); + const struct nand_sdr_timings *sdr; struct atmel_nand_controller *nc; + sdr = nand_get_sdr_timings(conf); + if (IS_ERR(sdr)) + return PTR_ERR(sdr); + nc = to_nand_controller(nand->base.controller); if (csline >= nand->numcs || @@ -1629,10 +1634,8 @@ static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc, } nand = devm_kzalloc(nc->dev, struct_size(nand, cs, numcs), GFP_KERNEL); - if (!nand) { - dev_err(nc->dev, "Failed to allocate NAND object\n"); + if (!nand) return ERR_PTR(-ENOMEM); - } nand->numcs = numcs; diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c index b46786cd53e0..7eec60ea9056 100644 --- a/drivers/mtd/nand/raw/cadence-nand-controller.c +++ b/drivers/mtd/nand/raw/cadence-nand-controller.c @@ -2348,9 +2348,9 @@ cadence_nand_setup_interface(struct nand_chip *chip, int chipnr, * for tRP and tRH timings. If it is NOT possible to sample data * with optimal tRP/tRH settings, the parameters will be extended. * If clk_period is 50ns (the lowest value) this condition is met - * for asynchronous timing modes 1, 2, 3, 4 and 5. - * If clk_period is 20ns the condition is met only - * for asynchronous timing mode 5. + * for SDR timing modes 1, 2, 3, 4 and 5. + * If clk_period is 20ns the condition is met only for SDR timing + * mode 5. */ if (sdr->tRC_min <= clk_period && sdr->tRP_min <= (clk_period / 2) && diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h index fdc5ed7de083..5e1c3ddae5f8 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h @@ -79,7 +79,7 @@ enum gpmi_type { struct gpmi_devdata { enum gpmi_type type; int bch_max_ecc_strength; - int max_chain_delay; /* See the async EDO mode */ + int max_chain_delay; /* See the SDR EDO mode */ const char * const *clks; const int clks_count; }; diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c index 8b2122ce6ec3..78c4e05434e2 100644 --- a/drivers/mtd/nand/raw/hisi504_nand.c +++ b/drivers/mtd/nand/raw/hisi504_nand.c @@ -761,10 +761,8 @@ static int hisi_nfc_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 1); host->mmio = devm_ioremap_resource(dev, res); - if (IS_ERR(host->mmio)) { - dev_err(dev, "devm_ioremap_resource[1] fail\n"); + if (IS_ERR(host->mmio)) return PTR_ERR(host->mmio); - } mtd->name = "hisi_nand"; mtd->dev.parent = &pdev->dev; diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index 012876e14317..7016e0f38398 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h @@ -90,9 +90,14 @@ void onfi_fill_interface_config(struct nand_chip *chip, unsigned int timing_mode); unsigned int onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings); +unsigned int +onfi_find_closest_nvddr_mode(const struct nand_nvddr_timings *spec_timings); int nand_choose_best_sdr_timings(struct nand_chip *chip, struct nand_interface_config *iface, struct nand_sdr_timings *spec_timings); +int nand_choose_best_nvddr_timings(struct nand_chip *chip, + struct nand_interface_config *iface, + struct nand_nvddr_timings *spec_timings); const struct nand_interface_config *nand_get_reset_interface_config(void); int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param); int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param); diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index 79da6b02e209..2455a581fd70 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -451,7 +451,7 @@ struct marvell_nfc_timings { }; /** - * Derives a duration in numbers of clock cycles. + * TO_CYCLES() - Derives a duration in numbers of clock cycles. * * @ps: Duration in pico-seconds * @period_ns: Clock period in nano-seconds @@ -3030,8 +3030,10 @@ static int __maybe_unused marvell_nfc_resume(struct device *dev) return ret; ret = clk_prepare_enable(nfc->reg_clk); - if (ret < 0) + if (ret < 0) { + clk_disable_unprepare(nfc->core_clk); return ret; + } /* * Reset nfc->selected_chip so the next command will cause the timing diff --git a/drivers/mtd/nand/raw/mtk_ecc.c b/drivers/mtd/nand/raw/mtk_ecc.c index 75f1fa3d4d35..c437d97debb8 100644 --- a/drivers/mtd/nand/raw/mtk_ecc.c +++ b/drivers/mtd/nand/raw/mtk_ecc.c @@ -515,10 +515,8 @@ static int mtk_ecc_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ecc->regs = devm_ioremap_resource(dev, res); - if (IS_ERR(ecc->regs)) { - dev_err(dev, "failed to map regs: %ld\n", PTR_ERR(ecc->regs)); + if (IS_ERR(ecc->regs)) return PTR_ERR(ecc->regs); - } ecc->clk = devm_clk_get(dev, NULL); if (IS_ERR(ecc->clk)) { diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index fb072c444495..57a583149cc0 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -42,6 +42,7 @@ #include <linux/io.h> #include <linux/mtd/partitions.h> #include <linux/of.h> +#include <linux/of_gpio.h> #include <linux/gpio/consumer.h> #include "internals.h" @@ -647,7 +648,7 @@ static int nand_block_checkbad(struct nand_chip *chip, loff_t ofs, int allowbbt) */ int nand_soft_waitrdy(struct nand_chip *chip, unsigned long timeout_ms) { - const struct nand_sdr_timings *timings; + const struct nand_interface_config *conf; u8 status = 0; int ret; @@ -655,8 +656,8 @@ int nand_soft_waitrdy(struct nand_chip *chip, unsigned long timeout_ms) return -ENOTSUPP; /* Wait tWB before polling the STATUS reg. */ - timings = nand_get_sdr_timings(nand_get_interface_config(chip)); - ndelay(PSEC_TO_NSEC(timings->tWB_max)); + conf = nand_get_interface_config(chip); + ndelay(NAND_COMMON_TIMING_NS(conf, tWB_max)); ret = nand_status_op(chip, NULL); if (ret) @@ -832,7 +833,7 @@ static int nand_reset_interface(struct nand_chip *chip, int chipnr) static int nand_setup_interface(struct nand_chip *chip, int chipnr) { const struct nand_controller_ops *ops = chip->controller->ops; - u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { }; + u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { }, request; int ret; if (!nand_controller_can_setup_interface(chip)) @@ -848,7 +849,12 @@ static int nand_setup_interface(struct nand_chip *chip, int chipnr) if (!chip->best_interface_config) return 0; - tmode_param[0] = chip->best_interface_config->timings.mode; + request = chip->best_interface_config->timings.mode; + if (nand_interface_is_sdr(chip->best_interface_config)) + request |= ONFI_DATA_INTERFACE_SDR; + else + request |= ONFI_DATA_INTERFACE_NVDDR; + tmode_param[0] = request; /* Change the mode on the chip side (if supported by the NAND chip) */ if (nand_supports_set_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE)) { @@ -877,9 +883,13 @@ static int nand_setup_interface(struct nand_chip *chip, int chipnr) if (ret) goto err_reset_chip; - if (tmode_param[0] != chip->best_interface_config->timings.mode) { - pr_warn("timing mode %d not acknowledged by the NAND chip\n", + if (request != tmode_param[0]) { + pr_warn("%s timing mode %d not acknowledged by the NAND chip\n", + nand_interface_is_nvddr(chip->best_interface_config) ? "NV-DDR" : "SDR", chip->best_interface_config->timings.mode); + pr_debug("NAND chip would work in %s timing mode %d\n", + tmode_param[0] & ONFI_DATA_INTERFACE_NVDDR ? "NV-DDR" : "SDR", + (unsigned int)ONFI_TIMING_MODE_PARAM(tmode_param[0])); goto err_reset_chip; } @@ -935,7 +945,7 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip, /* Fallback to slower modes */ best_mode = iface->timings.mode; } else if (chip->parameters.onfi) { - best_mode = fls(chip->parameters.onfi->async_timing_mode) - 1; + best_mode = fls(chip->parameters.onfi->sdr_timing_modes) - 1; } for (mode = best_mode; mode >= 0; mode--) { @@ -943,13 +953,87 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip, ret = ops->setup_interface(chip, NAND_DATA_IFACE_CHECK_ONLY, iface); - if (!ret) + if (!ret) { + chip->best_interface_config = iface; break; + } } - chip->best_interface_config = iface; + return ret; +} - return 0; +/** + * nand_choose_best_nvddr_timings - Pick up the best NVDDR timings that both the + * NAND controller and the NAND chip support + * @chip: the NAND chip + * @iface: the interface configuration (can eventually be updated) + * @spec_timings: specific timings, when not fitting the ONFI specification + * + * If specific timings are provided, use them. Otherwise, retrieve supported + * timing modes from ONFI information. + */ +int nand_choose_best_nvddr_timings(struct nand_chip *chip, + struct nand_interface_config *iface, + struct nand_nvddr_timings *spec_timings) +{ + const struct nand_controller_ops *ops = chip->controller->ops; + int best_mode = 0, mode, ret; + + iface->type = NAND_NVDDR_IFACE; + + if (spec_timings) { + iface->timings.nvddr = *spec_timings; + iface->timings.mode = onfi_find_closest_nvddr_mode(spec_timings); + + /* Verify the controller supports the requested interface */ + ret = ops->setup_interface(chip, NAND_DATA_IFACE_CHECK_ONLY, + iface); + if (!ret) { + chip->best_interface_config = iface; + return ret; + } + + /* Fallback to slower modes */ + best_mode = iface->timings.mode; + } else if (chip->parameters.onfi) { + best_mode = fls(chip->parameters.onfi->nvddr_timing_modes) - 1; + } + + for (mode = best_mode; mode >= 0; mode--) { + onfi_fill_interface_config(chip, iface, NAND_NVDDR_IFACE, mode); + + ret = ops->setup_interface(chip, NAND_DATA_IFACE_CHECK_ONLY, + iface); + if (!ret) { + chip->best_interface_config = iface; + break; + } + } + + return ret; +} + +/** + * nand_choose_best_timings - Pick up the best NVDDR or SDR timings that both + * NAND controller and the NAND chip support + * @chip: the NAND chip + * @iface: the interface configuration (can eventually be updated) + * + * If specific timings are provided, use them. Otherwise, retrieve supported + * timing modes from ONFI information. + */ +static int nand_choose_best_timings(struct nand_chip *chip, + struct nand_interface_config *iface) +{ + int ret; + + /* Try the fastest timings: NV-DDR */ + ret = nand_choose_best_nvddr_timings(chip, iface, NULL); + if (!ret) + return 0; + + /* Fallback to SDR timings otherwise */ + return nand_choose_best_sdr_timings(chip, iface, NULL); } /** @@ -980,7 +1064,7 @@ static int nand_choose_interface_config(struct nand_chip *chip) if (chip->ops.choose_interface_config) ret = chip->ops.choose_interface_config(chip, iface); else - ret = nand_choose_best_sdr_timings(chip, iface, NULL); + ret = nand_choose_best_timings(chip, iface); if (ret) kfree(iface); @@ -1046,15 +1130,15 @@ static int nand_sp_exec_read_page_op(struct nand_chip *chip, unsigned int page, unsigned int offset_in_page, void *buf, unsigned int len) { - const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(nand_get_interface_config(chip)); + const struct nand_interface_config *conf = + nand_get_interface_config(chip); struct mtd_info *mtd = nand_to_mtd(chip); u8 addrs[4]; struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_READ0, 0), - NAND_OP_ADDR(3, addrs, PSEC_TO_NSEC(sdr->tWB_max)), - NAND_OP_WAIT_RDY(PSEC_TO_MSEC(sdr->tR_max), - PSEC_TO_NSEC(sdr->tRR_min)), + NAND_OP_ADDR(3, addrs, NAND_COMMON_TIMING_NS(conf, tWB_max)), + NAND_OP_WAIT_RDY(NAND_COMMON_TIMING_MS(conf, tR_max), + NAND_COMMON_TIMING_NS(conf, tRR_min)), NAND_OP_DATA_IN(len, buf, 0), }; struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs); @@ -1089,15 +1173,15 @@ static int nand_lp_exec_read_page_op(struct nand_chip *chip, unsigned int page, unsigned int offset_in_page, void *buf, unsigned int len) { - const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(nand_get_interface_config(chip)); + const struct nand_interface_config *conf = + nand_get_interface_config(chip); u8 addrs[5]; struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_READ0, 0), NAND_OP_ADDR(4, addrs, 0), - NAND_OP_CMD(NAND_CMD_READSTART, PSEC_TO_NSEC(sdr->tWB_max)), - NAND_OP_WAIT_RDY(PSEC_TO_MSEC(sdr->tR_max), - PSEC_TO_NSEC(sdr->tRR_min)), + NAND_OP_CMD(NAND_CMD_READSTART, NAND_COMMON_TIMING_NS(conf, tWB_max)), + NAND_OP_WAIT_RDY(NAND_COMMON_TIMING_MS(conf, tR_max), + NAND_COMMON_TIMING_NS(conf, tRR_min)), NAND_OP_DATA_IN(len, buf, 0), }; struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs); @@ -1186,13 +1270,14 @@ int nand_read_param_page_op(struct nand_chip *chip, u8 page, void *buf, return -EINVAL; if (nand_has_exec_op(chip)) { - const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(nand_get_interface_config(chip)); + const struct nand_interface_config *conf = + nand_get_interface_config(chip); struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_PARAM, 0), - NAND_OP_ADDR(1, &page, PSEC_TO_NSEC(sdr->tWB_max)), - NAND_OP_WAIT_RDY(PSEC_TO_MSEC(sdr->tR_max), - PSEC_TO_NSEC(sdr->tRR_min)), + NAND_OP_ADDR(1, &page, + NAND_COMMON_TIMING_NS(conf, tWB_max)), + NAND_OP_WAIT_RDY(NAND_COMMON_TIMING_MS(conf, tR_max), + NAND_COMMON_TIMING_NS(conf, tRR_min)), NAND_OP_8BIT_DATA_IN(len, buf, 0), }; struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs); @@ -1241,14 +1326,14 @@ int nand_change_read_column_op(struct nand_chip *chip, return -ENOTSUPP; if (nand_has_exec_op(chip)) { - const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(nand_get_interface_config(chip)); + const struct nand_interface_config *conf = + nand_get_interface_config(chip); u8 addrs[2] = {}; struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_RNDOUT, 0), NAND_OP_ADDR(2, addrs, 0), NAND_OP_CMD(NAND_CMD_RNDOUTSTART, - PSEC_TO_NSEC(sdr->tCCS_min)), + NAND_COMMON_TIMING_NS(conf, tCCS_min)), NAND_OP_DATA_IN(len, buf, 0), }; struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs); @@ -1316,8 +1401,8 @@ static int nand_exec_prog_page_op(struct nand_chip *chip, unsigned int page, unsigned int offset_in_page, const void *buf, unsigned int len, bool prog) { - const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(nand_get_interface_config(chip)); + const struct nand_interface_config *conf = + nand_get_interface_config(chip); struct mtd_info *mtd = nand_to_mtd(chip); u8 addrs[5] = {}; struct nand_op_instr instrs[] = { @@ -1328,10 +1413,11 @@ static int nand_exec_prog_page_op(struct nand_chip *chip, unsigned int page, */ NAND_OP_CMD(NAND_CMD_READ0, 0), NAND_OP_CMD(NAND_CMD_SEQIN, 0), - NAND_OP_ADDR(0, addrs, PSEC_TO_NSEC(sdr->tADL_min)), + NAND_OP_ADDR(0, addrs, NAND_COMMON_TIMING_NS(conf, tADL_min)), NAND_OP_DATA_OUT(len, buf, 0), - NAND_OP_CMD(NAND_CMD_PAGEPROG, PSEC_TO_NSEC(sdr->tWB_max)), - NAND_OP_WAIT_RDY(PSEC_TO_MSEC(sdr->tPROG_max), 0), + NAND_OP_CMD(NAND_CMD_PAGEPROG, + NAND_COMMON_TIMING_NS(conf, tWB_max)), + NAND_OP_WAIT_RDY(NAND_COMMON_TIMING_MS(conf, tPROG_max), 0), }; struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs); int naddrs = nand_fill_column_cycles(chip, addrs, offset_in_page); @@ -1430,12 +1516,13 @@ int nand_prog_page_end_op(struct nand_chip *chip) u8 status; if (nand_has_exec_op(chip)) { - const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(nand_get_interface_config(chip)); + const struct nand_interface_config *conf = + nand_get_interface_config(chip); struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_PAGEPROG, - PSEC_TO_NSEC(sdr->tWB_max)), - NAND_OP_WAIT_RDY(PSEC_TO_MSEC(sdr->tPROG_max), 0), + NAND_COMMON_TIMING_NS(conf, tWB_max)), + NAND_OP_WAIT_RDY(NAND_COMMON_TIMING_MS(conf, tPROG_max), + 0), }; struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs); @@ -1548,12 +1635,12 @@ int nand_change_write_column_op(struct nand_chip *chip, return -ENOTSUPP; if (nand_has_exec_op(chip)) { - const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(nand_get_interface_config(chip)); + const struct nand_interface_config *conf = + nand_get_interface_config(chip); u8 addrs[2]; struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_RNDIN, 0), - NAND_OP_ADDR(2, addrs, PSEC_TO_NSEC(sdr->tCCS_min)), + NAND_OP_ADDR(2, addrs, NAND_COMMON_TIMING_NS(conf, tCCS_min)), NAND_OP_DATA_OUT(len, buf, 0), }; struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs); @@ -1597,26 +1684,46 @@ int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf, unsigned int len) { unsigned int i; - u8 *id = buf; + u8 *id = buf, *ddrbuf = NULL; if (len && !buf) return -EINVAL; if (nand_has_exec_op(chip)) { - const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(nand_get_interface_config(chip)); + const struct nand_interface_config *conf = + nand_get_interface_config(chip); struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_READID, 0), - NAND_OP_ADDR(1, &addr, PSEC_TO_NSEC(sdr->tADL_min)), + NAND_OP_ADDR(1, &addr, + NAND_COMMON_TIMING_NS(conf, tADL_min)), NAND_OP_8BIT_DATA_IN(len, buf, 0), }; struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs); + int ret; + + /* READ_ID data bytes are received twice in NV-DDR mode */ + if (len && nand_interface_is_nvddr(conf)) { + ddrbuf = kzalloc(len * 2, GFP_KERNEL); + if (!ddrbuf) + return -ENOMEM; + + instrs[2].ctx.data.len *= 2; + instrs[2].ctx.data.buf.in = ddrbuf; + } /* Drop the DATA_IN instruction if len is set to 0. */ if (!len) op.ninstrs--; - return nand_exec_op(chip, &op); + ret = nand_exec_op(chip, &op); + if (!ret && len && nand_interface_is_nvddr(conf)) { + for (i = 0; i < len; i++) + id[i] = ddrbuf[i * 2]; + } + + kfree(ddrbuf); + + return ret; } chip->legacy.cmdfunc(chip, NAND_CMD_READID, addr, -1); @@ -1642,19 +1749,31 @@ EXPORT_SYMBOL_GPL(nand_readid_op); int nand_status_op(struct nand_chip *chip, u8 *status) { if (nand_has_exec_op(chip)) { - const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(nand_get_interface_config(chip)); + const struct nand_interface_config *conf = + nand_get_interface_config(chip); + u8 ddrstatus[2]; struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_STATUS, - PSEC_TO_NSEC(sdr->tADL_min)), + NAND_COMMON_TIMING_NS(conf, tADL_min)), NAND_OP_8BIT_DATA_IN(1, status, 0), }; struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs); + int ret; + + /* The status data byte will be received twice in NV-DDR mode */ + if (status && nand_interface_is_nvddr(conf)) { + instrs[1].ctx.data.len *= 2; + instrs[1].ctx.data.buf.in = ddrstatus; + } if (!status) op.ninstrs--; - return nand_exec_op(chip, &op); + ret = nand_exec_op(chip, &op); + if (!ret && status && nand_interface_is_nvddr(conf)) + *status = ddrstatus[0]; + + return ret; } chip->legacy.cmdfunc(chip, NAND_CMD_STATUS, -1, -1); @@ -1711,15 +1830,16 @@ int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock) u8 status; if (nand_has_exec_op(chip)) { - const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(nand_get_interface_config(chip)); + const struct nand_interface_config *conf = + nand_get_interface_config(chip); u8 addrs[3] = { page, page >> 8, page >> 16 }; struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_ERASE1, 0), NAND_OP_ADDR(2, addrs, 0), NAND_OP_CMD(NAND_CMD_ERASE2, - PSEC_TO_MSEC(sdr->tWB_max)), - NAND_OP_WAIT_RDY(PSEC_TO_MSEC(sdr->tBERS_max), 0), + NAND_COMMON_TIMING_MS(conf, tWB_max)), + NAND_OP_WAIT_RDY(NAND_COMMON_TIMING_MS(conf, tBERS_max), + 0), }; struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs); @@ -1770,14 +1890,17 @@ static int nand_set_features_op(struct nand_chip *chip, u8 feature, int i, ret; if (nand_has_exec_op(chip)) { - const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(nand_get_interface_config(chip)); + const struct nand_interface_config *conf = + nand_get_interface_config(chip); struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_SET_FEATURES, 0), - NAND_OP_ADDR(1, &feature, PSEC_TO_NSEC(sdr->tADL_min)), + NAND_OP_ADDR(1, &feature, NAND_COMMON_TIMING_NS(conf, + tADL_min)), NAND_OP_8BIT_DATA_OUT(ONFI_SUBFEATURE_PARAM_LEN, data, - PSEC_TO_NSEC(sdr->tWB_max)), - NAND_OP_WAIT_RDY(PSEC_TO_MSEC(sdr->tFEAT_max), 0), + NAND_COMMON_TIMING_NS(conf, + tWB_max)), + NAND_OP_WAIT_RDY(NAND_COMMON_TIMING_MS(conf, tFEAT_max), + 0), }; struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs); @@ -1813,23 +1936,37 @@ static int nand_set_features_op(struct nand_chip *chip, u8 feature, static int nand_get_features_op(struct nand_chip *chip, u8 feature, void *data) { - u8 *params = data; + u8 *params = data, ddrbuf[ONFI_SUBFEATURE_PARAM_LEN * 2]; int i; if (nand_has_exec_op(chip)) { - const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(nand_get_interface_config(chip)); + const struct nand_interface_config *conf = + nand_get_interface_config(chip); struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_GET_FEATURES, 0), - NAND_OP_ADDR(1, &feature, PSEC_TO_NSEC(sdr->tWB_max)), - NAND_OP_WAIT_RDY(PSEC_TO_MSEC(sdr->tFEAT_max), - PSEC_TO_NSEC(sdr->tRR_min)), + NAND_OP_ADDR(1, &feature, + NAND_COMMON_TIMING_NS(conf, tWB_max)), + NAND_OP_WAIT_RDY(NAND_COMMON_TIMING_MS(conf, tFEAT_max), + NAND_COMMON_TIMING_NS(conf, tRR_min)), NAND_OP_8BIT_DATA_IN(ONFI_SUBFEATURE_PARAM_LEN, data, 0), }; struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs); + int ret; - return nand_exec_op(chip, &op); + /* GET_FEATURE data bytes are received twice in NV-DDR mode */ + if (nand_interface_is_nvddr(conf)) { + instrs[3].ctx.data.len *= 2; + instrs[3].ctx.data.buf.in = ddrbuf; + } + + ret = nand_exec_op(chip, &op); + if (nand_interface_is_nvddr(conf)) { + for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; i++) + params[i] = ddrbuf[i * 2]; + } + + return ret; } chip->legacy.cmdfunc(chip, NAND_CMD_GET_FEATURES, feature, -1); @@ -1874,11 +2011,13 @@ static int nand_wait_rdy_op(struct nand_chip *chip, unsigned int timeout_ms, int nand_reset_op(struct nand_chip *chip) { if (nand_has_exec_op(chip)) { - const struct nand_sdr_timings *sdr = - nand_get_sdr_timings(nand_get_interface_config(chip)); + const struct nand_interface_config *conf = + nand_get_interface_config(chip); struct nand_op_instr instrs[] = { - NAND_OP_CMD(NAND_CMD_RESET, PSEC_TO_NSEC(sdr->tWB_max)), - NAND_OP_WAIT_RDY(PSEC_TO_MSEC(sdr->tRST_max), 0), + NAND_OP_CMD(NAND_CMD_RESET, + NAND_COMMON_TIMING_NS(conf, tWB_max)), + NAND_OP_WAIT_RDY(NAND_COMMON_TIMING_MS(conf, tRST_max), + 0), }; struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs); @@ -1913,17 +2052,50 @@ int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len, return -EINVAL; if (nand_has_exec_op(chip)) { + const struct nand_interface_config *conf = + nand_get_interface_config(chip); struct nand_op_instr instrs[] = { NAND_OP_DATA_IN(len, buf, 0), }; struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs); + u8 *ddrbuf = NULL; + int ret, i; instrs[0].ctx.data.force_8bit = force_8bit; - if (check_only) - return nand_check_op(chip, &op); + /* + * Parameter payloads (ID, status, features, etc) do not go + * through the same pipeline as regular data, hence the + * force_8bit flag must be set and this also indicates that in + * case NV-DDR timings are being used the data will be received + * twice. + */ + if (force_8bit && nand_interface_is_nvddr(conf)) { + ddrbuf = kzalloc(len * 2, GFP_KERNEL); + if (!ddrbuf) + return -ENOMEM; - return nand_exec_op(chip, &op); + instrs[0].ctx.data.len *= 2; + instrs[0].ctx.data.buf.in = ddrbuf; + } + + if (check_only) { + ret = nand_check_op(chip, &op); + kfree(ddrbuf); + return ret; + } + + ret = nand_exec_op(chip, &op); + if (!ret && force_8bit && nand_interface_is_nvddr(conf)) { + u8 *dst = buf; + + for (i = 0; i < len; i++) + dst[i] = ddrbuf[i * 2]; + } + + kfree(ddrbuf); + + return ret; } if (check_only) @@ -3136,13 +3308,13 @@ static int nand_setup_read_retry(struct nand_chip *chip, int retry_mode) static void nand_wait_readrdy(struct nand_chip *chip) { - const struct nand_sdr_timings *sdr; + const struct nand_interface_config *conf; if (!(chip->options & NAND_NEED_READRDY)) return; - sdr = nand_get_sdr_timings(nand_get_interface_config(chip)); - WARN_ON(nand_wait_rdy_op(chip, PSEC_TO_MSEC(sdr->tR_max), 0)); + conf = nand_get_interface_config(chip); + WARN_ON(nand_wait_rdy_op(chip, NAND_COMMON_TIMING_MS(conf, tR_max), 0)); } /** @@ -5078,6 +5250,44 @@ static int of_get_nand_secure_regions(struct nand_chip *chip) return 0; } +/** + * rawnand_dt_parse_gpio_cs - Parse the gpio-cs property of a controller + * @dev: Device that will be parsed. Also used for managed allocations. + * @cs_array: Array of GPIO desc pointers allocated on success + * @ncs_array: Number of entries in @cs_array updated on success. + * @return 0 on success, an error otherwise. + */ +int rawnand_dt_parse_gpio_cs(struct device *dev, struct gpio_desc ***cs_array, + unsigned int *ncs_array) +{ + struct device_node *np = dev->of_node; + struct gpio_desc **descs; + int ndescs, i; + + ndescs = of_gpio_named_count(np, "cs-gpios"); + if (ndescs < 0) { + dev_dbg(dev, "No valid cs-gpios property\n"); + return 0; + } + + descs = devm_kcalloc(dev, ndescs, sizeof(*descs), GFP_KERNEL); + if (!descs) + return -ENOMEM; + + for (i = 0; i < ndescs; i++) { + descs[i] = gpiod_get_index_optional(dev, "cs", i, + GPIOD_OUT_HIGH); + if (IS_ERR(descs[i])) + return PTR_ERR(descs[i]); + } + + *ncs_array = ndescs; + *cs_array = descs; + + return 0; +} +EXPORT_SYMBOL(rawnand_dt_parse_gpio_cs); + static int rawnand_dt_init(struct nand_chip *chip) { struct nand_device *nand = mtd_to_nanddev(nand_to_mtd(chip)); diff --git a/drivers/mtd/nand/raw/nand_legacy.c b/drivers/mtd/nand/raw/nand_legacy.c index eccc18b266d5..743792edf98d 100644 --- a/drivers/mtd/nand/raw/nand_legacy.c +++ b/drivers/mtd/nand/raw/nand_legacy.c @@ -369,7 +369,7 @@ static void nand_ccs_delay(struct nand_chip *chip) * Wait tCCS_min if it is correctly defined, otherwise wait 500ns * (which should be safe for all NANDs). */ - if (nand_controller_can_setup_interface(chip)) + if (!IS_ERR(sdr) && nand_controller_can_setup_interface(chip)) ndelay(sdr->tCCS_min / 1000); else ndelay(500); diff --git a/drivers/mtd/nand/raw/nand_onfi.c b/drivers/mtd/nand/raw/nand_onfi.c index 45649e03797d..7586befce7f9 100644 --- a/drivers/mtd/nand/raw/nand_onfi.c +++ b/drivers/mtd/nand/raw/nand_onfi.c @@ -315,7 +315,10 @@ int nand_onfi_detect(struct nand_chip *chip) onfi->tBERS = le16_to_cpu(p->t_bers); onfi->tR = le16_to_cpu(p->t_r); onfi->tCCS = le16_to_cpu(p->t_ccs); - onfi->async_timing_mode = le16_to_cpu(p->async_timing_mode); + onfi->fast_tCAD = le16_to_cpu(p->nvddr_nvddr2_features) & BIT(0); + onfi->sdr_timing_modes = le16_to_cpu(p->sdr_timing_modes); + if (le16_to_cpu(p->features) & ONFI_FEATURE_NV_DDR) + onfi->nvddr_timing_modes = le16_to_cpu(p->nvddr_timing_modes); onfi->vendor_revision = le16_to_cpu(p->vendor_revision); memcpy(onfi->vendor, p->vendor, sizeof(p->vendor)); chip->parameters.onfi = onfi; diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c index 94d832646487..7b41afc372d2 100644 --- a/drivers/mtd/nand/raw/nand_timings.c +++ b/drivers/mtd/nand/raw/nand_timings.c @@ -292,6 +292,261 @@ static const struct nand_interface_config onfi_sdr_timings[] = { }, }; +static const struct nand_interface_config onfi_nvddr_timings[] = { + /* Mode 0 */ + { + .type = NAND_NVDDR_IFACE, + .timings.mode = 0, + .timings.nvddr = { + .tCCS_min = 500000, + .tR_max = 200000000, + .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, + .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, + .tAC_min = 3000, + .tAC_max = 25000, + .tADL_min = 400000, + .tCAD_min = 45000, + .tCAH_min = 10000, + .tCALH_min = 10000, + .tCALS_min = 10000, + .tCAS_min = 10000, + .tCEH_min = 20000, + .tCH_min = 10000, + .tCK_min = 50000, + .tCS_min = 35000, + .tDH_min = 5000, + .tDQSCK_min = 3000, + .tDQSCK_max = 25000, + .tDQSD_min = 0, + .tDQSD_max = 18000, + .tDQSHZ_max = 20000, + .tDQSQ_max = 5000, + .tDS_min = 5000, + .tDSC_min = 50000, + .tFEAT_max = 1000000, + .tITC_max = 1000000, + .tQHS_max = 6000, + .tRHW_min = 100000, + .tRR_min = 20000, + .tRST_max = 500000000, + .tWB_max = 100000, + .tWHR_min = 80000, + .tWRCK_min = 20000, + .tWW_min = 100000, + }, + }, + /* Mode 1 */ + { + .type = NAND_NVDDR_IFACE, + .timings.mode = 1, + .timings.nvddr = { + .tCCS_min = 500000, + .tR_max = 200000000, + .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, + .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, + .tAC_min = 3000, + .tAC_max = 25000, + .tADL_min = 400000, + .tCAD_min = 45000, + .tCAH_min = 5000, + .tCALH_min = 5000, + .tCALS_min = 5000, + .tCAS_min = 5000, + .tCEH_min = 20000, + .tCH_min = 5000, + .tCK_min = 30000, + .tCS_min = 25000, + .tDH_min = 2500, + .tDQSCK_min = 3000, + .tDQSCK_max = 25000, + .tDQSD_min = 0, + .tDQSD_max = 18000, + .tDQSHZ_max = 20000, + .tDQSQ_max = 2500, + .tDS_min = 3000, + .tDSC_min = 30000, + .tFEAT_max = 1000000, + .tITC_max = 1000000, + .tQHS_max = 3000, + .tRHW_min = 100000, + .tRR_min = 20000, + .tRST_max = 500000000, + .tWB_max = 100000, + .tWHR_min = 80000, + .tWRCK_min = 20000, + .tWW_min = 100000, + }, + }, + /* Mode 2 */ + { + .type = NAND_NVDDR_IFACE, + .timings.mode = 2, + .timings.nvddr = { + .tCCS_min = 500000, + .tR_max = 200000000, + .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, + .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, + .tAC_min = 3000, + .tAC_max = 25000, + .tADL_min = 400000, + .tCAD_min = 45000, + .tCAH_min = 4000, + .tCALH_min = 4000, + .tCALS_min = 4000, + .tCAS_min = 4000, + .tCEH_min = 20000, + .tCH_min = 4000, + .tCK_min = 20000, + .tCS_min = 15000, + .tDH_min = 1700, + .tDQSCK_min = 3000, + .tDQSCK_max = 25000, + .tDQSD_min = 0, + .tDQSD_max = 18000, + .tDQSHZ_max = 20000, + .tDQSQ_max = 1700, + .tDS_min = 2000, + .tDSC_min = 20000, + .tFEAT_max = 1000000, + .tITC_max = 1000000, + .tQHS_max = 2000, + .tRHW_min = 100000, + .tRR_min = 20000, + .tRST_max = 500000000, + .tWB_max = 100000, + .tWHR_min = 80000, + .tWRCK_min = 20000, + .tWW_min = 100000, + }, + }, + /* Mode 3 */ + { + .type = NAND_NVDDR_IFACE, + .timings.mode = 3, + .timings.nvddr = { + .tCCS_min = 500000, + .tR_max = 200000000, + .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, + .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, + .tAC_min = 3000, + .tAC_max = 25000, + .tADL_min = 400000, + .tCAD_min = 45000, + .tCAH_min = 3000, + .tCALH_min = 3000, + .tCALS_min = 3000, + .tCAS_min = 3000, + .tCEH_min = 20000, + .tCH_min = 3000, + .tCK_min = 15000, + .tCS_min = 15000, + .tDH_min = 1300, + .tDQSCK_min = 3000, + .tDQSCK_max = 25000, + .tDQSD_min = 0, + .tDQSD_max = 18000, + .tDQSHZ_max = 20000, + .tDQSQ_max = 1300, + .tDS_min = 1500, + .tDSC_min = 15000, + .tFEAT_max = 1000000, + .tITC_max = 1000000, + .tQHS_max = 1500, + .tRHW_min = 100000, + .tRR_min = 20000, + .tRST_max = 500000000, + .tWB_max = 100000, + .tWHR_min = 80000, + .tWRCK_min = 20000, + .tWW_min = 100000, + }, + }, + /* Mode 4 */ + { + .type = NAND_NVDDR_IFACE, + .timings.mode = 4, + .timings.nvddr = { + .tCCS_min = 500000, + .tR_max = 200000000, + .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, + .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, + .tAC_min = 3000, + .tAC_max = 25000, + .tADL_min = 400000, + .tCAD_min = 45000, + .tCAH_min = 2500, + .tCALH_min = 2500, + .tCALS_min = 2500, + .tCAS_min = 2500, + .tCEH_min = 20000, + .tCH_min = 2500, + .tCK_min = 12000, + .tCS_min = 15000, + .tDH_min = 1100, + .tDQSCK_min = 3000, + .tDQSCK_max = 25000, + .tDQSD_min = 0, + .tDQSD_max = 18000, + .tDQSHZ_max = 20000, + .tDQSQ_max = 1000, + .tDS_min = 1100, + .tDSC_min = 12000, + .tFEAT_max = 1000000, + .tITC_max = 1000000, + .tQHS_max = 1200, + .tRHW_min = 100000, + .tRR_min = 20000, + .tRST_max = 500000000, + .tWB_max = 100000, + .tWHR_min = 80000, + .tWRCK_min = 20000, + .tWW_min = 100000, + }, + }, + /* Mode 5 */ + { + .type = NAND_NVDDR_IFACE, + .timings.mode = 5, + .timings.nvddr = { + .tCCS_min = 500000, + .tR_max = 200000000, + .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, + .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, + .tAC_min = 3000, + .tAC_max = 25000, + .tADL_min = 400000, + .tCAD_min = 45000, + .tCAH_min = 2000, + .tCALH_min = 2000, + .tCALS_min = 2000, + .tCAS_min = 2000, + .tCEH_min = 20000, + .tCH_min = 2000, + .tCK_min = 10000, + .tCS_min = 15000, + .tDH_min = 900, + .tDQSCK_min = 3000, + .tDQSCK_max = 25000, + .tDQSD_min = 0, + .tDQSD_max = 18000, + .tDQSHZ_max = 20000, + .tDQSQ_max = 850, + .tDS_min = 900, + .tDSC_min = 10000, + .tFEAT_max = 1000000, + .tITC_max = 1000000, + .tQHS_max = 1000, + .tRHW_min = 100000, + .tRR_min = 20000, + .tRST_max = 500000000, + .tWB_max = 100000, + .tWHR_min = 80000, + .tWRCK_min = 20000, + .tWW_min = 100000, + }, + }, +}; + /* All NAND chips share the same reset data interface: SDR mode 0 */ const struct nand_interface_config *nand_get_reset_interface_config(void) { @@ -346,23 +601,60 @@ onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings) } /** - * onfi_fill_interface_config - Initialize an interface config from a given - * ONFI mode + * onfi_find_closest_nvddr_mode - Derive the closest ONFI NVDDR timing mode + * given a set of timings + * @spec_timings: the timings to challenge + */ +unsigned int +onfi_find_closest_nvddr_mode(const struct nand_nvddr_timings *spec_timings) +{ + const struct nand_nvddr_timings *onfi_timings; + int mode; + + for (mode = ARRAY_SIZE(onfi_nvddr_timings) - 1; mode > 0; mode--) { + onfi_timings = &onfi_nvddr_timings[mode].timings.nvddr; + + if (spec_timings->tCCS_min <= onfi_timings->tCCS_min && + spec_timings->tAC_min <= onfi_timings->tAC_min && + spec_timings->tADL_min <= onfi_timings->tADL_min && + spec_timings->tCAD_min <= onfi_timings->tCAD_min && + spec_timings->tCAH_min <= onfi_timings->tCAH_min && + spec_timings->tCALH_min <= onfi_timings->tCALH_min && + spec_timings->tCALS_min <= onfi_timings->tCALS_min && + spec_timings->tCAS_min <= onfi_timings->tCAS_min && + spec_timings->tCEH_min <= onfi_timings->tCEH_min && + spec_timings->tCH_min <= onfi_timings->tCH_min && + spec_timings->tCK_min <= onfi_timings->tCK_min && + spec_timings->tCS_min <= onfi_timings->tCS_min && + spec_timings->tDH_min <= onfi_timings->tDH_min && + spec_timings->tDQSCK_min <= onfi_timings->tDQSCK_min && + spec_timings->tDQSD_min <= onfi_timings->tDQSD_min && + spec_timings->tDS_min <= onfi_timings->tDS_min && + spec_timings->tDSC_min <= onfi_timings->tDSC_min && + spec_timings->tRHW_min <= onfi_timings->tRHW_min && + spec_timings->tRR_min <= onfi_timings->tRR_min && + spec_timings->tWHR_min <= onfi_timings->tWHR_min && + spec_timings->tWRCK_min <= onfi_timings->tWRCK_min && + spec_timings->tWW_min <= onfi_timings->tWW_min) + return mode; + } + + return 0; +} + +/* + * onfi_fill_sdr_interface_config - Initialize a SDR interface config from a + * given ONFI mode * @chip: The NAND chip * @iface: The interface configuration to fill - * @type: The interface type * @timing_mode: The ONFI timing mode */ -void onfi_fill_interface_config(struct nand_chip *chip, - struct nand_interface_config *iface, - enum nand_interface_type type, - unsigned int timing_mode) +static void onfi_fill_sdr_interface_config(struct nand_chip *chip, + struct nand_interface_config *iface, + unsigned int timing_mode) { struct onfi_params *onfi = chip->parameters.onfi; - if (WARN_ON(type != NAND_SDR_IFACE)) - return; - if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_sdr_timings))) return; @@ -385,3 +677,61 @@ void onfi_fill_interface_config(struct nand_chip *chip, timings->tCCS_min = 1000UL * onfi->tCCS; } } + +/** + * onfi_fill_nvddr_interface_config - Initialize a NVDDR interface config from a + * given ONFI mode + * @chip: The NAND chip + * @iface: The interface configuration to fill + * @timing_mode: The ONFI timing mode + */ +static void onfi_fill_nvddr_interface_config(struct nand_chip *chip, + struct nand_interface_config *iface, + unsigned int timing_mode) +{ + struct onfi_params *onfi = chip->parameters.onfi; + + if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_nvddr_timings))) + return; + + *iface = onfi_nvddr_timings[timing_mode]; + + /* + * Initialize timings that cannot be deduced from timing mode: + * tPROG, tBERS, tR, tCCS and tCAD. + * These information are part of the ONFI parameter page. + */ + if (onfi) { + struct nand_nvddr_timings *timings = &iface->timings.nvddr; + + /* microseconds -> picoseconds */ + timings->tPROG_max = 1000000ULL * onfi->tPROG; + timings->tBERS_max = 1000000ULL * onfi->tBERS; + timings->tR_max = 1000000ULL * onfi->tR; + + /* nanoseconds -> picoseconds */ + timings->tCCS_min = 1000UL * onfi->tCCS; + + if (onfi->fast_tCAD) + timings->tCAD_min = 25000; + } +} + +/** + * onfi_fill_interface_config - Initialize an interface config from a given + * ONFI mode + * @chip: The NAND chip + * @iface: The interface configuration to fill + * @type: The interface type + * @timing_mode: The ONFI timing mode + */ +void onfi_fill_interface_config(struct nand_chip *chip, + struct nand_interface_config *iface, + enum nand_interface_type type, + unsigned int timing_mode) +{ + if (type == NAND_SDR_IFACE) + return onfi_fill_sdr_interface_config(chip, iface, timing_mode); + else + return onfi_fill_nvddr_interface_config(chip, iface, timing_mode); +} diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index c75e7a0b101f..b1839eef5b65 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -131,7 +131,7 @@ #define BCH_ECC_SIZE0 0x0 /* ecc_size0 = 0, no oob protection */ #define BCH_ECC_SIZE1 0x20 /* ecc_size1 = 32 */ -#define BADBLOCK_MARKER_LENGTH 2 +#define BBM_LEN 2 static u_char bch16_vector[] = {0xf5, 0x24, 0x1c, 0xd0, 0x61, 0xb3, 0xf1, 0x55, 0x2e, 0x2c, 0x86, 0xa3, 0xed, 0x36, 0x1b, 0x78, @@ -171,6 +171,10 @@ struct omap_nand_info { struct device *elm_dev; /* NAND ready gpio */ struct gpio_desc *ready_gpiod; + unsigned int neccpg; + unsigned int nsteps_per_eccpg; + unsigned int eccpg_size; + unsigned int eccpg_bytes; }; static inline struct omap_nand_info *mtd_to_omap(struct mtd_info *mtd) @@ -1355,7 +1359,7 @@ static int omap_elm_correct_data(struct nand_chip *chip, u_char *data, { struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip)); struct nand_ecc_ctrl *ecc = &info->nand.ecc; - int eccsteps = info->nand.ecc.steps; + int eccsteps = info->nsteps_per_eccpg; int i , j, stat = 0; int eccflag, actual_eccbytes; struct elm_errorvec err_vec[ERROR_VECTOR_MAX]; @@ -1525,24 +1529,37 @@ static int omap_write_page_bch(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { struct mtd_info *mtd = nand_to_mtd(chip); - int ret; + struct omap_nand_info *info = mtd_to_omap(mtd); uint8_t *ecc_calc = chip->ecc.calc_buf; + unsigned int eccpg; + int ret; - nand_prog_page_begin_op(chip, page, 0, NULL, 0); + ret = nand_prog_page_begin_op(chip, page, 0, NULL, 0); + if (ret) + return ret; - /* Enable GPMC ecc engine */ - chip->ecc.hwctl(chip, NAND_ECC_WRITE); + for (eccpg = 0; eccpg < info->neccpg; eccpg++) { + /* Enable GPMC ecc engine */ + chip->ecc.hwctl(chip, NAND_ECC_WRITE); - /* Write data */ - chip->legacy.write_buf(chip, buf, mtd->writesize); + /* Write data */ + chip->legacy.write_buf(chip, buf + (eccpg * info->eccpg_size), + info->eccpg_size); - /* Update ecc vector from GPMC result registers */ - omap_calculate_ecc_bch_multi(mtd, buf, &ecc_calc[0]); + /* Update ecc vector from GPMC result registers */ + ret = omap_calculate_ecc_bch_multi(mtd, + buf + (eccpg * info->eccpg_size), + ecc_calc); + if (ret) + return ret; - ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0, - chip->ecc.total); - if (ret) - return ret; + ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, + chip->oob_poi, + eccpg * info->eccpg_bytes, + info->eccpg_bytes); + if (ret) + return ret; + } /* Write ecc vector to OOB area */ chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize); @@ -1566,12 +1583,13 @@ static int omap_write_subpage_bch(struct nand_chip *chip, u32 offset, int oob_required, int page) { struct mtd_info *mtd = nand_to_mtd(chip); + struct omap_nand_info *info = mtd_to_omap(mtd); u8 *ecc_calc = chip->ecc.calc_buf; int ecc_size = chip->ecc.size; int ecc_bytes = chip->ecc.bytes; - int ecc_steps = chip->ecc.steps; u32 start_step = offset / ecc_size; u32 end_step = (offset + data_len - 1) / ecc_size; + unsigned int eccpg; int step, ret = 0; /* @@ -1580,36 +1598,48 @@ static int omap_write_subpage_bch(struct nand_chip *chip, u32 offset, * ECC is calculated for all subpages but we choose * only what we want. */ - nand_prog_page_begin_op(chip, page, 0, NULL, 0); - - /* Enable GPMC ECC engine */ - chip->ecc.hwctl(chip, NAND_ECC_WRITE); - - /* Write data */ - chip->legacy.write_buf(chip, buf, mtd->writesize); + ret = nand_prog_page_begin_op(chip, page, 0, NULL, 0); + if (ret) + return ret; - for (step = 0; step < ecc_steps; step++) { - /* mask ECC of un-touched subpages by padding 0xFF */ - if (step < start_step || step > end_step) - memset(ecc_calc, 0xff, ecc_bytes); - else - ret = _omap_calculate_ecc_bch(mtd, buf, ecc_calc, step); + for (eccpg = 0; eccpg < info->neccpg; eccpg++) { + /* Enable GPMC ECC engine */ + chip->ecc.hwctl(chip, NAND_ECC_WRITE); + + /* Write data */ + chip->legacy.write_buf(chip, buf + (eccpg * info->eccpg_size), + info->eccpg_size); + + for (step = 0; step < info->nsteps_per_eccpg; step++) { + unsigned int base_step = eccpg * info->nsteps_per_eccpg; + const u8 *bufoffs = buf + (eccpg * info->eccpg_size); + + /* Mask ECC of un-touched subpages with 0xFFs */ + if ((step + base_step) < start_step || + (step + base_step) > end_step) + memset(ecc_calc + (step * ecc_bytes), 0xff, + ecc_bytes); + else + ret = _omap_calculate_ecc_bch(mtd, + bufoffs + (step * ecc_size), + ecc_calc + (step * ecc_bytes), + step); + + if (ret) + return ret; + } + /* + * Copy the calculated ECC for the whole page including the + * masked values (0xFF) corresponding to unwritten subpages. + */ + ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, + eccpg * info->eccpg_bytes, + info->eccpg_bytes); if (ret) return ret; - - buf += ecc_size; - ecc_calc += ecc_bytes; } - /* copy calculated ECC for whole page to chip->buffer->oob */ - /* this include masked-value(0xFF) for unwritten subpages */ - ecc_calc = chip->ecc.calc_buf; - ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0, - chip->ecc.total); - if (ret) - return ret; - /* write OOB buffer to NAND device */ chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize); @@ -1634,40 +1664,60 @@ static int omap_read_page_bch(struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { struct mtd_info *mtd = nand_to_mtd(chip); + struct omap_nand_info *info = mtd_to_omap(mtd); uint8_t *ecc_calc = chip->ecc.calc_buf; uint8_t *ecc_code = chip->ecc.code_buf; + unsigned int max_bitflips = 0, eccpg; int stat, ret; - unsigned int max_bitflips = 0; - - nand_read_page_op(chip, page, 0, NULL, 0); - /* Enable GPMC ecc engine */ - chip->ecc.hwctl(chip, NAND_ECC_READ); + ret = nand_read_page_op(chip, page, 0, NULL, 0); + if (ret) + return ret; - /* Read data */ - chip->legacy.read_buf(chip, buf, mtd->writesize); + for (eccpg = 0; eccpg < info->neccpg; eccpg++) { + /* Enable GPMC ecc engine */ + chip->ecc.hwctl(chip, NAND_ECC_READ); - /* Read oob bytes */ - nand_change_read_column_op(chip, - mtd->writesize + BADBLOCK_MARKER_LENGTH, - chip->oob_poi + BADBLOCK_MARKER_LENGTH, - chip->ecc.total, false); + /* Read data */ + ret = nand_change_read_column_op(chip, eccpg * info->eccpg_size, + buf + (eccpg * info->eccpg_size), + info->eccpg_size, false); + if (ret) + return ret; - /* Calculate ecc bytes */ - omap_calculate_ecc_bch_multi(mtd, buf, ecc_calc); + /* Read oob bytes */ + ret = nand_change_read_column_op(chip, + mtd->writesize + BBM_LEN + + (eccpg * info->eccpg_bytes), + chip->oob_poi + BBM_LEN + + (eccpg * info->eccpg_bytes), + info->eccpg_bytes, false); + if (ret) + return ret; - ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, - chip->ecc.total); - if (ret) - return ret; + /* Calculate ecc bytes */ + ret = omap_calculate_ecc_bch_multi(mtd, + buf + (eccpg * info->eccpg_size), + ecc_calc); + if (ret) + return ret; - stat = chip->ecc.correct(chip, buf, ecc_code, ecc_calc); + ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, + chip->oob_poi, + eccpg * info->eccpg_bytes, + info->eccpg_bytes); + if (ret) + return ret; - if (stat < 0) { - mtd->ecc_stats.failed++; - } else { - mtd->ecc_stats.corrected += stat; - max_bitflips = max_t(unsigned int, max_bitflips, stat); + stat = chip->ecc.correct(chip, + buf + (eccpg * info->eccpg_size), + ecc_code, ecc_calc); + if (stat < 0) { + mtd->ecc_stats.failed++; + } else { + mtd->ecc_stats.corrected += stat; + max_bitflips = max_t(unsigned int, max_bitflips, stat); + } } return max_bitflips; @@ -1820,7 +1870,7 @@ static int omap_ooblayout_ecc(struct mtd_info *mtd, int section, { struct omap_nand_info *info = mtd_to_omap(mtd); struct nand_chip *chip = &info->nand; - int off = BADBLOCK_MARKER_LENGTH; + int off = BBM_LEN; if (info->ecc_opt == OMAP_ECC_HAM1_CODE_HW && !(chip->options & NAND_BUSWIDTH_16)) @@ -1840,7 +1890,7 @@ static int omap_ooblayout_free(struct mtd_info *mtd, int section, { struct omap_nand_info *info = mtd_to_omap(mtd); struct nand_chip *chip = &info->nand; - int off = BADBLOCK_MARKER_LENGTH; + int off = BBM_LEN; if (info->ecc_opt == OMAP_ECC_HAM1_CODE_HW && !(chip->options & NAND_BUSWIDTH_16)) @@ -1870,7 +1920,7 @@ static int omap_sw_ooblayout_ecc(struct mtd_info *mtd, int section, struct nand_device *nand = mtd_to_nanddev(mtd); unsigned int nsteps = nanddev_get_ecc_nsteps(nand); unsigned int ecc_bytes = nanddev_get_ecc_bytes_per_step(nand); - int off = BADBLOCK_MARKER_LENGTH; + int off = BBM_LEN; if (section >= nsteps) return -ERANGE; @@ -1891,7 +1941,7 @@ static int omap_sw_ooblayout_free(struct mtd_info *mtd, int section, struct nand_device *nand = mtd_to_nanddev(mtd); unsigned int nsteps = nanddev_get_ecc_nsteps(nand); unsigned int ecc_bytes = nanddev_get_ecc_bytes_per_step(nand); - int off = BADBLOCK_MARKER_LENGTH; + int off = BBM_LEN; if (section) return -ERANGE; @@ -1920,7 +1970,8 @@ static int omap_nand_attach_chip(struct nand_chip *chip) struct mtd_info *mtd = nand_to_mtd(chip); struct omap_nand_info *info = mtd_to_omap(mtd); struct device *dev = &info->pdev->dev; - int min_oobbytes = BADBLOCK_MARKER_LENGTH; + int min_oobbytes = BBM_LEN; + int elm_bch_strength = -1; int oobbytes_per_step; dma_cap_mask_t mask; int err; @@ -2074,12 +2125,7 @@ static int omap_nand_attach_chip(struct nand_chip *chip) chip->ecc.write_subpage = omap_write_subpage_bch; mtd_set_ooblayout(mtd, &omap_ooblayout_ops); oobbytes_per_step = chip->ecc.bytes; - - err = elm_config(info->elm_dev, BCH4_ECC, - mtd->writesize / chip->ecc.size, - chip->ecc.size, chip->ecc.bytes); - if (err < 0) - return err; + elm_bch_strength = BCH4_ECC; break; case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: @@ -2116,13 +2162,7 @@ static int omap_nand_attach_chip(struct nand_chip *chip) chip->ecc.write_subpage = omap_write_subpage_bch; mtd_set_ooblayout(mtd, &omap_ooblayout_ops); oobbytes_per_step = chip->ecc.bytes; - - err = elm_config(info->elm_dev, BCH8_ECC, - mtd->writesize / chip->ecc.size, - chip->ecc.size, chip->ecc.bytes); - if (err < 0) - return err; - + elm_bch_strength = BCH8_ECC; break; case OMAP_ECC_BCH16_CODE_HW: @@ -2138,19 +2178,32 @@ static int omap_nand_attach_chip(struct nand_chip *chip) chip->ecc.write_subpage = omap_write_subpage_bch; mtd_set_ooblayout(mtd, &omap_ooblayout_ops); oobbytes_per_step = chip->ecc.bytes; - - err = elm_config(info->elm_dev, BCH16_ECC, - mtd->writesize / chip->ecc.size, - chip->ecc.size, chip->ecc.bytes); - if (err < 0) - return err; - + elm_bch_strength = BCH16_ECC; break; default: dev_err(dev, "Invalid or unsupported ECC scheme\n"); return -EINVAL; } + if (elm_bch_strength >= 0) { + chip->ecc.steps = mtd->writesize / chip->ecc.size; + info->neccpg = chip->ecc.steps / ERROR_VECTOR_MAX; + if (info->neccpg) { + info->nsteps_per_eccpg = ERROR_VECTOR_MAX; + } else { + info->neccpg = 1; + info->nsteps_per_eccpg = chip->ecc.steps; + } + info->eccpg_size = info->nsteps_per_eccpg * chip->ecc.size; + info->eccpg_bytes = info->nsteps_per_eccpg * chip->ecc.bytes; + + err = elm_config(info->elm_dev, elm_bch_strength, + info->nsteps_per_eccpg, chip->ecc.size, + chip->ecc.bytes); + if (err < 0) + return err; + } + /* Check if NAND device's OOB is enough to store ECC signatures */ min_oobbytes += (oobbytes_per_step * (mtd->writesize / chip->ecc.size)); diff --git a/drivers/mtd/nand/raw/omap_elm.c b/drivers/mtd/nand/raw/omap_elm.c index 550695a4c1ab..2b21ce04b3ec 100644 --- a/drivers/mtd/nand/raw/omap_elm.c +++ b/drivers/mtd/nand/raw/omap_elm.c @@ -116,7 +116,7 @@ int elm_config(struct device *dev, enum bch_ecc bch_type, return -EINVAL; } /* ELM support 8 error syndrome process */ - if (ecc_steps > ERROR_VECTOR_MAX) { + if (ecc_steps > ERROR_VECTOR_MAX && ecc_steps % ERROR_VECTOR_MAX) { dev_err(dev, "unsupported config ecc-step=%d\n", ecc_steps); return -EINVAL; } diff --git a/drivers/mtd/nand/raw/pl35x-nand-controller.c b/drivers/mtd/nand/raw/pl35x-nand-controller.c new file mode 100644 index 000000000000..8a91e069ee2e --- /dev/null +++ b/drivers/mtd/nand/raw/pl35x-nand-controller.c @@ -0,0 +1,1194 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM PL35X NAND flash controller driver + * + * Copyright (C) 2017 Xilinx, Inc + * Author: + * Miquel Raynal <miquel.raynal@bootlin.com> + * Original work (rewritten): + * Punnaiah Choudary Kalluri <punnaia@xilinx.com> + * Naga Sureshkumar Relli <nagasure@xilinx.com> + */ + +#include <linux/amba/bus.h> +#include <linux/err.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <linux/iopoll.h> +#include <linux/irq.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/rawnand.h> +#include <linux/mtd/partitions.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/clk.h> + +#define PL35X_NANDC_DRIVER_NAME "pl35x-nand-controller" + +/* SMC controller status register (RO) */ +#define PL35X_SMC_MEMC_STATUS 0x0 +#define PL35X_SMC_MEMC_STATUS_RAW_INT_STATUS1 BIT(6) +/* SMC clear config register (WO) */ +#define PL35X_SMC_MEMC_CFG_CLR 0xC +#define PL35X_SMC_MEMC_CFG_CLR_INT_DIS_1 BIT(1) +#define PL35X_SMC_MEMC_CFG_CLR_INT_CLR_1 BIT(4) +#define PL35X_SMC_MEMC_CFG_CLR_ECC_INT_DIS_1 BIT(6) +/* SMC direct command register (WO) */ +#define PL35X_SMC_DIRECT_CMD 0x10 +#define PL35X_SMC_DIRECT_CMD_NAND_CS (0x4 << 23) +#define PL35X_SMC_DIRECT_CMD_UPD_REGS (0x2 << 21) +/* SMC set cycles register (WO) */ +#define PL35X_SMC_CYCLES 0x14 +#define PL35X_SMC_NAND_TRC_CYCLES(x) ((x) << 0) +#define PL35X_SMC_NAND_TWC_CYCLES(x) ((x) << 4) +#define PL35X_SMC_NAND_TREA_CYCLES(x) ((x) << 8) +#define PL35X_SMC_NAND_TWP_CYCLES(x) ((x) << 11) +#define PL35X_SMC_NAND_TCLR_CYCLES(x) ((x) << 14) +#define PL35X_SMC_NAND_TAR_CYCLES(x) ((x) << 17) +#define PL35X_SMC_NAND_TRR_CYCLES(x) ((x) << 20) +/* SMC set opmode register (WO) */ +#define PL35X_SMC_OPMODE 0x18 +#define PL35X_SMC_OPMODE_BW_8 0 +#define PL35X_SMC_OPMODE_BW_16 1 +/* SMC ECC status register (RO) */ +#define PL35X_SMC_ECC_STATUS 0x400 +#define PL35X_SMC_ECC_STATUS_ECC_BUSY BIT(6) +/* SMC ECC configuration register */ +#define PL35X_SMC_ECC_CFG 0x404 +#define PL35X_SMC_ECC_CFG_MODE_MASK 0xC +#define PL35X_SMC_ECC_CFG_MODE_BYPASS 0 +#define PL35X_SMC_ECC_CFG_MODE_APB BIT(2) +#define PL35X_SMC_ECC_CFG_MODE_MEM BIT(3) +#define PL35X_SMC_ECC_CFG_PGSIZE_MASK 0x3 +/* SMC ECC command 1 register */ +#define PL35X_SMC_ECC_CMD1 0x408 +#define PL35X_SMC_ECC_CMD1_WRITE(x) ((x) << 0) +#define PL35X_SMC_ECC_CMD1_READ(x) ((x) << 8) +#define PL35X_SMC_ECC_CMD1_READ_END(x) ((x) << 16) +#define PL35X_SMC_ECC_CMD1_READ_END_VALID(x) ((x) << 24) +/* SMC ECC command 2 register */ +#define PL35X_SMC_ECC_CMD2 0x40C +#define PL35X_SMC_ECC_CMD2_WRITE_COL_CHG(x) ((x) << 0) +#define PL35X_SMC_ECC_CMD2_READ_COL_CHG(x) ((x) << 8) +#define PL35X_SMC_ECC_CMD2_READ_COL_CHG_END(x) ((x) << 16) +#define PL35X_SMC_ECC_CMD2_READ_COL_CHG_END_VALID(x) ((x) << 24) +/* SMC ECC value registers (RO) */ +#define PL35X_SMC_ECC_VALUE(x) (0x418 + (4 * (x))) +#define PL35X_SMC_ECC_VALUE_IS_CORRECTABLE(x) ((x) & BIT(27)) +#define PL35X_SMC_ECC_VALUE_HAS_FAILED(x) ((x) & BIT(28)) +#define PL35X_SMC_ECC_VALUE_IS_VALID(x) ((x) & BIT(30)) + +/* NAND AXI interface */ +#define PL35X_SMC_CMD_PHASE 0 +#define PL35X_SMC_CMD_PHASE_CMD0(x) ((x) << 3) +#define PL35X_SMC_CMD_PHASE_CMD1(x) ((x) << 11) +#define PL35X_SMC_CMD_PHASE_CMD1_VALID BIT(20) +#define PL35X_SMC_CMD_PHASE_ADDR(pos, x) ((x) << (8 * (pos))) +#define PL35X_SMC_CMD_PHASE_NADDRS(x) ((x) << 21) +#define PL35X_SMC_DATA_PHASE BIT(19) +#define PL35X_SMC_DATA_PHASE_ECC_LAST BIT(10) +#define PL35X_SMC_DATA_PHASE_CLEAR_CS BIT(21) + +#define PL35X_NAND_MAX_CS 1 +#define PL35X_NAND_LAST_XFER_SZ 4 +#define TO_CYCLES(ps, period_ns) (DIV_ROUND_UP((ps) / 1000, period_ns)) + +#define PL35X_NAND_ECC_BITS_MASK 0xFFF +#define PL35X_NAND_ECC_BYTE_OFF_MASK 0x1FF +#define PL35X_NAND_ECC_BIT_OFF_MASK 0x7 + +struct pl35x_nand_timings { + unsigned int t_rc:4; + unsigned int t_wc:4; + unsigned int t_rea:3; + unsigned int t_wp:3; + unsigned int t_clr:3; + unsigned int t_ar:3; + unsigned int t_rr:4; + unsigned int rsvd:8; +}; + +struct pl35x_nand { + struct list_head node; + struct nand_chip chip; + unsigned int cs; + unsigned int addr_cycles; + u32 ecc_cfg; + u32 timings; +}; + +/** + * struct pl35x_nandc - NAND flash controller driver structure + * @dev: Kernel device + * @conf_regs: SMC configuration registers for command phase + * @io_regs: NAND data registers for data phase + * @controller: Core NAND controller structure + * @chip: NAND chip information structure + * @selected_chip: NAND chip currently selected by the controller + * @assigned_cs: List of assigned CS + * @ecc_buf: Temporary buffer to extract ECC bytes + */ +struct pl35x_nandc { + struct device *dev; + void __iomem *conf_regs; + void __iomem *io_regs; + struct nand_controller controller; + struct list_head chips; + struct nand_chip *selected_chip; + unsigned long assigned_cs; + u8 *ecc_buf; +}; + +static inline struct pl35x_nandc *to_pl35x_nandc(struct nand_controller *ctrl) +{ + return container_of(ctrl, struct pl35x_nandc, controller); +} + +static inline struct pl35x_nand *to_pl35x_nand(struct nand_chip *chip) +{ + return container_of(chip, struct pl35x_nand, chip); +} + +static int pl35x_ecc_ooblayout16_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + + if (section >= chip->ecc.steps) + return -ERANGE; + + oobregion->offset = (section * chip->ecc.bytes); + oobregion->length = chip->ecc.bytes; + + return 0; +} + +static int pl35x_ecc_ooblayout16_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + + if (section >= chip->ecc.steps) + return -ERANGE; + + oobregion->offset = (section * chip->ecc.bytes) + 8; + oobregion->length = 8; + + return 0; +} + +static const struct mtd_ooblayout_ops pl35x_ecc_ooblayout16_ops = { + .ecc = pl35x_ecc_ooblayout16_ecc, + .free = pl35x_ecc_ooblayout16_free, +}; + +/* Generic flash bbt decriptors */ +static u8 bbt_pattern[] = { 'B', 'b', 't', '0' }; +static u8 mirror_pattern[] = { '1', 't', 'b', 'B' }; + +static struct nand_bbt_descr bbt_main_descr = { + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, + .offs = 4, + .len = 4, + .veroffs = 20, + .maxblocks = 4, + .pattern = bbt_pattern +}; + +static struct nand_bbt_descr bbt_mirror_descr = { + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, + .offs = 4, + .len = 4, + .veroffs = 20, + .maxblocks = 4, + .pattern = mirror_pattern +}; + +static void pl35x_smc_update_regs(struct pl35x_nandc *nfc) +{ + writel(PL35X_SMC_DIRECT_CMD_NAND_CS | + PL35X_SMC_DIRECT_CMD_UPD_REGS, + nfc->conf_regs + PL35X_SMC_DIRECT_CMD); +} + +static int pl35x_smc_set_buswidth(struct pl35x_nandc *nfc, unsigned int bw) +{ + if (bw != PL35X_SMC_OPMODE_BW_8 && bw != PL35X_SMC_OPMODE_BW_16) + return -EINVAL; + + writel(bw, nfc->conf_regs + PL35X_SMC_OPMODE); + pl35x_smc_update_regs(nfc); + + return 0; +} + +static void pl35x_smc_clear_irq(struct pl35x_nandc *nfc) +{ + writel(PL35X_SMC_MEMC_CFG_CLR_INT_CLR_1, + nfc->conf_regs + PL35X_SMC_MEMC_CFG_CLR); +} + +static int pl35x_smc_wait_for_irq(struct pl35x_nandc *nfc) +{ + u32 reg; + int ret; + + ret = readl_poll_timeout(nfc->conf_regs + PL35X_SMC_MEMC_STATUS, reg, + reg & PL35X_SMC_MEMC_STATUS_RAW_INT_STATUS1, + 10, 1000000); + if (ret) + dev_err(nfc->dev, + "Timeout polling on NAND controller interrupt (0x%x)\n", + reg); + + pl35x_smc_clear_irq(nfc); + + return ret; +} + +static int pl35x_smc_wait_for_ecc_done(struct pl35x_nandc *nfc) +{ + u32 reg; + int ret; + + ret = readl_poll_timeout(nfc->conf_regs + PL35X_SMC_ECC_STATUS, reg, + !(reg & PL35X_SMC_ECC_STATUS_ECC_BUSY), + 10, 1000000); + if (ret) + dev_err(nfc->dev, + "Timeout polling on ECC controller interrupt\n"); + + return ret; +} + +static int pl35x_smc_set_ecc_mode(struct pl35x_nandc *nfc, + struct nand_chip *chip, + unsigned int mode) +{ + struct pl35x_nand *plnand; + u32 ecc_cfg; + + ecc_cfg = readl(nfc->conf_regs + PL35X_SMC_ECC_CFG); + ecc_cfg &= ~PL35X_SMC_ECC_CFG_MODE_MASK; + ecc_cfg |= mode; + writel(ecc_cfg, nfc->conf_regs + PL35X_SMC_ECC_CFG); + + if (chip) { + plnand = to_pl35x_nand(chip); + plnand->ecc_cfg = ecc_cfg; + } + + if (mode != PL35X_SMC_ECC_CFG_MODE_BYPASS) + return pl35x_smc_wait_for_ecc_done(nfc); + + return 0; +} + +static void pl35x_smc_force_byte_access(struct nand_chip *chip, + bool force_8bit) +{ + struct pl35x_nandc *nfc = to_pl35x_nandc(chip->controller); + int ret; + + if (!(chip->options & NAND_BUSWIDTH_16)) + return; + + if (force_8bit) + ret = pl35x_smc_set_buswidth(nfc, PL35X_SMC_OPMODE_BW_8); + else + ret = pl35x_smc_set_buswidth(nfc, PL35X_SMC_OPMODE_BW_16); + + if (ret) + dev_err(nfc->dev, "Error in Buswidth\n"); +} + +static void pl35x_nand_select_target(struct nand_chip *chip, + unsigned int die_nr) +{ + struct pl35x_nandc *nfc = to_pl35x_nandc(chip->controller); + struct pl35x_nand *plnand = to_pl35x_nand(chip); + + if (chip == nfc->selected_chip) + return; + + /* Setup the timings */ + writel(plnand->timings, nfc->conf_regs + PL35X_SMC_CYCLES); + pl35x_smc_update_regs(nfc); + + /* Configure the ECC engine */ + writel(plnand->ecc_cfg, nfc->conf_regs + PL35X_SMC_ECC_CFG); + + nfc->selected_chip = chip; +} + +static void pl35x_nand_read_data_op(struct nand_chip *chip, u8 *in, + unsigned int len, bool force_8bit, + unsigned int flags, unsigned int last_flags) +{ + struct pl35x_nandc *nfc = to_pl35x_nandc(chip->controller); + unsigned int buf_end = len / 4; + unsigned int in_start = round_down(len, 4); + unsigned int data_phase_addr; + u32 *buf32 = (u32 *)in; + u8 *buf8 = (u8 *)in; + int i; + + if (force_8bit) + pl35x_smc_force_byte_access(chip, true); + + for (i = 0; i < buf_end; i++) { + data_phase_addr = PL35X_SMC_DATA_PHASE + flags; + if (i + 1 == buf_end) + data_phase_addr = PL35X_SMC_DATA_PHASE + last_flags; + + buf32[i] = readl(nfc->io_regs + data_phase_addr); + } + + /* No working extra flags on unaligned data accesses */ + for (i = in_start; i < len; i++) + buf8[i] = readb(nfc->io_regs + PL35X_SMC_DATA_PHASE); + + if (force_8bit) + pl35x_smc_force_byte_access(chip, false); +} + +static void pl35x_nand_write_data_op(struct nand_chip *chip, const u8 *out, + int len, bool force_8bit, + unsigned int flags, + unsigned int last_flags) +{ + struct pl35x_nandc *nfc = to_pl35x_nandc(chip->controller); + unsigned int buf_end = len / 4; + unsigned int in_start = round_down(len, 4); + const u32 *buf32 = (const u32 *)out; + const u8 *buf8 = (const u8 *)out; + unsigned int data_phase_addr; + int i; + + if (force_8bit) + pl35x_smc_force_byte_access(chip, true); + + for (i = 0; i < buf_end; i++) { + data_phase_addr = PL35X_SMC_DATA_PHASE + flags; + if (i + 1 == buf_end) + data_phase_addr = PL35X_SMC_DATA_PHASE + last_flags; + + writel(buf32[i], nfc->io_regs + data_phase_addr); + } + + /* No working extra flags on unaligned data accesses */ + for (i = in_start; i < len; i++) + writeb(buf8[i], nfc->io_regs + PL35X_SMC_DATA_PHASE); + + if (force_8bit) + pl35x_smc_force_byte_access(chip, false); +} + +static int pl35x_nand_correct_data(struct pl35x_nandc *nfc, unsigned char *buf, + unsigned char *read_ecc, + unsigned char *calc_ecc) +{ + unsigned short ecc_odd, ecc_even, read_ecc_lower, read_ecc_upper; + unsigned short calc_ecc_lower, calc_ecc_upper; + unsigned short byte_addr, bit_addr; + + read_ecc_lower = (read_ecc[0] | (read_ecc[1] << 8)) & + PL35X_NAND_ECC_BITS_MASK; + read_ecc_upper = ((read_ecc[1] >> 4) | (read_ecc[2] << 4)) & + PL35X_NAND_ECC_BITS_MASK; + + calc_ecc_lower = (calc_ecc[0] | (calc_ecc[1] << 8)) & + PL35X_NAND_ECC_BITS_MASK; + calc_ecc_upper = ((calc_ecc[1] >> 4) | (calc_ecc[2] << 4)) & + PL35X_NAND_ECC_BITS_MASK; + + ecc_odd = read_ecc_lower ^ calc_ecc_lower; + ecc_even = read_ecc_upper ^ calc_ecc_upper; + + /* No error */ + if (likely(!ecc_odd && !ecc_even)) + return 0; + + /* One error in the main data; to be corrected */ + if (ecc_odd == (~ecc_even & PL35X_NAND_ECC_BITS_MASK)) { + /* Bits [11:3] of error code give the byte offset */ + byte_addr = (ecc_odd >> 3) & PL35X_NAND_ECC_BYTE_OFF_MASK; + /* Bits [2:0] of error code give the bit offset */ + bit_addr = ecc_odd & PL35X_NAND_ECC_BIT_OFF_MASK; + /* Toggle the faulty bit */ + buf[byte_addr] ^= (BIT(bit_addr)); + + return 1; + } + + /* One error in the ECC data; no action needed */ + if (hweight32(ecc_odd | ecc_even) == 1) + return 1; + + return -EBADMSG; +} + +static void pl35x_nand_ecc_reg_to_array(struct nand_chip *chip, u32 ecc_reg, + u8 *ecc_array) +{ + u32 ecc_value = ~ecc_reg; + unsigned int ecc_byte; + + for (ecc_byte = 0; ecc_byte < chip->ecc.bytes; ecc_byte++) + ecc_array[ecc_byte] = ecc_value >> (8 * ecc_byte); +} + +static int pl35x_nand_read_eccbytes(struct pl35x_nandc *nfc, + struct nand_chip *chip, u8 *read_ecc) +{ + u32 ecc_value; + int chunk; + + for (chunk = 0; chunk < chip->ecc.steps; + chunk++, read_ecc += chip->ecc.bytes) { + ecc_value = readl(nfc->conf_regs + PL35X_SMC_ECC_VALUE(chunk)); + if (!PL35X_SMC_ECC_VALUE_IS_VALID(ecc_value)) + return -EINVAL; + + pl35x_nand_ecc_reg_to_array(chip, ecc_value, read_ecc); + } + + return 0; +} + +static int pl35x_nand_recover_data_hwecc(struct pl35x_nandc *nfc, + struct nand_chip *chip, u8 *data, + u8 *read_ecc) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + unsigned int max_bitflips = 0, chunk; + u8 calc_ecc[3]; + u32 ecc_value; + int stats; + + for (chunk = 0; chunk < chip->ecc.steps; + chunk++, data += chip->ecc.size, read_ecc += chip->ecc.bytes) { + /* Read ECC value for each chunk */ + ecc_value = readl(nfc->conf_regs + PL35X_SMC_ECC_VALUE(chunk)); + + if (!PL35X_SMC_ECC_VALUE_IS_VALID(ecc_value)) + return -EINVAL; + + if (PL35X_SMC_ECC_VALUE_HAS_FAILED(ecc_value)) { + mtd->ecc_stats.failed++; + continue; + } + + pl35x_nand_ecc_reg_to_array(chip, ecc_value, calc_ecc); + stats = pl35x_nand_correct_data(nfc, data, read_ecc, calc_ecc); + if (stats < 0) { + mtd->ecc_stats.failed++; + } else { + mtd->ecc_stats.corrected += stats; + max_bitflips = max_t(unsigned int, max_bitflips, stats); + } + } + + return max_bitflips; +} + +static int pl35x_nand_write_page_hwecc(struct nand_chip *chip, + const u8 *buf, int oob_required, + int page) +{ + struct pl35x_nandc *nfc = to_pl35x_nandc(chip->controller); + struct pl35x_nand *plnand = to_pl35x_nand(chip); + struct mtd_info *mtd = nand_to_mtd(chip); + unsigned int first_row = (mtd->writesize <= 512) ? 1 : 2; + unsigned int nrows = plnand->addr_cycles; + u32 addr1 = 0, addr2 = 0, row; + u32 cmd_addr; + int i, ret; + + ret = pl35x_smc_set_ecc_mode(nfc, chip, PL35X_SMC_ECC_CFG_MODE_APB); + if (ret) + return ret; + + cmd_addr = PL35X_SMC_CMD_PHASE | + PL35X_SMC_CMD_PHASE_NADDRS(plnand->addr_cycles) | + PL35X_SMC_CMD_PHASE_CMD0(NAND_CMD_SEQIN); + + for (i = 0, row = first_row; row < nrows; i++, row++) { + u8 addr = page >> ((i * 8) & 0xFF); + + if (row < 4) + addr1 |= PL35X_SMC_CMD_PHASE_ADDR(row, addr); + else + addr2 |= PL35X_SMC_CMD_PHASE_ADDR(row - 4, addr); + } + + /* Send the command and address cycles */ + writel(addr1, nfc->io_regs + cmd_addr); + if (plnand->addr_cycles > 4) + writel(addr2, nfc->io_regs + cmd_addr); + + /* Write the data with the engine enabled */ + pl35x_nand_write_data_op(chip, buf, mtd->writesize, false, + 0, PL35X_SMC_DATA_PHASE_ECC_LAST); + ret = pl35x_smc_wait_for_ecc_done(nfc); + if (ret) + goto disable_ecc_engine; + + /* Copy the HW calculated ECC bytes in the OOB buffer */ + ret = pl35x_nand_read_eccbytes(nfc, chip, nfc->ecc_buf); + if (ret) + goto disable_ecc_engine; + + if (!oob_required) + memset(chip->oob_poi, 0xFF, mtd->oobsize); + + ret = mtd_ooblayout_set_eccbytes(mtd, nfc->ecc_buf, chip->oob_poi, + 0, chip->ecc.total); + if (ret) + goto disable_ecc_engine; + + /* Write the spare area with ECC bytes */ + pl35x_nand_write_data_op(chip, chip->oob_poi, mtd->oobsize, false, 0, + PL35X_SMC_CMD_PHASE_CMD1(NAND_CMD_PAGEPROG) | + PL35X_SMC_CMD_PHASE_CMD1_VALID | + PL35X_SMC_DATA_PHASE_CLEAR_CS); + ret = pl35x_smc_wait_for_irq(nfc); + if (ret) + goto disable_ecc_engine; + +disable_ecc_engine: + pl35x_smc_set_ecc_mode(nfc, chip, PL35X_SMC_ECC_CFG_MODE_BYPASS); + + return ret; +} + +/* + * This functions reads data and checks the data integrity by comparing hardware + * generated ECC values and read ECC values from spare area. + * + * There is a limitation with SMC controller: ECC_LAST must be set on the + * last data access to tell the ECC engine not to expect any further data. + * In practice, this implies to shrink the last data transfert by eg. 4 bytes, + * and doing a last 4-byte transfer with the additional bit set. The last block + * should be aligned with the end of an ECC block. Because of this limitation, + * it is not possible to use the core routines. + */ +static int pl35x_nand_read_page_hwecc(struct nand_chip *chip, + u8 *buf, int oob_required, int page) +{ + const struct nand_sdr_timings *sdr = + nand_get_sdr_timings(nand_get_interface_config(chip)); + struct pl35x_nandc *nfc = to_pl35x_nandc(chip->controller); + struct pl35x_nand *plnand = to_pl35x_nand(chip); + struct mtd_info *mtd = nand_to_mtd(chip); + unsigned int first_row = (mtd->writesize <= 512) ? 1 : 2; + unsigned int nrows = plnand->addr_cycles; + unsigned int addr1 = 0, addr2 = 0, row; + u32 cmd_addr; + int i, ret; + + ret = pl35x_smc_set_ecc_mode(nfc, chip, PL35X_SMC_ECC_CFG_MODE_APB); + if (ret) + return ret; + + cmd_addr = PL35X_SMC_CMD_PHASE | + PL35X_SMC_CMD_PHASE_NADDRS(plnand->addr_cycles) | + PL35X_SMC_CMD_PHASE_CMD0(NAND_CMD_READ0) | + PL35X_SMC_CMD_PHASE_CMD1(NAND_CMD_READSTART) | + PL35X_SMC_CMD_PHASE_CMD1_VALID; + + for (i = 0, row = first_row; row < nrows; i++, row++) { + u8 addr = page >> ((i * 8) & 0xFF); + + if (row < 4) + addr1 |= PL35X_SMC_CMD_PHASE_ADDR(row, addr); + else + addr2 |= PL35X_SMC_CMD_PHASE_ADDR(row - 4, addr); + } + + /* Send the command and address cycles */ + writel(addr1, nfc->io_regs + cmd_addr); + if (plnand->addr_cycles > 4) + writel(addr2, nfc->io_regs + cmd_addr); + + /* Wait the data to be available in the NAND cache */ + ndelay(PSEC_TO_NSEC(sdr->tRR_min)); + ret = pl35x_smc_wait_for_irq(nfc); + if (ret) + goto disable_ecc_engine; + + /* Retrieve the raw data with the engine enabled */ + pl35x_nand_read_data_op(chip, buf, mtd->writesize, false, + 0, PL35X_SMC_DATA_PHASE_ECC_LAST); + ret = pl35x_smc_wait_for_ecc_done(nfc); + if (ret) + goto disable_ecc_engine; + + /* Retrieve the stored ECC bytes */ + pl35x_nand_read_data_op(chip, chip->oob_poi, mtd->oobsize, false, + 0, PL35X_SMC_DATA_PHASE_CLEAR_CS); + ret = mtd_ooblayout_get_eccbytes(mtd, nfc->ecc_buf, chip->oob_poi, 0, + chip->ecc.total); + if (ret) + goto disable_ecc_engine; + + pl35x_smc_set_ecc_mode(nfc, chip, PL35X_SMC_ECC_CFG_MODE_BYPASS); + + /* Correct the data and report failures */ + return pl35x_nand_recover_data_hwecc(nfc, chip, buf, nfc->ecc_buf); + +disable_ecc_engine: + pl35x_smc_set_ecc_mode(nfc, chip, PL35X_SMC_ECC_CFG_MODE_BYPASS); + + return ret; +} + +static int pl35x_nand_exec_op(struct nand_chip *chip, + const struct nand_subop *subop) +{ + struct pl35x_nandc *nfc = to_pl35x_nandc(chip->controller); + const struct nand_op_instr *instr, *data_instr = NULL; + unsigned int rdy_tim_ms = 0, naddrs = 0, cmds = 0, last_flags = 0; + u32 addr1 = 0, addr2 = 0, cmd0 = 0, cmd1 = 0, cmd_addr = 0; + unsigned int op_id, len, offset, rdy_del_ns; + int last_instr_type = -1; + bool cmd1_valid = false; + const u8 *addrs; + int i, ret; + + for (op_id = 0; op_id < subop->ninstrs; op_id++) { + instr = &subop->instrs[op_id]; + + switch (instr->type) { + case NAND_OP_CMD_INSTR: + if (!cmds) { + cmd0 = PL35X_SMC_CMD_PHASE_CMD0(instr->ctx.cmd.opcode); + } else { + cmd1 = PL35X_SMC_CMD_PHASE_CMD1(instr->ctx.cmd.opcode); + if (last_instr_type != NAND_OP_DATA_OUT_INSTR) + cmd1_valid = true; + } + cmds++; + break; + + case NAND_OP_ADDR_INSTR: + offset = nand_subop_get_addr_start_off(subop, op_id); + naddrs = nand_subop_get_num_addr_cyc(subop, op_id); + addrs = &instr->ctx.addr.addrs[offset]; + cmd_addr |= PL35X_SMC_CMD_PHASE_NADDRS(naddrs); + + for (i = offset; i < naddrs; i++) { + if (i < 4) + addr1 |= PL35X_SMC_CMD_PHASE_ADDR(i, addrs[i]); + else + addr2 |= PL35X_SMC_CMD_PHASE_ADDR(i - 4, addrs[i]); + } + break; + + case NAND_OP_DATA_IN_INSTR: + case NAND_OP_DATA_OUT_INSTR: + data_instr = instr; + len = nand_subop_get_data_len(subop, op_id); + break; + + case NAND_OP_WAITRDY_INSTR: + rdy_tim_ms = instr->ctx.waitrdy.timeout_ms; + rdy_del_ns = instr->delay_ns; + break; + } + + last_instr_type = instr->type; + } + + /* Command phase */ + cmd_addr |= PL35X_SMC_CMD_PHASE | cmd0 | cmd1 | + (cmd1_valid ? PL35X_SMC_CMD_PHASE_CMD1_VALID : 0); + writel(addr1, nfc->io_regs + cmd_addr); + if (naddrs > 4) + writel(addr2, nfc->io_regs + cmd_addr); + + /* Data phase */ + if (data_instr && data_instr->type == NAND_OP_DATA_OUT_INSTR) { + last_flags = PL35X_SMC_DATA_PHASE_CLEAR_CS; + if (cmds == 2) + last_flags |= cmd1 | PL35X_SMC_CMD_PHASE_CMD1_VALID; + + pl35x_nand_write_data_op(chip, data_instr->ctx.data.buf.out, + len, data_instr->ctx.data.force_8bit, + 0, last_flags); + } + + if (rdy_tim_ms) { + ndelay(rdy_del_ns); + ret = pl35x_smc_wait_for_irq(nfc); + if (ret) + return ret; + } + + if (data_instr && data_instr->type == NAND_OP_DATA_IN_INSTR) + pl35x_nand_read_data_op(chip, data_instr->ctx.data.buf.in, + len, data_instr->ctx.data.force_8bit, + 0, PL35X_SMC_DATA_PHASE_CLEAR_CS); + + return 0; +} + +static const struct nand_op_parser pl35x_nandc_op_parser = NAND_OP_PARSER( + NAND_OP_PARSER_PATTERN(pl35x_nand_exec_op, + NAND_OP_PARSER_PAT_CMD_ELEM(true), + NAND_OP_PARSER_PAT_ADDR_ELEM(true, 7), + NAND_OP_PARSER_PAT_CMD_ELEM(true), + NAND_OP_PARSER_PAT_WAITRDY_ELEM(true), + NAND_OP_PARSER_PAT_DATA_IN_ELEM(true, 2112)), + NAND_OP_PARSER_PATTERN(pl35x_nand_exec_op, + NAND_OP_PARSER_PAT_CMD_ELEM(false), + NAND_OP_PARSER_PAT_ADDR_ELEM(false, 7), + NAND_OP_PARSER_PAT_DATA_OUT_ELEM(false, 2112), + NAND_OP_PARSER_PAT_CMD_ELEM(false), + NAND_OP_PARSER_PAT_WAITRDY_ELEM(true)), + NAND_OP_PARSER_PATTERN(pl35x_nand_exec_op, + NAND_OP_PARSER_PAT_CMD_ELEM(false), + NAND_OP_PARSER_PAT_ADDR_ELEM(false, 7), + NAND_OP_PARSER_PAT_DATA_OUT_ELEM(false, 2112), + NAND_OP_PARSER_PAT_CMD_ELEM(true), + NAND_OP_PARSER_PAT_WAITRDY_ELEM(true)), + ); + +static int pl35x_nfc_exec_op(struct nand_chip *chip, + const struct nand_operation *op, + bool check_only) +{ + if (!check_only) + pl35x_nand_select_target(chip, op->cs); + + return nand_op_parser_exec_op(chip, &pl35x_nandc_op_parser, + op, check_only); +} + +static int pl35x_nfc_setup_interface(struct nand_chip *chip, int cs, + const struct nand_interface_config *conf) +{ + struct pl35x_nandc *nfc = to_pl35x_nandc(chip->controller); + struct pl35x_nand *plnand = to_pl35x_nand(chip); + struct pl35x_nand_timings tmgs = {}; + const struct nand_sdr_timings *sdr; + unsigned int period_ns, val; + struct clk *mclk; + + sdr = nand_get_sdr_timings(conf); + if (IS_ERR(sdr)) + return PTR_ERR(sdr); + + mclk = of_clk_get_by_name(nfc->dev->parent->of_node, "memclk"); + if (IS_ERR(mclk)) { + dev_err(nfc->dev, "Failed to retrieve SMC memclk\n"); + return PTR_ERR(mclk); + } + + /* + * SDR timings are given in pico-seconds while NFC timings must be + * expressed in NAND controller clock cycles. We use the TO_CYCLE() + * macro to convert from one to the other. + */ + period_ns = NSEC_PER_SEC / clk_get_rate(mclk); + + /* + * PL35X SMC needs one extra read cycle in SDR Mode 5. This is not + * written anywhere in the datasheet but is an empirical observation. + */ + val = TO_CYCLES(sdr->tRC_min, period_ns); + if (sdr->tRC_min <= 20000) + val++; + + tmgs.t_rc = val; + if (tmgs.t_rc != val || tmgs.t_rc < 2) + return -EINVAL; + + val = TO_CYCLES(sdr->tWC_min, period_ns); + tmgs.t_wc = val; + if (tmgs.t_wc != val || tmgs.t_wc < 2) + return -EINVAL; + + /* + * For all SDR modes, PL35X SMC needs tREA_max being 1, + * this is also an empirical result. + */ + tmgs.t_rea = 1; + + val = TO_CYCLES(sdr->tWP_min, period_ns); + tmgs.t_wp = val; + if (tmgs.t_wp != val || tmgs.t_wp < 1) + return -EINVAL; + + val = TO_CYCLES(sdr->tCLR_min, period_ns); + tmgs.t_clr = val; + if (tmgs.t_clr != val) + return -EINVAL; + + val = TO_CYCLES(sdr->tAR_min, period_ns); + tmgs.t_ar = val; + if (tmgs.t_ar != val) + return -EINVAL; + + val = TO_CYCLES(sdr->tRR_min, period_ns); + tmgs.t_rr = val; + if (tmgs.t_rr != val) + return -EINVAL; + + if (cs == NAND_DATA_IFACE_CHECK_ONLY) + return 0; + + plnand->timings = PL35X_SMC_NAND_TRC_CYCLES(tmgs.t_rc) | + PL35X_SMC_NAND_TWC_CYCLES(tmgs.t_wc) | + PL35X_SMC_NAND_TREA_CYCLES(tmgs.t_rea) | + PL35X_SMC_NAND_TWP_CYCLES(tmgs.t_wp) | + PL35X_SMC_NAND_TCLR_CYCLES(tmgs.t_clr) | + PL35X_SMC_NAND_TAR_CYCLES(tmgs.t_ar) | + PL35X_SMC_NAND_TRR_CYCLES(tmgs.t_rr); + + return 0; +} + +static void pl35x_smc_set_ecc_pg_size(struct pl35x_nandc *nfc, + struct nand_chip *chip, + unsigned int pg_sz) +{ + struct pl35x_nand *plnand = to_pl35x_nand(chip); + u32 sz; + + switch (pg_sz) { + case SZ_512: + sz = 1; + break; + case SZ_1K: + sz = 2; + break; + case SZ_2K: + sz = 3; + break; + default: + sz = 0; + break; + } + + plnand->ecc_cfg = readl(nfc->conf_regs + PL35X_SMC_ECC_CFG); + plnand->ecc_cfg &= ~PL35X_SMC_ECC_CFG_PGSIZE_MASK; + plnand->ecc_cfg |= sz; + writel(plnand->ecc_cfg, nfc->conf_regs + PL35X_SMC_ECC_CFG); +} + +static int pl35x_nand_init_hw_ecc_controller(struct pl35x_nandc *nfc, + struct nand_chip *chip) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + int ret = 0; + + if (mtd->writesize < SZ_512 || mtd->writesize > SZ_2K) { + dev_err(nfc->dev, + "The hardware ECC engine is limited to pages up to 2kiB\n"); + return -EOPNOTSUPP; + } + + chip->ecc.strength = 1; + chip->ecc.bytes = 3; + chip->ecc.size = SZ_512; + chip->ecc.steps = mtd->writesize / chip->ecc.size; + chip->ecc.read_page = pl35x_nand_read_page_hwecc; + chip->ecc.write_page = pl35x_nand_write_page_hwecc; + chip->ecc.write_page_raw = nand_monolithic_write_page_raw; + pl35x_smc_set_ecc_pg_size(nfc, chip, mtd->writesize); + + nfc->ecc_buf = devm_kmalloc(nfc->dev, chip->ecc.bytes * chip->ecc.steps, + GFP_KERNEL); + if (!nfc->ecc_buf) + return -ENOMEM; + + switch (mtd->oobsize) { + case 16: + /* Legacy Xilinx layout */ + mtd_set_ooblayout(mtd, &pl35x_ecc_ooblayout16_ops); + chip->bbt_options |= NAND_BBT_NO_OOB_BBM; + break; + case 64: + mtd_set_ooblayout(mtd, nand_get_large_page_ooblayout()); + break; + default: + dev_err(nfc->dev, "Unsupported OOB size\n"); + return -EOPNOTSUPP; + } + + return ret; +} + +static int pl35x_nand_attach_chip(struct nand_chip *chip) +{ + const struct nand_ecc_props *requirements = + nanddev_get_ecc_requirements(&chip->base); + struct pl35x_nandc *nfc = to_pl35x_nandc(chip->controller); + struct pl35x_nand *plnand = to_pl35x_nand(chip); + struct mtd_info *mtd = nand_to_mtd(chip); + int ret; + + if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_NONE && + (!chip->ecc.size || !chip->ecc.strength)) { + if (requirements->step_size && requirements->strength) { + chip->ecc.size = requirements->step_size; + chip->ecc.strength = requirements->strength; + } else { + dev_info(nfc->dev, + "No minimum ECC strength, using 1b/512B\n"); + chip->ecc.size = 512; + chip->ecc.strength = 1; + } + } + + if (mtd->writesize <= SZ_512) + plnand->addr_cycles = 1; + else + plnand->addr_cycles = 2; + + if (chip->options & NAND_ROW_ADDR_3) + plnand->addr_cycles += 3; + else + plnand->addr_cycles += 2; + + switch (chip->ecc.engine_type) { + case NAND_ECC_ENGINE_TYPE_ON_DIE: + /* Keep these legacy BBT descriptors for ON_DIE situations */ + chip->bbt_td = &bbt_main_descr; + chip->bbt_md = &bbt_mirror_descr; + fallthrough; + case NAND_ECC_ENGINE_TYPE_NONE: + case NAND_ECC_ENGINE_TYPE_SOFT: + break; + case NAND_ECC_ENGINE_TYPE_ON_HOST: + ret = pl35x_nand_init_hw_ecc_controller(nfc, chip); + if (ret) + return ret; + break; + default: + dev_err(nfc->dev, "Unsupported ECC mode: %d\n", + chip->ecc.engine_type); + return -EINVAL; + } + + return 0; +} + +static const struct nand_controller_ops pl35x_nandc_ops = { + .attach_chip = pl35x_nand_attach_chip, + .exec_op = pl35x_nfc_exec_op, + .setup_interface = pl35x_nfc_setup_interface, +}; + +static int pl35x_nand_reset_state(struct pl35x_nandc *nfc) +{ + int ret; + + /* Disable interrupts and clear their status */ + writel(PL35X_SMC_MEMC_CFG_CLR_INT_CLR_1 | + PL35X_SMC_MEMC_CFG_CLR_ECC_INT_DIS_1 | + PL35X_SMC_MEMC_CFG_CLR_INT_DIS_1, + nfc->conf_regs + PL35X_SMC_MEMC_CFG_CLR); + + /* Set default bus width to 8-bit */ + ret = pl35x_smc_set_buswidth(nfc, PL35X_SMC_OPMODE_BW_8); + if (ret) + return ret; + + /* Ensure the ECC controller is bypassed by default */ + ret = pl35x_smc_set_ecc_mode(nfc, NULL, PL35X_SMC_ECC_CFG_MODE_BYPASS); + if (ret) + return ret; + + /* + * Configure the commands that the ECC block uses to detect the + * operations it should start/end. + */ + writel(PL35X_SMC_ECC_CMD1_WRITE(NAND_CMD_SEQIN) | + PL35X_SMC_ECC_CMD1_READ(NAND_CMD_READ0) | + PL35X_SMC_ECC_CMD1_READ_END(NAND_CMD_READSTART) | + PL35X_SMC_ECC_CMD1_READ_END_VALID(NAND_CMD_READ1), + nfc->conf_regs + PL35X_SMC_ECC_CMD1); + writel(PL35X_SMC_ECC_CMD2_WRITE_COL_CHG(NAND_CMD_RNDIN) | + PL35X_SMC_ECC_CMD2_READ_COL_CHG(NAND_CMD_RNDOUT) | + PL35X_SMC_ECC_CMD2_READ_COL_CHG_END(NAND_CMD_RNDOUTSTART) | + PL35X_SMC_ECC_CMD2_READ_COL_CHG_END_VALID(NAND_CMD_READ1), + nfc->conf_regs + PL35X_SMC_ECC_CMD2); + + return 0; +} + +static int pl35x_nand_chip_init(struct pl35x_nandc *nfc, + struct device_node *np) +{ + struct pl35x_nand *plnand; + struct nand_chip *chip; + struct mtd_info *mtd; + int cs, ret; + + plnand = devm_kzalloc(nfc->dev, sizeof(*plnand), GFP_KERNEL); + if (!plnand) + return -ENOMEM; + + ret = of_property_read_u32(np, "reg", &cs); + if (ret) + return ret; + + if (cs >= PL35X_NAND_MAX_CS) { + dev_err(nfc->dev, "Wrong CS %d\n", cs); + return -EINVAL; + } + + if (test_and_set_bit(cs, &nfc->assigned_cs)) { + dev_err(nfc->dev, "Already assigned CS %d\n", cs); + return -EINVAL; + } + + plnand->cs = cs; + + chip = &plnand->chip; + chip->options = NAND_BUSWIDTH_AUTO | NAND_USES_DMA | NAND_NO_SUBPAGE_WRITE; + chip->bbt_options = NAND_BBT_USE_FLASH; + chip->controller = &nfc->controller; + mtd = nand_to_mtd(chip); + mtd->dev.parent = nfc->dev; + nand_set_flash_node(chip, nfc->dev->of_node); + if (!mtd->name) { + mtd->name = devm_kasprintf(nfc->dev, GFP_KERNEL, + "%s", PL35X_NANDC_DRIVER_NAME); + if (!mtd->name) { + dev_err(nfc->dev, "Failed to allocate mtd->name\n"); + return -ENOMEM; + } + } + + ret = nand_scan(chip, 1); + if (ret) + return ret; + + ret = mtd_device_register(mtd, NULL, 0); + if (ret) { + nand_cleanup(chip); + return ret; + } + + list_add_tail(&plnand->node, &nfc->chips); + + return ret; +} + +static void pl35x_nand_chips_cleanup(struct pl35x_nandc *nfc) +{ + struct pl35x_nand *plnand, *tmp; + struct nand_chip *chip; + int ret; + + list_for_each_entry_safe(plnand, tmp, &nfc->chips, node) { + chip = &plnand->chip; + ret = mtd_device_unregister(nand_to_mtd(chip)); + WARN_ON(ret); + nand_cleanup(chip); + list_del(&plnand->node); + } +} + +static int pl35x_nand_chips_init(struct pl35x_nandc *nfc) +{ + struct device_node *np = nfc->dev->of_node, *nand_np; + int nchips = of_get_child_count(np); + int ret; + + if (!nchips || nchips > PL35X_NAND_MAX_CS) { + dev_err(nfc->dev, "Incorrect number of NAND chips (%d)\n", + nchips); + return -EINVAL; + } + + for_each_child_of_node(np, nand_np) { + ret = pl35x_nand_chip_init(nfc, nand_np); + if (ret) { + of_node_put(nand_np); + pl35x_nand_chips_cleanup(nfc); + break; + } + } + + return ret; +} + +static int pl35x_nand_probe(struct platform_device *pdev) +{ + struct device *smc_dev = pdev->dev.parent; + struct amba_device *smc_amba = to_amba_device(smc_dev); + struct pl35x_nandc *nfc; + u32 ret; + + nfc = devm_kzalloc(&pdev->dev, sizeof(*nfc), GFP_KERNEL); + if (!nfc) + return -ENOMEM; + + nfc->dev = &pdev->dev; + nand_controller_init(&nfc->controller); + nfc->controller.ops = &pl35x_nandc_ops; + INIT_LIST_HEAD(&nfc->chips); + + nfc->conf_regs = devm_ioremap_resource(&smc_amba->dev, &smc_amba->res); + if (IS_ERR(nfc->conf_regs)) + return PTR_ERR(nfc->conf_regs); + + nfc->io_regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(nfc->io_regs)) + return PTR_ERR(nfc->io_regs); + + ret = pl35x_nand_reset_state(nfc); + if (ret) + return ret; + + ret = pl35x_nand_chips_init(nfc); + if (ret) + return ret; + + platform_set_drvdata(pdev, nfc); + + return 0; +} + +static int pl35x_nand_remove(struct platform_device *pdev) +{ + struct pl35x_nandc *nfc = platform_get_drvdata(pdev); + + pl35x_nand_chips_cleanup(nfc); + + return 0; +} + +static const struct of_device_id pl35x_nand_of_match[] = { + { .compatible = "arm,pl353-nand-r2p1" }, + {}, +}; +MODULE_DEVICE_TABLE(of, pl35x_nand_of_match); + +static struct platform_driver pl35x_nandc_driver = { + .probe = pl35x_nand_probe, + .remove = pl35x_nand_remove, + .driver = { + .name = PL35X_NANDC_DRIVER_NAME, + .of_match_table = pl35x_nand_of_match, + }, +}; +module_platform_driver(pl35x_nandc_driver); + +MODULE_AUTHOR("Xilinx, Inc."); +MODULE_ALIAS("platform:" PL35X_NANDC_DRIVER_NAME); +MODULE_DESCRIPTION("ARM PL35X NAND controller driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index a64fb6ce915d..ef0badea4f41 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -734,6 +734,7 @@ static void update_rw_regs(struct qcom_nand_host *host, int num_cw, bool read, i { struct nand_chip *chip = &host->chip; u32 cmd, cfg0, cfg1, ecc_bch_cfg; + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); if (read) { if (host->use_ecc) @@ -762,7 +763,8 @@ static void update_rw_regs(struct qcom_nand_host *host, int num_cw, bool read, i nandc_set_reg(chip, NAND_DEV0_CFG0, cfg0); nandc_set_reg(chip, NAND_DEV0_CFG1, cfg1); nandc_set_reg(chip, NAND_DEV0_ECC_CFG, ecc_bch_cfg); - nandc_set_reg(chip, NAND_EBI2_ECC_BUF_CFG, host->ecc_buf_cfg); + if (!nandc->props->qpic_v2) + nandc_set_reg(chip, NAND_EBI2_ECC_BUF_CFG, host->ecc_buf_cfg); nandc_set_reg(chip, NAND_FLASH_STATUS, host->clrflashstatus); nandc_set_reg(chip, NAND_READ_STATUS, host->clrreadstatus); nandc_set_reg(chip, NAND_EXEC_CMD, 1); @@ -1133,7 +1135,8 @@ static void config_nand_page_read(struct nand_chip *chip) write_reg_dma(nandc, NAND_ADDR0, 2, 0); write_reg_dma(nandc, NAND_DEV0_CFG0, 3, 0); - write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1, 0); + if (!nandc->props->qpic_v2) + write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1, 0); write_reg_dma(nandc, NAND_ERASED_CW_DETECT_CFG, 1, 0); write_reg_dma(nandc, NAND_ERASED_CW_DETECT_CFG, 1, NAND_ERASED_CW_SET | NAND_BAM_NEXT_SGL); @@ -1191,8 +1194,9 @@ static void config_nand_page_write(struct nand_chip *chip) write_reg_dma(nandc, NAND_ADDR0, 2, 0); write_reg_dma(nandc, NAND_DEV0_CFG0, 3, 0); - write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1, - NAND_BAM_NEXT_SGL); + if (!nandc->props->qpic_v2) + write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1, + NAND_BAM_NEXT_SGL); } /* @@ -1248,7 +1252,8 @@ static int nandc_param(struct qcom_nand_host *host) | 2 << WR_RD_BSY_GAP | 0 << WIDE_FLASH | 1 << DEV0_CFG1_ECC_DISABLE); - nandc_set_reg(chip, NAND_EBI2_ECC_BUF_CFG, 1 << ECC_CFG_ECC_DISABLE); + if (!nandc->props->qpic_v2) + nandc_set_reg(chip, NAND_EBI2_ECC_BUF_CFG, 1 << ECC_CFG_ECC_DISABLE); /* configure CMD1 and VLD for ONFI param probing in QPIC v1 */ if (!nandc->props->qpic_v2) { @@ -1850,8 +1855,7 @@ static int parse_read_errors(struct qcom_nand_host *host, u8 *data_buf, * ERASED_CW bits are set. */ if (host->bch_enabled) { - erased = (erased_cw & ERASED_CW) == ERASED_CW ? - true : false; + erased = (erased_cw & ERASED_CW) == ERASED_CW; /* * For RS ECC, HW reports the erased CW by placing * special characters at certain offsets in the buffer. @@ -2689,7 +2693,8 @@ static int qcom_nand_attach_chip(struct nand_chip *chip) | ecc_mode << ECC_MODE | host->ecc_bytes_hw << ECC_PARITY_SIZE_BYTES_BCH; - host->ecc_buf_cfg = 0x203 << NUM_STEPS; + if (!nandc->props->qpic_v2) + host->ecc_buf_cfg = 0x203 << NUM_STEPS; host->clrflashstatus = FS_READY_BSY_N; host->clrreadstatus = 0xc0; @@ -2882,7 +2887,7 @@ static int qcom_nandc_setup(struct qcom_nand_controller *nandc) return 0; } -static const char * const probes[] = { "qcomsmem", NULL }; +static const char * const probes[] = { "cmdlinepart", "ofpart", "qcomsmem", NULL }; static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc, struct qcom_nand_host *host, diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c index ebe859ca49cb..ed0cf732d20e 100644 --- a/drivers/mtd/nand/raw/r852.c +++ b/drivers/mtd/nand/raw/r852.c @@ -583,8 +583,8 @@ static void r852_update_card_detect(struct r852_device *dev) r852_write_reg(dev, R852_CARD_IRQ_ENABLE, card_detect_reg); } -static ssize_t r852_media_type_show(struct device *sys_dev, - struct device_attribute *attr, char *buf) +static ssize_t media_type_show(struct device *sys_dev, + struct device_attribute *attr, char *buf) { struct mtd_info *mtd = container_of(sys_dev, struct mtd_info, dev); struct r852_device *dev = r852_get_dev(mtd); @@ -593,8 +593,7 @@ static ssize_t r852_media_type_show(struct device *sys_dev, strcpy(buf, data); return strlen(data); } - -static DEVICE_ATTR(media_type, S_IRUGO, r852_media_type_show, NULL); +static DEVICE_ATTR_RO(media_type); /* Detect properties of card in slot */ diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 923a9e236fcf..ea953e31933e 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1972,10 +1972,8 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, sunxi_nand = devm_kzalloc(dev, struct_size(sunxi_nand, sels, nsels), GFP_KERNEL); - if (!sunxi_nand) { - dev_err(dev, "could not allocate chip\n"); + if (!sunxi_nand) return -ENOMEM; - } sunxi_nand->nsels = nsels; diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 3131fae0c715..446ba8d43fbc 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -138,20 +138,12 @@ int spinand_select_target(struct spinand_device *spinand, unsigned int target) return 0; } -static int spinand_init_cfg_cache(struct spinand_device *spinand) +static int spinand_read_cfg(struct spinand_device *spinand) { struct nand_device *nand = spinand_to_nand(spinand); - struct device *dev = &spinand->spimem->spi->dev; unsigned int target; int ret; - spinand->cfg_cache = devm_kcalloc(dev, - nand->memorg.ntargets, - sizeof(*spinand->cfg_cache), - GFP_KERNEL); - if (!spinand->cfg_cache) - return -ENOMEM; - for (target = 0; target < nand->memorg.ntargets; target++) { ret = spinand_select_target(spinand, target); if (ret) @@ -170,6 +162,21 @@ static int spinand_init_cfg_cache(struct spinand_device *spinand) return 0; } +static int spinand_init_cfg_cache(struct spinand_device *spinand) +{ + struct nand_device *nand = spinand_to_nand(spinand); + struct device *dev = &spinand->spimem->spi->dev; + + spinand->cfg_cache = devm_kcalloc(dev, + nand->memorg.ntargets, + sizeof(*spinand->cfg_cache), + GFP_KERNEL); + if (!spinand->cfg_cache) + return -ENOMEM; + + return 0; +} + static int spinand_init_quad_enable(struct spinand_device *spinand) { bool enable = false; @@ -290,6 +297,8 @@ static int spinand_ondie_ecc_finish_io_req(struct nand_device *nand, { struct spinand_ondie_ecc_conf *engine_conf = nand->ecc.ctx.priv; struct spinand_device *spinand = nand_to_spinand(nand); + struct mtd_info *mtd = spinand_to_mtd(spinand); + int ret; if (req->mode == MTD_OPS_RAW) return 0; @@ -299,7 +308,13 @@ static int spinand_ondie_ecc_finish_io_req(struct nand_device *nand, return 0; /* Finish a page write: check the status, report errors/bitflips */ - return spinand_check_ecc_status(spinand, engine_conf->status); + ret = spinand_check_ecc_status(spinand, engine_conf->status); + if (ret == -EBADMSG) + mtd->ecc_stats.failed++; + else if (ret > 0) + mtd->ecc_stats.corrected += ret; + + return ret; } static struct nand_ecc_engine_ops spinand_ondie_ecc_engine_ops = { @@ -635,13 +650,10 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from, if (ret < 0 && ret != -EBADMSG) break; - if (ret == -EBADMSG) { + if (ret == -EBADMSG) ecc_failed = true; - mtd->ecc_stats.failed++; - } else { - mtd->ecc_stats.corrected += ret; + else max_bitflips = max_t(unsigned int, max_bitflips, ret); - } ret = 0; ops->retlen += iter.req.datalen; @@ -1093,12 +1105,71 @@ static int spinand_detect(struct spinand_device *spinand) return 0; } +static int spinand_init_flash(struct spinand_device *spinand) +{ + struct device *dev = &spinand->spimem->spi->dev; + struct nand_device *nand = spinand_to_nand(spinand); + int ret, i; + + ret = spinand_read_cfg(spinand); + if (ret) + return ret; + + ret = spinand_init_quad_enable(spinand); + if (ret) + return ret; + + ret = spinand_upd_cfg(spinand, CFG_OTP_ENABLE, 0); + if (ret) + return ret; + + ret = spinand_manufacturer_init(spinand); + if (ret) { + dev_err(dev, + "Failed to initialize the SPI NAND chip (err = %d)\n", + ret); + return ret; + } + + /* After power up, all blocks are locked, so unlock them here. */ + for (i = 0; i < nand->memorg.ntargets; i++) { + ret = spinand_select_target(spinand, i); + if (ret) + break; + + ret = spinand_lock_block(spinand, BL_ALL_UNLOCKED); + if (ret) + break; + } + + if (ret) + spinand_manufacturer_cleanup(spinand); + + return ret; +} + +static void spinand_mtd_resume(struct mtd_info *mtd) +{ + struct spinand_device *spinand = mtd_to_spinand(mtd); + int ret; + + ret = spinand_reset_op(spinand); + if (ret) + return; + + ret = spinand_init_flash(spinand); + if (ret) + return; + + spinand_ecc_enable(spinand, false); +} + static int spinand_init(struct spinand_device *spinand) { struct device *dev = &spinand->spimem->spi->dev; struct mtd_info *mtd = spinand_to_mtd(spinand); struct nand_device *nand = mtd_to_nanddev(mtd); - int ret, i; + int ret; /* * We need a scratch buffer because the spi_mem interface requires that @@ -1131,22 +1202,10 @@ static int spinand_init(struct spinand_device *spinand) if (ret) goto err_free_bufs; - ret = spinand_init_quad_enable(spinand); + ret = spinand_init_flash(spinand); if (ret) goto err_free_bufs; - ret = spinand_upd_cfg(spinand, CFG_OTP_ENABLE, 0); - if (ret) - goto err_free_bufs; - - ret = spinand_manufacturer_init(spinand); - if (ret) { - dev_err(dev, - "Failed to initialize the SPI NAND chip (err = %d)\n", - ret); - goto err_free_bufs; - } - ret = spinand_create_dirmaps(spinand); if (ret) { dev_err(dev, @@ -1155,17 +1214,6 @@ static int spinand_init(struct spinand_device *spinand) goto err_manuf_cleanup; } - /* After power up, all blocks are locked, so unlock them here. */ - for (i = 0; i < nand->memorg.ntargets; i++) { - ret = spinand_select_target(spinand, i); - if (ret) - goto err_manuf_cleanup; - - ret = spinand_lock_block(spinand, BL_ALL_UNLOCKED); - if (ret) - goto err_manuf_cleanup; - } - ret = nanddev_init(nand, &spinand_ops, THIS_MODULE); if (ret) goto err_manuf_cleanup; @@ -1186,6 +1234,7 @@ static int spinand_init(struct spinand_device *spinand) mtd->_block_isreserved = spinand_mtd_block_isreserved; mtd->_erase = spinand_mtd_erase; mtd->_max_bad_blocks = nanddev_mtd_max_bad_blocks; + mtd->_resume = spinand_mtd_resume; if (nand->ecc.engine) { ret = mtd_ooblayout_count_freebytes(mtd); diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c index 6701aaa21a49..a9890350db02 100644 --- a/drivers/mtd/nand/spi/macronix.c +++ b/drivers/mtd/nand/spi/macronix.c @@ -186,6 +186,118 @@ static const struct spinand_info macronix_spinand_table[] = { 0 /*SPINAND_HAS_QE_BIT*/, SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, mx35lf1ge4ab_ecc_get_status)), + + SPINAND_INFO("MX35LF2G14AC", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x20), + NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX35UF4G24AD", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb5), + NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 2, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX35UF4GE4AD", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb7), + NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX35UF2G14AC", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa0), + NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX35UF2G24AD", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa4), + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX35UF2GE4AD", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa6), + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX35UF2GE4AC", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa2), + NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX35UF1G14AC", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x90), + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX35UF1G24AD", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x94), + NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX35UF1GE4AD", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x96), + NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX35UF1GE4AC", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x92), + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + }; static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = { diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index bcd0094f172d..913db0dd6a8d 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c @@ -619,7 +619,6 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) return BLOCK_NIL; } //printk("Restarting scan\n"); - lastEUN = BLOCK_NIL; continue; } diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c index 444a77bb7692..75e86ed3e678 100644 --- a/drivers/mtd/nftlmount.c +++ b/drivers/mtd/nftlmount.c @@ -188,17 +188,14 @@ device is already correct. /* memory alloc */ nftl->EUNtable = kmalloc_array(nftl->nb_blocks, sizeof(u16), GFP_KERNEL); - if (!nftl->EUNtable) { - printk(KERN_NOTICE "NFTL: allocation of EUNtable failed\n"); + if (!nftl->EUNtable) return -ENOMEM; - } nftl->ReplUnitTable = kmalloc_array(nftl->nb_blocks, sizeof(u16), GFP_KERNEL); if (!nftl->ReplUnitTable) { kfree(nftl->EUNtable); - printk(KERN_NOTICE "NFTL: allocation of ReplUnitTable failed\n"); return -ENOMEM; } @@ -269,7 +266,7 @@ static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int buf = kmalloc(SECTORSIZE + mtd->oobsize, GFP_KERNEL); if (!buf) - return -1; + return -ENOMEM; ret = -1; for (i = 0; i < len; i += SECTORSIZE) { diff --git a/drivers/mtd/parsers/Kconfig b/drivers/mtd/parsers/Kconfig index 9babe678c41b..337ea8b9a4c3 100644 --- a/drivers/mtd/parsers/Kconfig +++ b/drivers/mtd/parsers/Kconfig @@ -115,7 +115,7 @@ config MTD_AFS_PARTS config MTD_PARSER_TRX tristate "Parser for TRX format partitions" - depends on MTD && (BCM47XX || ARCH_BCM_5301X || COMPILE_TEST) + depends on MTD && (BCM47XX || ARCH_BCM_5301X || ARCH_MEDIATEK || COMPILE_TEST) help TRX is a firmware format used by Broadcom on their devices. It may contain up to 3/4 partitions (depending on the version). diff --git a/drivers/mtd/parsers/parser_trx.c b/drivers/mtd/parsers/parser_trx.c index 8541182134d4..4814cf218e17 100644 --- a/drivers/mtd/parsers/parser_trx.c +++ b/drivers/mtd/parsers/parser_trx.c @@ -51,13 +51,20 @@ static int parser_trx_parse(struct mtd_info *mtd, const struct mtd_partition **pparts, struct mtd_part_parser_data *data) { + struct device_node *np = mtd_get_of_node(mtd); struct mtd_partition *parts; struct mtd_partition *part; struct trx_header trx; size_t bytes_read; uint8_t curr_part = 0, i = 0; + uint32_t trx_magic = TRX_MAGIC; int err; + /* Get different magic from device tree if specified */ + err = of_property_read_u32(np, "brcm,trx-magic", &trx_magic); + if (err != 0 && err != -EINVAL) + pr_err("failed to parse \"brcm,trx-magic\" DT attribute, using default: %d\n", err); + parts = kcalloc(TRX_PARSER_MAX_PARTS, sizeof(struct mtd_partition), GFP_KERNEL); if (!parts) @@ -70,7 +77,7 @@ static int parser_trx_parse(struct mtd_info *mtd, return err; } - if (trx.magic != TRX_MAGIC) { + if (trx.magic != trx_magic) { kfree(parts); return -ENOENT; } diff --git a/drivers/mtd/parsers/qcomsmempart.c b/drivers/mtd/parsers/qcomsmempart.c index d9083308f6ba..06a818cd2433 100644 --- a/drivers/mtd/parsers/qcomsmempart.c +++ b/drivers/mtd/parsers/qcomsmempart.c @@ -159,6 +159,15 @@ out_free_parts: return ret; } +static void parse_qcomsmem_cleanup(const struct mtd_partition *pparts, + int nr_parts) +{ + int i; + + for (i = 0; i < nr_parts; i++) + kfree(pparts[i].name); +} + static const struct of_device_id qcomsmem_of_match_table[] = { { .compatible = "qcom,smem-part" }, {}, @@ -167,6 +176,7 @@ MODULE_DEVICE_TABLE(of, qcomsmem_of_match_table); static struct mtd_part_parser mtd_parser_qcomsmem = { .parse_fn = parse_qcomsmem_part, + .cleanup = parse_qcomsmem_cleanup, .name = "qcomsmem", .of_match_table = qcomsmem_of_match_table, }; diff --git a/drivers/mtd/parsers/redboot.c b/drivers/mtd/parsers/redboot.c index 91146bdc4713..feb44a573d44 100644 --- a/drivers/mtd/parsers/redboot.c +++ b/drivers/mtd/parsers/redboot.c @@ -17,15 +17,15 @@ #include <linux/module.h> struct fis_image_desc { - unsigned char name[16]; // Null terminated name - uint32_t flash_base; // Address within FLASH of image - uint32_t mem_base; // Address in memory where it executes - uint32_t size; // Length of image - uint32_t entry_point; // Execution entry point - uint32_t data_length; // Length of actual data - unsigned char _pad[256-(16+7*sizeof(uint32_t))]; - uint32_t desc_cksum; // Checksum over image descriptor - uint32_t file_cksum; // Checksum over image data + unsigned char name[16]; // Null terminated name + u32 flash_base; // Address within FLASH of image + u32 mem_base; // Address in memory where it executes + u32 size; // Length of image + u32 entry_point; // Execution entry point + u32 data_length; // Length of actual data + unsigned char _pad[256 - (16 + 7 * sizeof(u32))]; + u32 desc_cksum; // Checksum over image descriptor + u32 file_cksum; // Checksum over image data }; struct fis_list { @@ -45,6 +45,7 @@ static inline int redboot_checksum(struct fis_image_desc *img) static void parse_redboot_of(struct mtd_info *master) { struct device_node *np; + struct device_node *npart; u32 dirblock; int ret; @@ -52,7 +53,11 @@ static void parse_redboot_of(struct mtd_info *master) if (!np) return; - ret = of_property_read_u32(np, "fis-index-block", &dirblock); + npart = of_get_child_by_name(np, "partitions"); + if (!npart) + return; + + ret = of_property_read_u32(npart, "fis-index-block", &dirblock); if (ret) return; @@ -85,12 +90,12 @@ static int parse_redboot_partitions(struct mtd_info *master, parse_redboot_of(master); - if ( directory < 0 ) { + if (directory < 0) { offset = master->size + directory * master->erasesize; while (mtd_block_isbad(master, offset)) { if (!offset) { - nogood: - printk(KERN_NOTICE "Failed to find a non-bad block to check for RedBoot partition table\n"); +nogood: + pr_notice("Failed to find a non-bad block to check for RedBoot partition table\n"); return -EIO; } offset -= master->erasesize; @@ -108,8 +113,8 @@ static int parse_redboot_partitions(struct mtd_info *master, if (!buf) return -ENOMEM; - printk(KERN_NOTICE "Searching for RedBoot partition table in %s at offset 0x%lx\n", - master->name, offset); + pr_notice("Searching for RedBoot partition table in %s at offset 0x%lx\n", + master->name, offset); ret = mtd_read(master, offset, master->erasesize, &retlen, (void *)buf); @@ -145,14 +150,13 @@ static int parse_redboot_partitions(struct mtd_info *master, && swab32(buf[i].size) < master->erasesize)) { int j; /* Update numslots based on actual FIS directory size */ - numslots = swab32(buf[i].size) / sizeof (struct fis_image_desc); + numslots = swab32(buf[i].size) / sizeof(struct fis_image_desc); for (j = 0; j < numslots; ++j) { - /* A single 0xff denotes a deleted entry. * Two of them in a row is the end of the table. */ if (buf[j].name[0] == 0xff) { - if (buf[j].name[1] == 0xff) { + if (buf[j].name[1] == 0xff) { break; } else { continue; @@ -179,8 +183,8 @@ static int parse_redboot_partitions(struct mtd_info *master, } if (i == numslots) { /* Didn't find it */ - printk(KERN_NOTICE "No RedBoot partition table detected in %s\n", - master->name); + pr_notice("No RedBoot partition table detected in %s\n", + master->name); ret = 0; goto out; } @@ -199,7 +203,7 @@ static int parse_redboot_partitions(struct mtd_info *master, break; new_fl = kmalloc(sizeof(struct fis_list), GFP_KERNEL); - namelen += strlen(buf[i].name)+1; + namelen += strlen(buf[i].name) + 1; if (!new_fl) { ret = -ENOMEM; goto out; @@ -208,13 +212,13 @@ static int parse_redboot_partitions(struct mtd_info *master, if (data && data->origin) buf[i].flash_base -= data->origin; else - buf[i].flash_base &= master->size-1; + buf[i].flash_base &= master->size - 1; /* I'm sure the JFFS2 code has done me permanent damage. * I now think the following is _normal_ */ prev = &fl; - while(*prev && (*prev)->img->flash_base < new_fl->img->flash_base) + while (*prev && (*prev)->img->flash_base < new_fl->img->flash_base) prev = &(*prev)->next; new_fl->next = *prev; *prev = new_fl; @@ -234,7 +238,7 @@ static int parse_redboot_partitions(struct mtd_info *master, } } #endif - parts = kzalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL); + parts = kzalloc(sizeof(*parts) * nrparts + nulllen + namelen, GFP_KERNEL); if (!parts) { ret = -ENOMEM; @@ -243,23 +247,22 @@ static int parse_redboot_partitions(struct mtd_info *master, nullname = (char *)&parts[nrparts]; #ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED - if (nulllen > 0) { + if (nulllen > 0) strcpy(nullname, nullstring); - } #endif names = nullname + nulllen; - i=0; + i = 0; #ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED if (fl->img->flash_base) { - parts[0].name = nullname; - parts[0].size = fl->img->flash_base; - parts[0].offset = 0; + parts[0].name = nullname; + parts[0].size = fl->img->flash_base; + parts[0].offset = 0; i++; } #endif - for ( ; i<nrparts; i++) { + for ( ; i < nrparts; i++) { parts[i].size = fl->img->size; parts[i].offset = fl->img->flash_base; parts[i].name = names; @@ -267,17 +270,17 @@ static int parse_redboot_partitions(struct mtd_info *master, strcpy(names, fl->img->name); #ifdef CONFIG_MTD_REDBOOT_PARTS_READONLY if (!memcmp(names, "RedBoot", 8) || - !memcmp(names, "RedBoot config", 15) || - !memcmp(names, "FIS directory", 14)) { + !memcmp(names, "RedBoot config", 15) || + !memcmp(names, "FIS directory", 14)) { parts[i].mask_flags = MTD_WRITEABLE; } #endif - names += strlen(names)+1; + names += strlen(names) + 1; #ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED - if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) { + if (fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) { i++; - parts[i].offset = parts[i-1].size + parts[i-1].offset; + parts[i].offset = parts[i - 1].size + parts[i - 1].offset; parts[i].size = fl->next->img->flash_base - parts[i].offset; parts[i].name = nullname; } @@ -291,6 +294,7 @@ static int parse_redboot_partitions(struct mtd_info *master, out: while (fl) { struct fis_list *old = fl; + fl = fl->next; kfree(old); } diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c index cce3bf6f99b4..6e0d5ce9b010 100644 --- a/drivers/mtd/rfd_ftl.c +++ b/drivers/mtd/rfd_ftl.c @@ -192,11 +192,8 @@ static int scan_header(struct partition *part) part->sector_map = vmalloc(array_size(sizeof(u_long), part->sector_count)); - if (!part->sector_map) { - printk(KERN_ERR PREFIX "'%s': unable to allocate memory for " - "sector map", part->mbd.mtd->name); + if (!part->sector_map) goto err; - } for (i=0; i<part->sector_count; i++) part->sector_map[i] = -1; diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c index 4d1ae25507ab..0cff2cda1b5a 100644 --- a/drivers/mtd/sm_ftl.c +++ b/drivers/mtd/sm_ftl.c @@ -265,7 +265,8 @@ static int sm_read_sector(struct sm_ftl *ftl, again: if (try++) { /* Avoid infinite recursion on CIS reads, sm_recheck_media - won't help anyway */ + * won't help anyway + */ if (zone == 0 && block == ftl->cis_block && boffset == ftl->cis_boffset) return ret; @@ -276,7 +277,8 @@ again: } /* Unfortunately, oob read will _always_ succeed, - despite card removal..... */ + * despite card removal..... + */ ret = mtd_read_oob(mtd, sm_mkoffset(ftl, zone, block, boffset), &ops); /* Test for unknown errors */ @@ -411,9 +413,10 @@ restart: /* If write fails. try to erase the block */ /* This is safe, because we never write in blocks - that contain valuable data. - This is intended to repair block that are marked - as erased, but that isn't fully erased*/ + * that contain valuable data. + * This is intended to repair block that are marked + * as erased, but that isn't fully erased + */ if (sm_erase_block(ftl, zone, block, 0)) return -EIO; @@ -448,7 +451,8 @@ static void sm_mark_block_bad(struct sm_ftl *ftl, int zone, int block) /* We aren't checking the return value, because we don't care */ /* This also fails on fake xD cards, but I guess these won't expose - any bad blocks till fail completely */ + * any bad blocks till fail completely + */ for (boffset = 0; boffset < ftl->block_size; boffset += SM_SECTOR_SIZE) sm_write_sector(ftl, zone, block, boffset, NULL, &oob); } @@ -505,7 +509,8 @@ static int sm_check_block(struct sm_ftl *ftl, int zone, int block) /* First just check that block doesn't look fishy */ /* Only blocks that are valid or are sliced in two parts, are - accepted */ + * accepted + */ for (boffset = 0; boffset < ftl->block_size; boffset += SM_SECTOR_SIZE) { @@ -554,7 +559,8 @@ static const uint8_t cis_signature[] = { 0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02, 0xDF, 0x01, 0x20 }; /* Find out media parameters. - * This ideally has to be based on nand id, but for now device size is enough */ + * This ideally has to be based on nand id, but for now device size is enough + */ static int sm_get_media_info(struct sm_ftl *ftl, struct mtd_info *mtd) { int i; @@ -607,7 +613,8 @@ static int sm_get_media_info(struct sm_ftl *ftl, struct mtd_info *mtd) } /* Minimum xD size is 16MiB. Also, all xD cards have standard zone - sizes. SmartMedia cards exist up to 128 MiB and have same layout*/ + * sizes. SmartMedia cards exist up to 128 MiB and have same layout + */ if (size_in_megs >= 16) { ftl->zone_count = size_in_megs / 16; ftl->zone_size = 1024; @@ -782,7 +789,8 @@ static int sm_init_zone(struct sm_ftl *ftl, int zone_num) } /* Test to see if block is erased. It is enough to test - first sector, because erase happens in one shot */ + * first sector, because erase happens in one shot + */ if (sm_block_erased(&oob)) { kfifo_in(&zone->free_sectors, (unsigned char *)&block, 2); @@ -792,7 +800,8 @@ static int sm_init_zone(struct sm_ftl *ftl, int zone_num) /* If block is marked as bad, skip it */ /* This assumes we can trust first sector*/ /* However the way the block valid status is defined, ensures - very low probability of failure here */ + * very low probability of failure here + */ if (!sm_block_valid(&oob)) { dbg("PH %04d <-> <marked bad>", block); continue; @@ -803,7 +812,8 @@ static int sm_init_zone(struct sm_ftl *ftl, int zone_num) /* Invalid LBA means that block is damaged. */ /* We can try to erase it, or mark it as bad, but - lets leave that to recovery application */ + * lets leave that to recovery application + */ if (lba == -2 || lba >= ftl->max_lba) { dbg("PH %04d <-> LBA %04d(bad)", block, lba); continue; @@ -811,7 +821,8 @@ static int sm_init_zone(struct sm_ftl *ftl, int zone_num) /* If there is no collision, - just put the sector in the FTL table */ + * just put the sector in the FTL table + */ if (zone->lba_to_phys_table[lba] < 0) { dbg_verbose("PH %04d <-> LBA %04d", block, lba); zone->lba_to_phys_table[lba] = block; @@ -834,9 +845,9 @@ static int sm_init_zone(struct sm_ftl *ftl, int zone_num) } /* If both blocks are valid and share same LBA, it means that - they hold different versions of same data. It not - known which is more recent, thus just erase one of them - */ + * they hold different versions of same data. It not + * known which is more recent, thus just erase one of them + */ sm_printk("both blocks are valid, erasing the later"); sm_erase_block(ftl, zone_num, block, 1); } @@ -845,7 +856,8 @@ static int sm_init_zone(struct sm_ftl *ftl, int zone_num) zone->initialized = 1; /* No free sectors, means that the zone is heavily damaged, write won't - work, but it can still can be (partially) read */ + * work, but it can still can be (partially) read + */ if (!kfifo_len(&zone->free_sectors)) { sm_printk("no free blocks in zone %d", zone_num); return 0; @@ -952,8 +964,9 @@ restart: /* If there are no spare blocks, */ /* we could still continue by erasing/writing the current block, - but for such worn out media it doesn't worth the trouble, - and the dangers */ + * but for such worn out media it doesn't worth the trouble, + * and the dangers + */ if (kfifo_out(&zone->free_sectors, (unsigned char *)&write_sector, 2) != 2) { dbg("no free sectors for write!"); diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile index 136f245c91dc..6b904e439372 100644 --- a/drivers/mtd/spi-nor/Makefile +++ b/drivers/mtd/spi-nor/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 -spi-nor-objs := core.o sfdp.o swp.o otp.o +spi-nor-objs := core.o sfdp.o swp.o otp.o sysfs.o spi-nor-objs += atmel.o spi-nor-objs += catalyst.o spi-nor-objs += eon.o diff --git a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c b/drivers/mtd/spi-nor/controllers/intel-spi-pci.c index 825610a2e9dc..1bc53b8bb88a 100644 --- a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c +++ b/drivers/mtd/spi-nor/controllers/intel-spi-pci.c @@ -74,6 +74,7 @@ static const struct pci_device_id intel_spi_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x4b24), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0x4da4), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0x51a4), (unsigned long)&cnl_info }, + { PCI_VDEVICE(INTEL, 0x54a4), (unsigned long)&cnl_info }, { PCI_VDEVICE(INTEL, 0x7aa4), (unsigned long)&cnl_info }, { PCI_VDEVICE(INTEL, 0xa0a4), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0xa1a4), (unsigned long)&bxt_info }, diff --git a/drivers/mtd/spi-nor/controllers/nxp-spifi.c b/drivers/mtd/spi-nor/controllers/nxp-spifi.c index 5703e8313980..2635c80231bb 100644 --- a/drivers/mtd/spi-nor/controllers/nxp-spifi.c +++ b/drivers/mtd/spi-nor/controllers/nxp-spifi.c @@ -326,7 +326,7 @@ static int nxp_spifi_setup_flash(struct nxp_spifi *spifi, ctrl |= SPIFI_CTRL_DUAL; } - switch (mode & (SPI_CPHA | SPI_CPOL)) { + switch (mode & SPI_MODE_X_MASK) { case SPI_MODE_0: ctrl &= ~SPIFI_CTRL_MODE3; break; diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index bd2c7717eb10..cc08bd707378 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -1318,7 +1318,7 @@ static u32 spi_nor_convert_addr(struct spi_nor *nor, loff_t addr) /* * Initiate the erasure of a single sector */ -static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr) +int spi_nor_erase_sector(struct spi_nor *nor, u32 addr) { int i; @@ -1411,9 +1411,7 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map, continue; spi_nor_div_by_erase_size(erase, addr, &rem); - if (rem) - continue; - else + if (!rem) return erase; } @@ -2839,6 +2837,21 @@ static int spi_nor_init(struct spi_nor *nor) return 0; } +/** + * spi_nor_soft_reset() - Perform a software reset + * @nor: pointer to 'struct spi_nor' + * + * Performs a "Soft Reset and Enter Default Protocol Mode" sequence which resets + * the device to its power-on-reset state. This is useful when the software has + * made some changes to device (volatile) registers and needs to reset it before + * shutting down, for example. + * + * Not every flash supports this sequence. The same set of opcodes might be used + * for some other operation on a flash that does not support this. Support for + * this sequence can be discovered via SFDP in the BFPT table. + * + * Return: 0 on success, -errno otherwise. + */ static void spi_nor_soft_reset(struct spi_nor *nor) { struct spi_mem_op op; @@ -3444,6 +3457,7 @@ static struct spi_mem_driver spi_nor_driver = { .driver = { .name = "spi-nor", .of_match_table = spi_nor_of_table, + .dev_groups = spi_nor_sysfs_groups, }, .id_table = spi_nor_dev_ids, }, diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h index 28a2e0be97a3..3348e1dd1445 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -207,6 +207,7 @@ struct spi_nor_otp_organization { * @read: read from the SPI NOR OTP area. * @write: write to the SPI NOR OTP area. * @lock: lock an OTP region. + * @erase: erase an OTP region. * @is_locked: check if an OTP region of the SPI NOR is locked. */ struct spi_nor_otp_ops { @@ -214,6 +215,7 @@ struct spi_nor_otp_ops { int (*write)(struct spi_nor *nor, loff_t addr, size_t len, const u8 *buf); int (*lock)(struct spi_nor *nor, unsigned int region); + int (*erase)(struct spi_nor *nor, loff_t addr); int (*is_locked)(struct spi_nor *nor, unsigned int region); }; @@ -459,6 +461,16 @@ struct spi_nor_manufacturer { const struct spi_nor_fixups *fixups; }; +/** + * struct sfdp - SFDP data + * @num_dwords: number of entries in the dwords array + * @dwords: array of double words of the SFDP data + */ +struct sfdp { + size_t num_dwords; + u32 *dwords; +}; + /* Manufacturer drivers. */ extern const struct spi_nor_manufacturer spi_nor_atmel; extern const struct spi_nor_manufacturer spi_nor_catalyst; @@ -478,6 +490,8 @@ extern const struct spi_nor_manufacturer spi_nor_winbond; extern const struct spi_nor_manufacturer spi_nor_xilinx; extern const struct spi_nor_manufacturer spi_nor_xmc; +extern const struct attribute_group *spi_nor_sysfs_groups[]; + void spi_nor_spimem_setup_op(const struct spi_nor *nor, struct spi_mem_op *op, const enum spi_nor_protocol proto); @@ -503,10 +517,12 @@ ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len, u8 *buf); ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len, const u8 *buf); +int spi_nor_erase_sector(struct spi_nor *nor, u32 addr); int spi_nor_otp_read_secr(struct spi_nor *nor, loff_t addr, size_t len, u8 *buf); int spi_nor_otp_write_secr(struct spi_nor *nor, loff_t addr, size_t len, const u8 *buf); +int spi_nor_otp_erase_secr(struct spi_nor *nor, loff_t addr); int spi_nor_otp_lock_sr2(struct spi_nor *nor, unsigned int region); int spi_nor_otp_is_locked_sr2(struct spi_nor *nor, unsigned int region); diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c index 42c2cf31702e..27498ed0cc0d 100644 --- a/drivers/mtd/spi-nor/macronix.c +++ b/drivers/mtd/spi-nor/macronix.c @@ -49,7 +49,8 @@ static const struct flash_info macronix_parts[] = { { "mx25u4035", INFO(0xc22533, 0, 64 * 1024, 8, SECT_4K) }, { "mx25u8035", INFO(0xc22534, 0, 64 * 1024, 16, SECT_4K) }, { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) }, - { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, SECT_4K) }, + { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, SECT_4K | + SPI_NOR_HAS_LOCK | SPI_NOR_4BIT_BP) }, { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, { "mx25r1635f", INFO(0xc22815, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | @@ -72,7 +73,7 @@ static const struct flash_info macronix_parts[] = { SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, - { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, + { "mx66l51235f", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024, diff --git a/drivers/mtd/spi-nor/otp.c b/drivers/mtd/spi-nor/otp.c index fcf38d260345..983e40b19134 100644 --- a/drivers/mtd/spi-nor/otp.c +++ b/drivers/mtd/spi-nor/otp.c @@ -15,14 +15,21 @@ #define spi_nor_otp_n_regions(nor) ((nor)->params->otp.org->n_regions) /** - * spi_nor_otp_read_secr() - read OTP data + * spi_nor_otp_read_secr() - read security register * @nor: pointer to 'struct spi_nor' - * @from: offset to read from + * @addr: offset to read from * @len: number of bytes to read * @buf: pointer to dst buffer * - * Read OTP data from one region by using the SPINOR_OP_RSECR commands. This - * method is used on GigaDevice and Winbond flashes. + * Read a security register by using the SPINOR_OP_RSECR commands. + * + * In Winbond/GigaDevice datasheets the term "security register" stands for + * an one-time-programmable memory area, consisting of multiple bytes (usually + * 256). Thus one "security register" maps to one OTP region. + * + * This method is used on GigaDevice and Winbond flashes. + * + * Please note, the read must not span multiple registers. * * Return: number of bytes read successfully, -errno otherwise */ @@ -40,7 +47,6 @@ int spi_nor_otp_read_secr(struct spi_nor *nor, loff_t addr, size_t len, u8 *buf) rdesc = nor->dirmap.rdesc; nor->read_opcode = SPINOR_OP_RSECR; - nor->addr_width = 3; nor->read_dummy = 8; nor->read_proto = SNOR_PROTO_1_1_1; nor->dirmap.rdesc = NULL; @@ -57,16 +63,20 @@ int spi_nor_otp_read_secr(struct spi_nor *nor, loff_t addr, size_t len, u8 *buf) } /** - * spi_nor_otp_write_secr() - write OTP data + * spi_nor_otp_write_secr() - write security register * @nor: pointer to 'struct spi_nor' - * @to: offset to write to + * @addr: offset to write to * @len: number of bytes to write * @buf: pointer to src buffer * - * Write OTP data to one region by using the SPINOR_OP_PSECR commands. This - * method is used on GigaDevice and Winbond flashes. + * Write a security register by using the SPINOR_OP_PSECR commands. + * + * For more information on the term "security register", see the documentation + * of spi_nor_otp_read_secr(). * - * Please note, the write must not span multiple OTP regions. + * This method is used on GigaDevice and Winbond flashes. + * + * Please note, the write must not span multiple registers. * * Return: number of bytes written successfully, -errno otherwise */ @@ -84,13 +94,12 @@ int spi_nor_otp_write_secr(struct spi_nor *nor, loff_t addr, size_t len, wdesc = nor->dirmap.wdesc; nor->program_opcode = SPINOR_OP_PSECR; - nor->addr_width = 3; nor->write_proto = SNOR_PROTO_1_1_1; nor->dirmap.wdesc = NULL; /* * We only support a write to one single page. For now all winbond - * flashes only have one page per OTP region. + * flashes only have one page per security register. */ ret = spi_nor_write_enable(nor); if (ret) @@ -111,6 +120,38 @@ out: return ret ?: written; } +/** + * spi_nor_otp_erase_secr() - erase a security register + * @nor: pointer to 'struct spi_nor' + * @addr: offset of the security register to be erased + * + * Erase a security register by using the SPINOR_OP_ESECR command. + * + * For more information on the term "security register", see the documentation + * of spi_nor_otp_read_secr(). + * + * This method is used on GigaDevice and Winbond flashes. + * + * Return: 0 on success, -errno otherwise + */ +int spi_nor_otp_erase_secr(struct spi_nor *nor, loff_t addr) +{ + u8 erase_opcode = nor->erase_opcode; + int ret; + + ret = spi_nor_write_enable(nor); + if (ret) + return ret; + + nor->erase_opcode = SPINOR_OP_ESECR; + ret = spi_nor_erase_sector(nor, addr); + nor->erase_opcode = erase_opcode; + if (ret) + return ret; + + return spi_nor_wait_till_ready(nor); +} + static int spi_nor_otp_lock_bit_cr(unsigned int region) { static const int lock_bits[] = { SR2_LB1, SR2_LB2, SR2_LB3 }; @@ -240,6 +281,29 @@ out: return ret; } +static int spi_nor_mtd_otp_range_is_locked(struct spi_nor *nor, loff_t ofs, + size_t len) +{ + const struct spi_nor_otp_ops *ops = nor->params->otp.ops; + unsigned int region; + int locked; + + /* + * If any of the affected OTP regions are locked the entire range is + * considered locked. + */ + for (region = spi_nor_otp_offset_to_region(nor, ofs); + region <= spi_nor_otp_offset_to_region(nor, ofs + len - 1); + region++) { + locked = ops->is_locked(nor, region); + /* take the branch it is locked or in case of an error */ + if (locked) + return locked; + } + + return 0; +} + static int spi_nor_mtd_otp_read_write(struct mtd_info *mtd, loff_t ofs, size_t total_len, size_t *retlen, const u8 *buf, bool is_write) @@ -255,14 +319,26 @@ static int spi_nor_mtd_otp_read_write(struct mtd_info *mtd, loff_t ofs, if (ofs < 0 || ofs >= spi_nor_otp_size(nor)) return 0; + /* don't access beyond the end */ + total_len = min_t(size_t, total_len, spi_nor_otp_size(nor) - ofs); + + if (!total_len) + return 0; + ret = spi_nor_lock_and_prep(nor); if (ret) return ret; - /* don't access beyond the end */ - total_len = min_t(size_t, total_len, spi_nor_otp_size(nor) - ofs); + if (is_write) { + ret = spi_nor_mtd_otp_range_is_locked(nor, ofs, total_len); + if (ret < 0) { + goto out; + } else if (ret) { + ret = -EROFS; + goto out; + } + } - *retlen = 0; while (total_len) { /* * The OTP regions are mapped into a contiguous area starting @@ -316,6 +392,59 @@ static int spi_nor_mtd_otp_write(struct mtd_info *mtd, loff_t to, size_t len, return spi_nor_mtd_otp_read_write(mtd, to, len, retlen, buf, true); } +static int spi_nor_mtd_otp_erase(struct mtd_info *mtd, loff_t from, size_t len) +{ + struct spi_nor *nor = mtd_to_spi_nor(mtd); + const struct spi_nor_otp_ops *ops = nor->params->otp.ops; + const size_t rlen = spi_nor_otp_region_len(nor); + unsigned int region; + loff_t rstart; + int ret; + + /* OTP erase is optional */ + if (!ops->erase) + return -EOPNOTSUPP; + + if (!len) + return 0; + + if (from < 0 || (from + len) > spi_nor_otp_size(nor)) + return -EINVAL; + + /* the user has to explicitly ask for whole regions */ + if (!IS_ALIGNED(len, rlen) || !IS_ALIGNED(from, rlen)) + return -EINVAL; + + ret = spi_nor_lock_and_prep(nor); + if (ret) + return ret; + + ret = spi_nor_mtd_otp_range_is_locked(nor, from, len); + if (ret < 0) { + goto out; + } else if (ret) { + ret = -EROFS; + goto out; + } + + while (len) { + region = spi_nor_otp_offset_to_region(nor, from); + rstart = spi_nor_otp_region_start(nor, region); + + ret = ops->erase(nor, rstart); + if (ret) + goto out; + + len -= rlen; + from += rlen; + } + +out: + spi_nor_unlock_and_unprep(nor); + + return ret; +} + static int spi_nor_mtd_otp_lock(struct mtd_info *mtd, loff_t from, size_t len) { struct spi_nor *nor = mtd_to_spi_nor(mtd); @@ -374,4 +503,5 @@ void spi_nor_otp_init(struct spi_nor *nor) mtd->_read_user_prot_reg = spi_nor_mtd_otp_read; mtd->_write_user_prot_reg = spi_nor_mtd_otp_write; mtd->_lock_user_prot_reg = spi_nor_mtd_otp_lock; + mtd->_erase_user_prot_reg = spi_nor_mtd_otp_erase; } diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c index 23c28e91f698..c500c2118a5d 100644 --- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -16,6 +16,7 @@ (((p)->parameter_table_pointer[2] << 16) | \ ((p)->parameter_table_pointer[1] << 8) | \ ((p)->parameter_table_pointer[0] << 0)) +#define SFDP_PARAM_HEADER_PARAM_LEN(p) ((p)->length * 4) #define SFDP_BFPT_ID 0xff00 /* Basic Flash Parameter Table */ #define SFDP_SECTOR_MAP_ID 0xff81 /* Sector Map Table */ @@ -1245,6 +1246,8 @@ int spi_nor_parse_sfdp(struct spi_nor *nor) struct sfdp_parameter_header *param_headers = NULL; struct sfdp_header header; struct device *dev = nor->dev; + struct sfdp *sfdp; + size_t sfdp_size; size_t psize; int i, err; @@ -1267,6 +1270,9 @@ int spi_nor_parse_sfdp(struct spi_nor *nor) bfpt_header->major != SFDP_JESD216_MAJOR) return -EINVAL; + sfdp_size = SFDP_PARAM_HEADER_PTP(bfpt_header) + + SFDP_PARAM_HEADER_PARAM_LEN(bfpt_header); + /* * Allocate memory then read all parameter headers with a single * Read SFDP command. These parameter headers will actually be parsed @@ -1294,6 +1300,58 @@ int spi_nor_parse_sfdp(struct spi_nor *nor) } /* + * Cache the complete SFDP data. It is not (easily) possible to fetch + * SFDP after probe time and we need it for the sysfs access. + */ + for (i = 0; i < header.nph; i++) { + param_header = ¶m_headers[i]; + sfdp_size = max_t(size_t, sfdp_size, + SFDP_PARAM_HEADER_PTP(param_header) + + SFDP_PARAM_HEADER_PARAM_LEN(param_header)); + } + + /* + * Limit the total size to a reasonable value to avoid allocating too + * much memory just of because the flash returned some insane values. + */ + if (sfdp_size > PAGE_SIZE) { + dev_dbg(dev, "SFDP data (%zu) too big, truncating\n", + sfdp_size); + sfdp_size = PAGE_SIZE; + } + + sfdp = devm_kzalloc(dev, sizeof(*sfdp), GFP_KERNEL); + if (!sfdp) { + err = -ENOMEM; + goto exit; + } + + /* + * The SFDP is organized in chunks of DWORDs. Thus, in theory, the + * sfdp_size should be a multiple of DWORDs. But in case a flash + * is not spec compliant, make sure that we have enough space to store + * the complete SFDP data. + */ + sfdp->num_dwords = DIV_ROUND_UP(sfdp_size, sizeof(*sfdp->dwords)); + sfdp->dwords = devm_kcalloc(dev, sfdp->num_dwords, + sizeof(*sfdp->dwords), GFP_KERNEL); + if (!sfdp->dwords) { + err = -ENOMEM; + devm_kfree(dev, sfdp); + goto exit; + } + + err = spi_nor_read_sfdp(nor, 0, sfdp_size, sfdp->dwords); + if (err < 0) { + dev_dbg(dev, "failed to read SFDP data\n"); + devm_kfree(dev, sfdp->dwords); + devm_kfree(dev, sfdp); + goto exit; + } + + nor->sfdp = sfdp; + + /* * Check other parameter headers to get the latest revision of * the basic flash parameter table. */ diff --git a/drivers/mtd/spi-nor/sysfs.c b/drivers/mtd/spi-nor/sysfs.c new file mode 100644 index 000000000000..9aec9d8a98ad --- /dev/null +++ b/drivers/mtd/spi-nor/sysfs.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/mtd/spi-nor.h> +#include <linux/spi/spi.h> +#include <linux/spi/spi-mem.h> +#include <linux/sysfs.h> + +#include "core.h" + +static ssize_t manufacturer_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct spi_device *spi = to_spi_device(dev); + struct spi_mem *spimem = spi_get_drvdata(spi); + struct spi_nor *nor = spi_mem_get_drvdata(spimem); + + return sysfs_emit(buf, "%s\n", nor->manufacturer->name); +} +static DEVICE_ATTR_RO(manufacturer); + +static ssize_t partname_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct spi_device *spi = to_spi_device(dev); + struct spi_mem *spimem = spi_get_drvdata(spi); + struct spi_nor *nor = spi_mem_get_drvdata(spimem); + + return sysfs_emit(buf, "%s\n", nor->info->name); +} +static DEVICE_ATTR_RO(partname); + +static ssize_t jedec_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct spi_device *spi = to_spi_device(dev); + struct spi_mem *spimem = spi_get_drvdata(spi); + struct spi_nor *nor = spi_mem_get_drvdata(spimem); + + return sysfs_emit(buf, "%*phN\n", nor->info->id_len, nor->info->id); +} +static DEVICE_ATTR_RO(jedec_id); + +static struct attribute *spi_nor_sysfs_entries[] = { + &dev_attr_manufacturer.attr, + &dev_attr_partname.attr, + &dev_attr_jedec_id.attr, + NULL +}; + +static ssize_t sfdp_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, + loff_t off, size_t count) +{ + struct spi_device *spi = to_spi_device(kobj_to_dev(kobj)); + struct spi_mem *spimem = spi_get_drvdata(spi); + struct spi_nor *nor = spi_mem_get_drvdata(spimem); + struct sfdp *sfdp = nor->sfdp; + size_t sfdp_size = sfdp->num_dwords * sizeof(*sfdp->dwords); + + return memory_read_from_buffer(buf, count, &off, nor->sfdp->dwords, + sfdp_size); +} +static BIN_ATTR_RO(sfdp, 0); + +static struct bin_attribute *spi_nor_sysfs_bin_entries[] = { + &bin_attr_sfdp, + NULL +}; + +static umode_t spi_nor_sysfs_is_bin_visible(struct kobject *kobj, + struct bin_attribute *attr, int n) +{ + struct spi_device *spi = to_spi_device(kobj_to_dev(kobj)); + struct spi_mem *spimem = spi_get_drvdata(spi); + struct spi_nor *nor = spi_mem_get_drvdata(spimem); + + if (attr == &bin_attr_sfdp && nor->sfdp) + return 0444; + + return 0; +} + +static const struct attribute_group spi_nor_sysfs_group = { + .name = "spi-nor", + .is_bin_visible = spi_nor_sysfs_is_bin_visible, + .attrs = spi_nor_sysfs_entries, + .bin_attrs = spi_nor_sysfs_bin_entries, +}; + +const struct attribute_group *spi_nor_sysfs_groups[] = { + &spi_nor_sysfs_group, + NULL +}; diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index 9a81c67a60c6..96573f61caf5 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -139,6 +139,7 @@ static int winbond_set_4byte_addr_mode(struct spi_nor *nor, bool enable) static const struct spi_nor_otp_ops winbond_otp_ops = { .read = spi_nor_otp_read_secr, .write = spi_nor_otp_write_secr, + .erase = spi_nor_otp_erase_secr, .lock = spi_nor_otp_lock_sr2, .is_locked = spi_nor_otp_is_locked_sr2, }; diff --git a/drivers/mtd/tests/oobtest.c b/drivers/mtd/tests/oobtest.c index c71daa89bfce..532997e10e29 100644 --- a/drivers/mtd/tests/oobtest.c +++ b/drivers/mtd/tests/oobtest.c @@ -506,7 +506,6 @@ static int __init mtd_oobtest_init(void) err = mtd_write_oob(mtd, addr0, &ops); if (err) { pr_info("error occurred as expected\n"); - err = 0; } else { pr_err("error: can write past end of OOB\n"); errcnt += 1; @@ -529,7 +528,6 @@ static int __init mtd_oobtest_init(void) if (err) { pr_info("error occurred as expected\n"); - err = 0; } else { pr_err("error: can read past end of OOB\n"); errcnt += 1; @@ -553,7 +551,6 @@ static int __init mtd_oobtest_init(void) err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops); if (err) { pr_info("error occurred as expected\n"); - err = 0; } else { pr_err("error: wrote past end of device\n"); errcnt += 1; @@ -576,7 +573,6 @@ static int __init mtd_oobtest_init(void) if (err) { pr_info("error occurred as expected\n"); - err = 0; } else { pr_err("error: read past end of device\n"); errcnt += 1; @@ -600,7 +596,6 @@ static int __init mtd_oobtest_init(void) err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops); if (err) { pr_info("error occurred as expected\n"); - err = 0; } else { pr_err("error: wrote past end of device\n"); errcnt += 1; @@ -623,7 +618,6 @@ static int __init mtd_oobtest_init(void) if (err) { pr_info("error occurred as expected\n"); - err = 0; } else { pr_err("error: read past end of device\n"); errcnt += 1; @@ -701,6 +695,7 @@ static int __init mtd_oobtest_init(void) (long long)addr); errcnt += 1; if (errcnt > 1000) { + err = -EINVAL; pr_err("error: too many errors\n"); goto out; } diff --git a/drivers/mtd/tests/torturetest.c b/drivers/mtd/tests/torturetest.c index 6787ac5471a9..841689b4d86d 100644 --- a/drivers/mtd/tests/torturetest.c +++ b/drivers/mtd/tests/torturetest.c @@ -230,8 +230,6 @@ static int __init tort_init(void) if (!bad_ebs) goto out_check_buf; - err = 0; - /* Initialize patterns */ memset(patt_FF, 0xFF, mtd->erasesize); for (i = 0; i < mtd->erasesize / pgsize; i++) { diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index ac2bdba8bb1a..3c0c8eca4d51 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c @@ -511,7 +511,7 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi) n = snprintf(d->dfs_dir_name, UBI_DFS_DIR_LEN + 1, UBI_DFS_DIR_NAME, ubi->ubi_num); - if (n == UBI_DFS_DIR_LEN) { + if (n > UBI_DFS_DIR_LEN) { /* The array size is too small */ return -EINVAL; } diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c index 4ffbfd534f18..2a7af611d43a 100644 --- a/drivers/net/caif/caif_serial.c +++ b/drivers/net/caif/caif_serial.c @@ -87,9 +87,9 @@ static void ldisc_tx_wakeup(struct tty_struct *tty); static inline void update_tty_status(struct ser_device *ser) { ser->tty_status = - ser->tty->stopped << 5 | - ser->tty->flow_stopped << 3 | - ser->tty->packet << 2; + ser->tty->flow.stopped << 5 | + ser->tty->flow.tco_stopped << 3 | + ser->tty->ctrl.packet << 2; } static inline void debugfs_init(struct ser_device *ser, struct tty_struct *tty) { @@ -159,7 +159,7 @@ static inline void debugfs_tx(struct ser_device *ser, const u8 *data, int size) #endif static void ldisc_receive(struct tty_struct *tty, const u8 *data, - char *flags, int count) + const char *flags, int count) { struct sk_buff *skb = NULL; struct ser_device *ser; @@ -380,6 +380,7 @@ static void ldisc_close(struct tty_struct *tty) /* The line discipline structure. */ static struct tty_ldisc_ops caif_ldisc = { .owner = THIS_MODULE, + .num = N_CAIF, .name = "n_caif", .open = ldisc_open, .close = ldisc_close, @@ -429,7 +430,7 @@ static int __init caif_ser_init(void) { int ret; - ret = tty_register_ldisc(N_CAIF, &caif_ldisc); + ret = tty_register_ldisc(&caif_ldisc); if (ret < 0) pr_err("cannot register CAIF ldisc=%d err=%d\n", N_CAIF, ret); @@ -444,7 +445,7 @@ static void __exit caif_ser_exit(void) spin_unlock(&ser_lock); ser_release(NULL); cancel_work_sync(&ser_release_work); - tty_unregister_ldisc(N_CAIF); + tty_unregister_ldisc(&caif_ldisc); debugfs_remove_recursive(debugfsdir); } diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index 31ba6664503d..d42ec7d1bc14 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -467,7 +467,8 @@ static void slc_setup(struct net_device *dev) */ static void slcan_receive_buf(struct tty_struct *tty, - const unsigned char *cp, char *fp, int count) + const unsigned char *cp, const char *fp, + int count) { struct slcan *sl = (struct slcan *) tty->disc_data; @@ -697,6 +698,7 @@ static int slcan_ioctl(struct tty_struct *tty, struct file *file, static struct tty_ldisc_ops slc_ldisc = { .owner = THIS_MODULE, + .num = N_SLCAN, .name = "slcan", .open = slcan_open, .close = slcan_close, @@ -721,7 +723,7 @@ static int __init slcan_init(void) return -ENOMEM; /* Fill in our line protocol discipline, and register it */ - status = tty_register_ldisc(N_SLCAN, &slc_ldisc); + status = tty_register_ldisc(&slc_ldisc); if (status) { printk(KERN_ERR "slcan: can't register line discipline\n"); kfree(slcan_devs); @@ -782,9 +784,7 @@ static void __exit slcan_exit(void) kfree(slcan_devs); slcan_devs = NULL; - i = tty_unregister_ldisc(N_SLCAN); - if (i) - printk(KERN_ERR "slcan: can't unregister ldisc (err %d)\n", i); + tty_unregister_ldisc(&slc_ldisc); } module_init(slcan_init); diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_trace.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu_trace.h index e6609068e81b..64aa7d350df1 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_trace.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_trace.h @@ -21,7 +21,7 @@ TRACE_EVENT(otx2_msg_alloc, __field(u16, id) __field(u64, size) ), - TP_fast_assign(__assign_str(dev, pci_name(pdev)) + TP_fast_assign(__assign_str(dev, pci_name(pdev)); __entry->id = id; __entry->size = size; ), @@ -36,7 +36,7 @@ TRACE_EVENT(otx2_msg_send, __field(u16, num_msgs) __field(u64, msg_size) ), - TP_fast_assign(__assign_str(dev, pci_name(pdev)) + TP_fast_assign(__assign_str(dev, pci_name(pdev)); __entry->num_msgs = num_msgs; __entry->msg_size = msg_size; ), @@ -52,7 +52,7 @@ TRACE_EVENT(otx2_msg_check, __field(u16, rspid) __field(int, rc) ), - TP_fast_assign(__assign_str(dev, pci_name(pdev)) + TP_fast_assign(__assign_str(dev, pci_name(pdev)); __entry->reqid = reqid; __entry->rspid = rspid; __entry->rc = rc; @@ -69,8 +69,8 @@ TRACE_EVENT(otx2_msg_interrupt, __string(str, msg) __field(u64, intr) ), - TP_fast_assign(__assign_str(dev, pci_name(pdev)) - __assign_str(str, msg) + TP_fast_assign(__assign_str(dev, pci_name(pdev)); + __assign_str(str, msg); __entry->intr = intr; ), TP_printk("[%s] mbox interrupt %s (0x%llx)\n", __get_str(dev), @@ -84,7 +84,7 @@ TRACE_EVENT(otx2_msg_process, __field(u16, id) __field(int, err) ), - TP_fast_assign(__assign_str(dev, pci_name(pdev)) + TP_fast_assign(__assign_str(dev, pci_name(pdev)); __entry->id = id; __entry->err = err; ), diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index a99e71bc7b3c..771b92019af1 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -2660,6 +2660,7 @@ int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave, case RES_XRCD: err = xrcdn_free_res(dev, slave, vhcr->op_modifier, alop, vhcr->in_param, &vhcr->out_param); + break; default: break; diff --git a/drivers/net/ethernet/sun/ldmvsw.c b/drivers/net/ethernet/sun/ldmvsw.c index 01ea0d6f8819..50bd4e3b0af9 100644 --- a/drivers/net/ethernet/sun/ldmvsw.c +++ b/drivers/net/ethernet/sun/ldmvsw.c @@ -404,7 +404,7 @@ err_out_free_dev: return err; } -static int vsw_port_remove(struct vio_dev *vdev) +static void vsw_port_remove(struct vio_dev *vdev) { struct vnet_port *port = dev_get_drvdata(&vdev->dev); unsigned long flags; @@ -430,8 +430,6 @@ static int vsw_port_remove(struct vio_dev *vdev) free_netdev(port->dev); } - - return 0; } static void vsw_cleanup(void) diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index 96b883f965f6..58ee89223951 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c @@ -510,7 +510,7 @@ err_out_put_mdesc: return err; } -static int vnet_port_remove(struct vio_dev *vdev) +static void vnet_port_remove(struct vio_dev *vdev) { struct vnet_port *port = dev_get_drvdata(&vdev->dev); @@ -533,7 +533,6 @@ static int vnet_port_remove(struct vio_dev *vdev) kfree(port); } - return 0; } static const struct vio_device_id vnet_port_match[] = { diff --git a/drivers/net/fjes/fjes_trace.h b/drivers/net/fjes/fjes_trace.h index 9237b69d8e21..6437ddbd7842 100644 --- a/drivers/net/fjes/fjes_trace.h +++ b/drivers/net/fjes/fjes_trace.h @@ -232,7 +232,7 @@ TRACE_EVENT(fjes_hw_start_debug_err, __string(err, err) ), TP_fast_assign( - __assign_str(err, err) + __assign_str(err, err); ), TP_printk("%s", __get_str(err)) ); @@ -258,7 +258,7 @@ TRACE_EVENT(fjes_hw_stop_debug_err, __string(err, err) ), TP_fast_assign( - __assign_str(err, err) + __assign_str(err, err); ), TP_printk("%s", __get_str(err)) ); diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index a15cc5e50290..fcf3af76b6d7 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -428,7 +428,7 @@ out: * and sent on to some IP layer for further processing. */ static void sixpack_receive_buf(struct tty_struct *tty, - const unsigned char *cp, char *fp, int count) + const unsigned char *cp, const char *fp, int count) { struct sixpack *sp; int count1; @@ -742,6 +742,7 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file, static struct tty_ldisc_ops sp_ldisc = { .owner = THIS_MODULE, + .num = N_6PACK, .name = "6pack", .open = sixpack_open, .close = sixpack_close, @@ -764,21 +765,16 @@ static int __init sixpack_init_driver(void) printk(msg_banner); /* Register the provided line protocol discipline */ - if ((status = tty_register_ldisc(N_6PACK, &sp_ldisc)) != 0) + status = tty_register_ldisc(&sp_ldisc); + if (status) printk(msg_regfail, status); return status; } -static const char msg_unregfail[] = KERN_ERR \ - "6pack: can't unregister line discipline (err = %d)\n"; - static void __exit sixpack_exit_driver(void) { - int ret; - - if ((ret = tty_unregister_ldisc(N_6PACK))) - printk(msg_unregfail, ret); + tty_unregister_ldisc(&sp_ldisc); } /* encode an AX.25 packet into 6pack */ diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index b99128669bc8..8666110bec55 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -872,7 +872,7 @@ static int mkiss_ioctl(struct tty_struct *tty, struct file *file, * and sent on to the AX.25 layer for further processing. */ static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) + const char *fp, int count) { struct mkiss *ax = mkiss_get(tty); @@ -934,6 +934,7 @@ out: static struct tty_ldisc_ops ax_ldisc = { .owner = THIS_MODULE, + .num = N_AX25, .name = "mkiss", .open = mkiss_open, .close = mkiss_close, @@ -953,22 +954,16 @@ static int __init mkiss_init_driver(void) printk(banner); - status = tty_register_ldisc(N_AX25, &ax_ldisc); + status = tty_register_ldisc(&ax_ldisc); if (status != 0) printk(msg_regfail, status); return status; } -static const char msg_unregfail[] = KERN_ERR \ - "mkiss: can't unregister line discipline (err = %d)\n"; - static void __exit mkiss_exit_driver(void) { - int ret; - - if ((ret = tty_unregister_ldisc(N_AX25))) - printk(msg_unregfail, ret); + tty_unregister_ldisc(&ax_ldisc); } MODULE_AUTHOR("Ralf Baechle DL5RB <ralf@linux-mips.org>"); diff --git a/drivers/net/ppp/ppp_async.c b/drivers/net/ppp/ppp_async.c index 8b41aa3fb64e..29a93d6bfe37 100644 --- a/drivers/net/ppp/ppp_async.c +++ b/drivers/net/ppp/ppp_async.c @@ -98,7 +98,7 @@ static int ppp_async_send(struct ppp_channel *chan, struct sk_buff *skb); static int ppp_async_push(struct asyncppp *ap); static void ppp_async_flush_output(struct asyncppp *ap); static void ppp_async_input(struct asyncppp *ap, const unsigned char *buf, - char *flags, int count); + const char *flags, int count); static int ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg); static void ppp_async_process(struct tasklet_struct *t); @@ -340,7 +340,7 @@ ppp_asynctty_poll(struct tty_struct *tty, struct file *file, poll_table *wait) /* May sleep, don't call from interrupt level or with interrupts disabled */ static void ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf, - char *cflags, int count) + const char *cflags, int count) { struct asyncppp *ap = ap_get(tty); unsigned long flags; @@ -372,6 +372,7 @@ ppp_asynctty_wakeup(struct tty_struct *tty) static struct tty_ldisc_ops ppp_ldisc = { .owner = THIS_MODULE, + .num = N_PPP, .name = "ppp", .open = ppp_asynctty_open, .close = ppp_asynctty_close, @@ -389,7 +390,7 @@ ppp_async_init(void) { int err; - err = tty_register_ldisc(N_PPP, &ppp_ldisc); + err = tty_register_ldisc(&ppp_ldisc); if (err != 0) printk(KERN_ERR "PPP_async: error %d registering line disc.\n", err); @@ -829,7 +830,7 @@ process_input_packet(struct asyncppp *ap) static void ppp_async_input(struct asyncppp *ap, const unsigned char *buf, - char *flags, int count) + const char *flags, int count) { struct sk_buff *skb; int c, i, j, n, s, f; @@ -1015,8 +1016,7 @@ static void async_lcp_peek(struct asyncppp *ap, unsigned char *data, static void __exit ppp_async_cleanup(void) { - if (tty_unregister_ldisc(N_PPP) != 0) - printk(KERN_ERR "failed to unregister PPP line discipline\n"); + tty_unregister_ldisc(&ppp_ldisc); } module_init(ppp_async_init); diff --git a/drivers/net/ppp/ppp_synctty.c b/drivers/net/ppp/ppp_synctty.c index 576b6a93bf23..af3e048695b6 100644 --- a/drivers/net/ppp/ppp_synctty.c +++ b/drivers/net/ppp/ppp_synctty.c @@ -94,7 +94,7 @@ static void ppp_sync_process(struct tasklet_struct *t); static int ppp_sync_push(struct syncppp *ap); static void ppp_sync_flush_output(struct syncppp *ap); static void ppp_sync_input(struct syncppp *ap, const unsigned char *buf, - char *flags, int count); + const char *flags, int count); static const struct ppp_channel_ops sync_ops = { .start_xmit = ppp_sync_send, @@ -333,7 +333,7 @@ ppp_sync_poll(struct tty_struct *tty, struct file *file, poll_table *wait) /* May sleep, don't call from interrupt level or with interrupts disabled */ static void ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf, - char *cflags, int count) + const char *cflags, int count) { struct syncppp *ap = sp_get(tty); unsigned long flags; @@ -365,6 +365,7 @@ ppp_sync_wakeup(struct tty_struct *tty) static struct tty_ldisc_ops ppp_sync_ldisc = { .owner = THIS_MODULE, + .num = N_SYNC_PPP, .name = "pppsync", .open = ppp_sync_open, .close = ppp_sync_close, @@ -382,7 +383,7 @@ ppp_sync_init(void) { int err; - err = tty_register_ldisc(N_SYNC_PPP, &ppp_sync_ldisc); + err = tty_register_ldisc(&ppp_sync_ldisc); if (err != 0) printk(KERN_ERR "PPP_sync: error %d registering line disc.\n", err); @@ -665,7 +666,7 @@ ppp_sync_flush_output(struct syncppp *ap) */ static void ppp_sync_input(struct syncppp *ap, const unsigned char *buf, - char *flags, int count) + const char *flags, int count) { struct sk_buff *skb; unsigned char *p; @@ -726,8 +727,7 @@ err: static void __exit ppp_sync_cleanup(void) { - if (tty_unregister_ldisc(N_SYNC_PPP) != 0) - printk(KERN_ERR "failed to unregister Sync PPP line discipline\n"); + tty_unregister_ldisc(&ppp_sync_ldisc); } module_init(ppp_sync_init); diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c index 1ab124eba8eb..dc84cb844319 100644 --- a/drivers/net/slip/slip.c +++ b/drivers/net/slip/slip.c @@ -685,7 +685,7 @@ static void sl_setup(struct net_device *dev) */ static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) + const char *fp, int count) { struct slip *sl = tty->disc_data; @@ -1263,6 +1263,7 @@ static int sl_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static struct tty_ldisc_ops sl_ldisc = { .owner = THIS_MODULE, + .num = N_SLIP, .name = "slip", .open = slip_open, .close = slip_close, @@ -1298,7 +1299,7 @@ static int __init slip_init(void) return -ENOMEM; /* Fill in our line protocol discipline, and register it */ - status = tty_register_ldisc(N_SLIP, &sl_ldisc); + status = tty_register_ldisc(&sl_ldisc); if (status != 0) { printk(KERN_ERR "SLIP: can't register line discipline (err = %d)\n", status); kfree(slip_devs); @@ -1359,9 +1360,7 @@ static void __exit slip_exit(void) kfree(slip_devs); slip_devs = NULL; - i = tty_unregister_ldisc(N_SLIP); - if (i != 0) - printk(KERN_ERR "SLIP: can't unregister line discipline (err = %d)\n", i); + tty_unregister_ldisc(&sl_ldisc); } module_init(slip_init); diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 54ef8492ca01..63006838bdcc 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1356,10 +1356,10 @@ out: } /* how much room is there for writing */ -static int hso_serial_write_room(struct tty_struct *tty) +static unsigned int hso_serial_write_room(struct tty_struct *tty) { struct hso_serial *serial = tty->driver_data; - int room; + unsigned int room; unsigned long flags; spin_lock_irqsave(&serial->serial_lock, flags); @@ -1403,11 +1403,11 @@ static void hso_serial_set_termios(struct tty_struct *tty, struct ktermios *old) } /* how many characters in the buffer */ -static int hso_serial_chars_in_buffer(struct tty_struct *tty) +static unsigned int hso_serial_chars_in_buffer(struct tty_struct *tty) { struct hso_serial *serial = tty->driver_data; - int chars; unsigned long flags; + unsigned int chars; /* sanity check */ if (serial == NULL) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index b0b81458ca94..8a58a2f013af 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1516,12 +1516,16 @@ static void virtnet_poll_cleantx(struct receive_queue *rq) return; if (__netif_tx_trylock(txq)) { - free_old_xmit_skbs(sq, true); + do { + virtqueue_disable_cb(sq->vq); + free_old_xmit_skbs(sq, true); + } while (unlikely(!virtqueue_enable_cb_delayed(sq->vq))); + + if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS) + netif_tx_wake_queue(txq); + __netif_tx_unlock(txq); } - - if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS) - netif_tx_wake_queue(txq); } static int virtnet_poll(struct napi_struct *napi, int budget) @@ -1592,6 +1596,8 @@ static int virtnet_poll_tx(struct napi_struct *napi, int budget) struct virtnet_info *vi = sq->vq->vdev->priv; unsigned int index = vq2txq(sq->vq); struct netdev_queue *txq; + int opaque; + bool done; if (unlikely(is_xdp_raw_buffer_queue(vi, index))) { /* We don't need to enable cb for XDP */ @@ -1601,14 +1607,32 @@ static int virtnet_poll_tx(struct napi_struct *napi, int budget) txq = netdev_get_tx_queue(vi->dev, index); __netif_tx_lock(txq, raw_smp_processor_id()); + virtqueue_disable_cb(sq->vq); free_old_xmit_skbs(sq, true); - __netif_tx_unlock(txq); - - virtqueue_napi_complete(napi, sq->vq, 0); if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS) netif_tx_wake_queue(txq); + opaque = virtqueue_enable_cb_prepare(sq->vq); + + done = napi_complete_done(napi, 0); + + if (!done) + virtqueue_disable_cb(sq->vq); + + __netif_tx_unlock(txq); + + if (done) { + if (unlikely(virtqueue_poll(sq->vq, opaque))) { + if (napi_schedule_prep(napi)) { + __netif_tx_lock(txq, raw_smp_processor_id()); + virtqueue_disable_cb(sq->vq); + __netif_tx_unlock(txq); + __napi_schedule(napi); + } + } + } + return 0; } @@ -1670,10 +1694,14 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) bool use_napi = sq->napi.weight; /* Free up any pending old buffers before queueing new ones. */ - free_old_xmit_skbs(sq, false); + do { + if (use_napi) + virtqueue_disable_cb(sq->vq); + + free_old_xmit_skbs(sq, false); - if (use_napi && kick) - virtqueue_enable_cb_delayed(sq->vq); + } while (use_napi && kick && + unlikely(!virtqueue_enable_cb_delayed(sq->vq))); /* timestamp packet in software */ skb_tx_timestamp(skb); @@ -3310,8 +3338,11 @@ static __maybe_unused int virtnet_restore(struct virtio_device *vdev) virtnet_set_queues(vi, vi->curr_queue_pairs); err = virtnet_cpu_notif_add(vi); - if (err) + if (err) { + virtnet_freeze_down(vdev); + remove_vq_common(vi); return err; + } return 0; } diff --git a/drivers/net/wireless/broadcom/b43/debugfs.c b/drivers/net/wireless/broadcom/b43/debugfs.c index 89a25aefb327..efa98444e3fb 100644 --- a/drivers/net/wireless/broadcom/b43/debugfs.c +++ b/drivers/net/wireless/broadcom/b43/debugfs.c @@ -643,24 +643,14 @@ bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature) return enabled; } -static void b43_remove_dynamic_debug(struct b43_wldev *dev) -{ - struct b43_dfsentry *e = dev->dfsentry; - int i; - - for (i = 0; i < __B43_NR_DYNDBG; i++) - debugfs_remove(e->dyn_debug_dentries[i]); -} - static void b43_add_dynamic_debug(struct b43_wldev *dev) { struct b43_dfsentry *e = dev->dfsentry; #define add_dyn_dbg(name, id, initstate) do { \ e->dyn_debug[id] = (initstate); \ - e->dyn_debug_dentries[id] = \ - debugfs_create_bool(name, 0600, e->subdir, \ - &(e->dyn_debug[id])); \ + debugfs_create_bool(name, 0600, e->subdir, \ + &(e->dyn_debug[id])); \ } while (0) add_dyn_dbg("debug_xmitpower", B43_DBG_XMITPOWER, false); @@ -713,10 +703,9 @@ void b43_debugfs_add_device(struct b43_wldev *dev) #define ADD_FILE(name, mode) \ do { \ - e->file_##name.dentry = \ - debugfs_create_file(__stringify(name), \ - mode, e->subdir, dev, \ - &fops_##name.fops); \ + debugfs_create_file(__stringify(name), \ + mode, e->subdir, dev, \ + &fops_##name.fops); \ } while (0) @@ -746,19 +735,6 @@ void b43_debugfs_remove_device(struct b43_wldev *dev) e = dev->dfsentry; if (!e) return; - b43_remove_dynamic_debug(dev); - - debugfs_remove(e->file_shm16read.dentry); - debugfs_remove(e->file_shm16write.dentry); - debugfs_remove(e->file_shm32read.dentry); - debugfs_remove(e->file_shm32write.dentry); - debugfs_remove(e->file_mmio16read.dentry); - debugfs_remove(e->file_mmio16write.dentry); - debugfs_remove(e->file_mmio32read.dentry); - debugfs_remove(e->file_mmio32write.dentry); - debugfs_remove(e->file_txstat.dentry); - debugfs_remove(e->file_restart.dentry); - debugfs_remove(e->file_loctls.dentry); debugfs_remove(e->subdir); kfree(e->txstatlog.log); diff --git a/drivers/net/wireless/broadcom/b43/debugfs.h b/drivers/net/wireless/broadcom/b43/debugfs.h index 0bf437c86c67..6f6b500b8881 100644 --- a/drivers/net/wireless/broadcom/b43/debugfs.h +++ b/drivers/net/wireless/broadcom/b43/debugfs.h @@ -32,7 +32,6 @@ struct b43_txstatus_log { }; struct b43_dfs_file { - struct dentry *dentry; char *buffer; size_t data_len; }; @@ -70,8 +69,6 @@ struct b43_dfsentry { /* Enabled/Disabled list for the dynamic debugging features. */ bool dyn_debug[__B43_NR_DYNDBG]; - /* Dentries for the dynamic debugging entries. */ - struct dentry *dyn_debug_dentries[__B43_NR_DYNDBG]; }; bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature); diff --git a/drivers/net/wireless/broadcom/b43legacy/debugfs.c b/drivers/net/wireless/broadcom/b43legacy/debugfs.c index e7e4293c01f2..6b0e8d117061 100644 --- a/drivers/net/wireless/broadcom/b43legacy/debugfs.c +++ b/drivers/net/wireless/broadcom/b43legacy/debugfs.c @@ -336,24 +336,14 @@ int b43legacy_debug(struct b43legacy_wldev *dev, enum b43legacy_dyndbg feature) return !!(dev->dfsentry && dev->dfsentry->dyn_debug[feature]); } -static void b43legacy_remove_dynamic_debug(struct b43legacy_wldev *dev) -{ - struct b43legacy_dfsentry *e = dev->dfsentry; - int i; - - for (i = 0; i < __B43legacy_NR_DYNDBG; i++) - debugfs_remove(e->dyn_debug_dentries[i]); -} - static void b43legacy_add_dynamic_debug(struct b43legacy_wldev *dev) { struct b43legacy_dfsentry *e = dev->dfsentry; #define add_dyn_dbg(name, id, initstate) do { \ e->dyn_debug[id] = (initstate); \ - e->dyn_debug_dentries[id] = \ - debugfs_create_bool(name, 0600, e->subdir, \ - &(e->dyn_debug[id])); \ + debugfs_create_bool(name, 0600, e->subdir, \ + &(e->dyn_debug[id])); \ } while (0) add_dyn_dbg("debug_xmitpower", B43legacy_DBG_XMITPOWER, false); @@ -396,11 +386,9 @@ void b43legacy_debugfs_add_device(struct b43legacy_wldev *dev) #define ADD_FILE(name, mode) \ do { \ - e->file_##name.dentry = \ - debugfs_create_file(__stringify(name), \ - mode, e->subdir, dev, \ - &fops_##name.fops); \ - e->file_##name.dentry = NULL; \ + debugfs_create_file(__stringify(name), mode, \ + e->subdir, dev, \ + &fops_##name.fops); \ } while (0) @@ -424,13 +412,6 @@ void b43legacy_debugfs_remove_device(struct b43legacy_wldev *dev) e = dev->dfsentry; if (!e) return; - b43legacy_remove_dynamic_debug(dev); - - debugfs_remove(e->file_tsf.dentry); - debugfs_remove(e->file_ucode_regs.dentry); - debugfs_remove(e->file_shm.dentry); - debugfs_remove(e->file_txstat.dentry); - debugfs_remove(e->file_restart.dentry); debugfs_remove(e->subdir); kfree(e->txstatlog.log); diff --git a/drivers/net/wireless/broadcom/b43legacy/debugfs.h b/drivers/net/wireless/broadcom/b43legacy/debugfs.h index 7a37764406b1..924130880dfe 100644 --- a/drivers/net/wireless/broadcom/b43legacy/debugfs.h +++ b/drivers/net/wireless/broadcom/b43legacy/debugfs.h @@ -28,7 +28,6 @@ struct b43legacy_txstatus_log { }; struct b43legacy_dfs_file { - struct dentry *dentry; char *buffer; size_t data_len; }; @@ -49,8 +48,6 @@ struct b43legacy_dfsentry { /* Enabled/Disabled list for the dynamic debugging features. */ bool dyn_debug[__B43legacy_NR_DYNDBG]; - /* Dentries for the dynamic debugging entries. */ - struct dentry *dyn_debug_dentries[__B43legacy_NR_DYNDBG]; }; int b43legacy_debug(struct b43legacy_wldev *dev, diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index e500b8405f8f..5669f17b395f 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -6784,7 +6784,7 @@ int wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) if (pdev_data->family && pdev_data->family->nvs_name) { nvs_name = pdev_data->family->nvs_name; - ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, + ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, nvs_name, &pdev->dev, GFP_KERNEL, wl, wlcore_nvs_cb); if (ret < 0) { diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index 3a777d0073b7..e6aa87043a95 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -363,8 +363,13 @@ struct nvdimm_bus *nvdimm_bus_register(struct device *parent, nvdimm_bus->dev.groups = nd_desc->attr_groups; nvdimm_bus->dev.bus = &nvdimm_bus_type; nvdimm_bus->dev.of_node = nd_desc->of_node; - dev_set_name(&nvdimm_bus->dev, "ndbus%d", nvdimm_bus->id); - rc = device_register(&nvdimm_bus->dev); + device_initialize(&nvdimm_bus->dev); + device_set_pm_not_required(&nvdimm_bus->dev); + rc = dev_set_name(&nvdimm_bus->dev, "ndbus%d", nvdimm_bus->id); + if (rc) + goto err; + + rc = device_add(&nvdimm_bus->dev); if (rc) { dev_dbg(&nvdimm_bus->dev, "registration failed: %d\n", rc); goto err; @@ -396,21 +401,10 @@ static int child_unregister(struct device *dev, void *data) if (dev->class) return 0; - if (is_nvdimm(dev)) { - struct nvdimm *nvdimm = to_nvdimm(dev); - bool dev_put = false; - - /* We are shutting down. Make state frozen artificially. */ - nvdimm_bus_lock(dev); - set_bit(NVDIMM_SECURITY_FROZEN, &nvdimm->sec.flags); - if (test_and_clear_bit(NDD_WORK_PENDING, &nvdimm->flags)) - dev_put = true; - nvdimm_bus_unlock(dev); - cancel_delayed_work_sync(&nvdimm->dwork); - if (dev_put) - put_device(dev); - } - nd_device_unregister(dev, ND_SYNC); + if (is_nvdimm(dev)) + nvdimm_delete(to_nvdimm(dev)); + else + nd_device_unregister(dev, ND_SYNC); return 0; } @@ -536,6 +530,7 @@ void __nd_device_register(struct device *dev) set_dev_node(dev, to_nd_region(dev)->numa_node); dev->bus = &nvdimm_bus_type; + device_set_pm_not_required(dev); if (dev->parent) { get_device(dev->parent); if (dev_to_node(dev) == NUMA_NO_NODE) @@ -728,18 +723,41 @@ const struct attribute_group nd_numa_attribute_group = { .is_visible = nd_numa_attr_visible, }; +static void ndctl_release(struct device *dev) +{ + kfree(dev); +} + int nvdimm_bus_create_ndctl(struct nvdimm_bus *nvdimm_bus) { dev_t devt = MKDEV(nvdimm_bus_major, nvdimm_bus->id); struct device *dev; + int rc; - dev = device_create(nd_class, &nvdimm_bus->dev, devt, nvdimm_bus, - "ndctl%d", nvdimm_bus->id); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + device_initialize(dev); + device_set_pm_not_required(dev); + dev->class = nd_class; + dev->parent = &nvdimm_bus->dev; + dev->devt = devt; + dev->release = ndctl_release; + rc = dev_set_name(dev, "ndctl%d", nvdimm_bus->id); + if (rc) + goto err; - if (IS_ERR(dev)) - dev_dbg(&nvdimm_bus->dev, "failed to register ndctl%d: %ld\n", - nvdimm_bus->id, PTR_ERR(dev)); - return PTR_ERR_OR_ZERO(dev); + rc = device_add(dev); + if (rc) { + dev_dbg(&nvdimm_bus->dev, "failed to register ndctl%d: %d\n", + nvdimm_bus->id, rc); + goto err; + } + return 0; + +err: + put_device(dev); + return rc; } void nvdimm_bus_destroy_ndctl(struct nvdimm_bus *nvdimm_bus) diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c index 9d208570d059..dc7449a40003 100644 --- a/drivers/nvdimm/dimm_devs.c +++ b/drivers/nvdimm/dimm_devs.c @@ -642,6 +642,24 @@ struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus, } EXPORT_SYMBOL_GPL(__nvdimm_create); +void nvdimm_delete(struct nvdimm *nvdimm) +{ + struct device *dev = &nvdimm->dev; + bool dev_put = false; + + /* We are shutting down. Make state frozen artificially. */ + nvdimm_bus_lock(dev); + set_bit(NVDIMM_SECURITY_FROZEN, &nvdimm->sec.flags); + if (test_and_clear_bit(NDD_WORK_PENDING, &nvdimm->flags)) + dev_put = true; + nvdimm_bus_unlock(dev); + cancel_delayed_work_sync(&nvdimm->dwork); + if (dev_put) + put_device(dev); + nd_device_unregister(dev, ND_SYNC); +} +EXPORT_SYMBOL_GPL(nvdimm_delete); + static void shutdown_security_notify(void *data) { struct nvdimm *nvdimm = data; diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 80c656dcbbac..11779be42186 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -609,6 +609,7 @@ EXPORT_SYMBOL_NS_GPL(nvme_put_ns, NVME_TARGET_PASSTHRU); static inline void nvme_clear_nvme_request(struct request *req) { + nvme_req(req)->status = 0; nvme_req(req)->retries = 0; nvme_req(req)->flags = 0; req->rq_flags |= RQF_DONTPREP; @@ -631,6 +632,8 @@ static inline void nvme_init_request(struct request *req, cmd->common.flags &= ~NVME_CMD_SGL_ALL; req->cmd_flags |= REQ_FAILFAST_DRIVER; + if (req->mq_hctx->type == HCTX_TYPE_POLL) + req->cmd_flags |= REQ_HIPRI; nvme_clear_nvme_request(req); memcpy(nvme_req(req)->cmd, cmd, sizeof(*cmd)); } @@ -1029,29 +1032,23 @@ blk_status_t nvme_setup_cmd(struct nvme_ns *ns, struct request *req) } EXPORT_SYMBOL_GPL(nvme_setup_cmd); -static void nvme_end_sync_rq(struct request *rq, blk_status_t error) +/* + * Return values: + * 0: success + * >0: nvme controller's cqe status response + * <0: kernel error in lieu of controller response + */ +static int nvme_execute_rq(struct gendisk *disk, struct request *rq, + bool at_head) { - struct completion *waiting = rq->end_io_data; + blk_status_t status; - rq->end_io_data = NULL; - complete(waiting); -} - -static void nvme_execute_rq_polled(struct request_queue *q, - struct gendisk *bd_disk, struct request *rq, int at_head) -{ - DECLARE_COMPLETION_ONSTACK(wait); - - WARN_ON_ONCE(!test_bit(QUEUE_FLAG_POLL, &q->queue_flags)); - - rq->cmd_flags |= REQ_HIPRI; - rq->end_io_data = &wait; - blk_execute_rq_nowait(bd_disk, rq, at_head, nvme_end_sync_rq); - - while (!completion_done(&wait)) { - blk_poll(q, request_to_qc_t(rq->mq_hctx, rq), true); - cond_resched(); - } + status = blk_execute_rq(disk, rq, at_head); + if (nvme_req(rq)->flags & NVME_REQ_CANCELLED) + return -EINTR; + if (nvme_req(rq)->status) + return nvme_req(rq)->status; + return blk_status_to_errno(status); } /* @@ -1061,7 +1058,7 @@ static void nvme_execute_rq_polled(struct request_queue *q, int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, union nvme_result *result, void *buffer, unsigned bufflen, unsigned timeout, int qid, int at_head, - blk_mq_req_flags_t flags, bool poll) + blk_mq_req_flags_t flags) { struct request *req; int ret; @@ -1082,16 +1079,9 @@ int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, goto out; } - if (poll) - nvme_execute_rq_polled(req->q, NULL, req, at_head); - else - blk_execute_rq(NULL, req, at_head); - if (result) + ret = nvme_execute_rq(NULL, req, at_head); + if (result && ret >= 0) *result = nvme_req(req)->result; - if (nvme_req(req)->flags & NVME_REQ_CANCELLED) - ret = -EINTR; - else - ret = nvme_req(req)->status; out: blk_mq_free_request(req); return ret; @@ -1102,7 +1092,7 @@ int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, void *buffer, unsigned bufflen) { return __nvme_submit_sync_cmd(q, cmd, NULL, buffer, bufflen, 0, - NVME_QID_ANY, 0, 0, false); + NVME_QID_ANY, 0, 0); } EXPORT_SYMBOL_GPL(nvme_submit_sync_cmd); @@ -1179,18 +1169,21 @@ static void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects) } } -void nvme_execute_passthru_rq(struct request *rq) +int nvme_execute_passthru_rq(struct request *rq) { struct nvme_command *cmd = nvme_req(rq)->cmd; struct nvme_ctrl *ctrl = nvme_req(rq)->ctrl; struct nvme_ns *ns = rq->q->queuedata; struct gendisk *disk = ns ? ns->disk : NULL; u32 effects; + int ret; effects = nvme_passthru_start(ctrl, ns, cmd->common.opcode); - blk_execute_rq(disk, rq, 0); + ret = nvme_execute_rq(disk, rq, false); if (effects) /* nothing to be done for zero cmd effects */ nvme_passthru_end(ctrl, effects); + + return ret; } EXPORT_SYMBOL_NS_GPL(nvme_execute_passthru_rq, NVME_TARGET_PASSTHRU); @@ -1465,7 +1458,7 @@ static int nvme_features(struct nvme_ctrl *dev, u8 op, unsigned int fid, c.features.dword11 = cpu_to_le32(dword11); ret = __nvme_submit_sync_cmd(dev->admin_q, &c, &res, - buffer, buflen, 0, NVME_QID_ANY, 0, 0, false); + buffer, buflen, 0, NVME_QID_ANY, 0, 0); if (ret >= 0 && result) *result = le32_to_cpu(res.u32); return ret; @@ -2047,7 +2040,7 @@ int nvme_sec_submit(void *data, u16 spsp, u8 secp, void *buffer, size_t len, cmd.common.cdw11 = cpu_to_le32(len); return __nvme_submit_sync_cmd(ctrl->admin_q, &cmd, NULL, buffer, len, 0, - NVME_QID_ANY, 1, 0, false); + NVME_QID_ANY, 1, 0); } EXPORT_SYMBOL_GPL(nvme_sec_submit); #endif /* CONFIG_BLK_SED_OPAL */ diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c index 1e6a7cc056ca..a5469fd9d4c3 100644 --- a/drivers/nvme/host/fabrics.c +++ b/drivers/nvme/host/fabrics.c @@ -154,7 +154,7 @@ int nvmf_reg_read32(struct nvme_ctrl *ctrl, u32 off, u32 *val) cmd.prop_get.offset = cpu_to_le32(off); ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, &res, NULL, 0, 0, - NVME_QID_ANY, 0, 0, false); + NVME_QID_ANY, 0, 0); if (ret >= 0) *val = le64_to_cpu(res.u64); @@ -200,7 +200,7 @@ int nvmf_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val) cmd.prop_get.offset = cpu_to_le32(off); ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, &res, NULL, 0, 0, - NVME_QID_ANY, 0, 0, false); + NVME_QID_ANY, 0, 0); if (ret >= 0) *val = le64_to_cpu(res.u64); @@ -245,7 +245,7 @@ int nvmf_reg_write32(struct nvme_ctrl *ctrl, u32 off, u32 val) cmd.prop_set.value = cpu_to_le64(val); ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, NULL, NULL, 0, 0, - NVME_QID_ANY, 0, 0, false); + NVME_QID_ANY, 0, 0); if (unlikely(ret)) dev_err(ctrl->device, "Property Set error: %d, offset %#x\n", @@ -391,7 +391,7 @@ int nvmf_connect_admin_queue(struct nvme_ctrl *ctrl) ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, &res, data, sizeof(*data), 0, NVME_QID_ANY, 1, - BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT, false); + BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT); if (ret) { nvmf_log_connect_error(ctrl, ret, le32_to_cpu(res.u32), &cmd, data); @@ -415,7 +415,6 @@ EXPORT_SYMBOL_GPL(nvmf_connect_admin_queue); * @qid: NVMe I/O queue number for the new I/O connection between * host and target (note qid == 0 is illegal as this is * the Admin queue, per NVMe standard). - * @poll: Whether or not to poll for the completion of the connect cmd. * * This function issues a fabrics-protocol connection * of a NVMe I/O queue (via NVMe Fabrics "Connect" command) @@ -427,7 +426,7 @@ EXPORT_SYMBOL_GPL(nvmf_connect_admin_queue); * > 0: NVMe error status code * < 0: Linux errno error code */ -int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid, bool poll) +int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid) { struct nvme_command cmd = { }; struct nvmf_connect_data *data; @@ -453,7 +452,7 @@ int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid, bool poll) ret = __nvme_submit_sync_cmd(ctrl->connect_q, &cmd, &res, data, sizeof(*data), 0, qid, 1, - BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT, poll); + BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT); if (ret) { nvmf_log_connect_error(ctrl, ret, le32_to_cpu(res.u32), &cmd, data); diff --git a/drivers/nvme/host/fabrics.h b/drivers/nvme/host/fabrics.h index c31dad69a773..a146cb903869 100644 --- a/drivers/nvme/host/fabrics.h +++ b/drivers/nvme/host/fabrics.h @@ -182,7 +182,7 @@ int nvmf_reg_read32(struct nvme_ctrl *ctrl, u32 off, u32 *val); int nvmf_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val); int nvmf_reg_write32(struct nvme_ctrl *ctrl, u32 off, u32 val); int nvmf_connect_admin_queue(struct nvme_ctrl *ctrl); -int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid, bool poll); +int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid); int nvmf_register_transport(struct nvmf_transport_ops *ops); void nvmf_unregister_transport(struct nvmf_transport_ops *ops); void nvmf_free_options(struct nvmf_ctrl_options *opts); diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 95aad3fed571..b08a61ca283f 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -2346,7 +2346,7 @@ nvme_fc_connect_io_queues(struct nvme_fc_ctrl *ctrl, u16 qsize) (qsize / 5)); if (ret) break; - ret = nvmf_connect_io_queue(&ctrl->ctrl, i, false); + ret = nvmf_connect_io_queue(&ctrl->ctrl, i); if (ret) break; diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c index d93928d1e5bd..305ddd415e45 100644 --- a/drivers/nvme/host/ioctl.c +++ b/drivers/nvme/host/ioctl.c @@ -93,11 +93,7 @@ static int nvme_submit_user_cmd(struct request_queue *q, } } - nvme_execute_passthru_rq(req); - if (nvme_req(req)->flags & NVME_REQ_CANCELLED) - ret = -EINTR; - else - ret = nvme_req(req)->status; + ret = nvme_execute_passthru_rq(req); if (result) *result = le64_to_cpu(nvme_req(req)->result.u64); if (meta && !ret && !write) { diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 75420ceacc10..18ef8dd03a90 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -658,7 +658,7 @@ int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, union nvme_result *result, void *buffer, unsigned bufflen, unsigned timeout, int qid, int at_head, - blk_mq_req_flags_t flags, bool poll); + blk_mq_req_flags_t flags); int nvme_set_features(struct nvme_ctrl *dev, unsigned int fid, unsigned int dword11, void *buffer, size_t buflen, u32 *result); @@ -876,7 +876,7 @@ static inline bool nvme_ctrl_sgl_supported(struct nvme_ctrl *ctrl) u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opcode); -void nvme_execute_passthru_rq(struct request *rq); +int nvme_execute_passthru_rq(struct request *rq); struct nvme_ctrl *nvme_ctrl_from_file(struct file *file); struct nvme_ns *nvme_find_get_ns(struct nvme_ctrl *ctrl, unsigned nsid); void nvme_put_ns(struct nvme_ns *ns); diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index a9e70cefd7ed..7f6b3a991501 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -680,11 +680,10 @@ static void nvme_rdma_stop_io_queues(struct nvme_rdma_ctrl *ctrl) static int nvme_rdma_start_queue(struct nvme_rdma_ctrl *ctrl, int idx) { struct nvme_rdma_queue *queue = &ctrl->queues[idx]; - bool poll = nvme_rdma_poll_queue(queue); int ret; if (idx) - ret = nvmf_connect_io_queue(&ctrl->ctrl, idx, poll); + ret = nvmf_connect_io_queue(&ctrl->ctrl, idx); else ret = nvmf_connect_admin_queue(&ctrl->ctrl); diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index c7bd37103cf4..12acfe05cd68 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -1574,7 +1574,7 @@ static int nvme_tcp_start_queue(struct nvme_ctrl *nctrl, int idx) int ret; if (idx) - ret = nvmf_connect_io_queue(nctrl, idx, false); + ret = nvmf_connect_io_queue(nctrl, idx); else ret = nvmf_connect_admin_queue(nctrl); diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c index a5c4a1865026..3a17a7e26bbf 100644 --- a/drivers/nvme/target/loop.c +++ b/drivers/nvme/target/loop.c @@ -337,7 +337,7 @@ static int nvme_loop_connect_io_queues(struct nvme_loop_ctrl *ctrl) int i, ret; for (i = 1; i < ctrl->ctrl.queue_count; i++) { - ret = nvmf_connect_io_queue(&ctrl->ctrl, i, false); + ret = nvmf_connect_io_queue(&ctrl->ctrl, i); if (ret) return ret; set_bit(NVME_LOOP_Q_LIVE, &ctrl->queues[i].flags); diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c index fced52de33ce..225cd1ffbe45 100644 --- a/drivers/nvme/target/passthru.c +++ b/drivers/nvme/target/passthru.c @@ -153,11 +153,10 @@ static void nvmet_passthru_execute_cmd_work(struct work_struct *w) { struct nvmet_req *req = container_of(w, struct nvmet_req, p.work); struct request *rq = req->p.rq; - u16 status; + int status; - nvme_execute_passthru_rq(rq); + status = nvme_execute_passthru_rq(rq); - status = nvme_req(rq)->status; if (status == NVME_SC_SUCCESS && req->cmd->common.opcode == nvme_admin_identify) { switch (req->cmd->identify.cns) { @@ -168,7 +167,8 @@ static void nvmet_passthru_execute_cmd_work(struct work_struct *w) nvmet_passthru_override_id_ns(req); break; } - } + } else if (status < 0) + status = NVME_SC_INTERNAL; req->cqe->result = nvme_req(rq)->result; nvmet_req_complete(req, status); diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c index d8aceef83284..07ee347ea3f3 100644 --- a/drivers/nvme/target/tcp.c +++ b/drivers/nvme/target/tcp.c @@ -1497,7 +1497,6 @@ static void nvmet_tcp_state_change(struct sock *sk) case TCP_CLOSE_WAIT: case TCP_CLOSE: /* FALLTHRU */ - sk->sk_user_data = NULL; nvmet_tcp_schedule_release_queue(queue); break; default: diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index bca671ff4e54..b3bc30a04ed7 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -180,6 +180,7 @@ static const char * const nvmem_type_str[] = { [NVMEM_TYPE_EEPROM] = "EEPROM", [NVMEM_TYPE_OTP] = "OTP", [NVMEM_TYPE_BATTERY_BACKED] = "Battery backed", + [NVMEM_TYPE_FRAM] = "FRAM", }; #ifdef CONFIG_DEBUG_LOCK_ALLOC @@ -359,6 +360,9 @@ static int nvmem_sysfs_setup_compat(struct nvmem_device *nvmem, if (!config->base_dev) return -EINVAL; + if (config->type == NVMEM_TYPE_FRAM) + bin_attr_nvmem_eeprom_compat.attr.name = "fram"; + nvmem->eeprom = bin_attr_nvmem_eeprom_compat; nvmem->eeprom.attr.mode = nvmem_bin_attr_get_umode(nvmem); nvmem->eeprom.size = nvmem->size; @@ -686,15 +690,17 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) continue; if (len < 2 * sizeof(u32)) { dev_err(dev, "nvmem: invalid reg on %pOF\n", child); + of_node_put(child); return -EINVAL; } cell = kzalloc(sizeof(*cell), GFP_KERNEL); - if (!cell) + if (!cell) { + of_node_put(child); return -ENOMEM; + } cell->nvmem = nvmem; - cell->np = of_node_get(child); cell->offset = be32_to_cpup(addr++); cell->bytes = be32_to_cpup(addr); cell->name = kasprintf(GFP_KERNEL, "%pOFn", child); @@ -715,11 +721,12 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) cell->name, nvmem->stride); /* Cells already added will be freed later. */ kfree_const(cell->name); - of_node_put(cell->np); kfree(cell); + of_node_put(child); return -EINVAL; } + cell->np = of_node_get(child); nvmem_cell_add(cell); } @@ -789,7 +796,9 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) nvmem->reg_write = config->reg_write; nvmem->keepout = config->keepout; nvmem->nkeepout = config->nkeepout; - if (!config->no_of_node) + if (config->of_node) + nvmem->dev.of_node = config->of_node; + else if (!config->no_of_node) nvmem->dev.of_node = config->dev->of_node; switch (config->id) { @@ -1606,9 +1615,9 @@ int nvmem_cell_read_u64(struct device *dev, const char *cell_id, u64 *val) } EXPORT_SYMBOL_GPL(nvmem_cell_read_u64); -static void *nvmem_cell_read_variable_common(struct device *dev, - const char *cell_id, - size_t max_len, size_t *len) +static const void *nvmem_cell_read_variable_common(struct device *dev, + const char *cell_id, + size_t max_len, size_t *len) { struct nvmem_cell *cell; int nbits; @@ -1652,7 +1661,7 @@ int nvmem_cell_read_variable_le_u32(struct device *dev, const char *cell_id, u32 *val) { size_t len; - u8 *buf; + const u8 *buf; int i; buf = nvmem_cell_read_variable_common(dev, cell_id, sizeof(*val), &len); @@ -1683,7 +1692,7 @@ int nvmem_cell_read_variable_le_u64(struct device *dev, const char *cell_id, u64 *val) { size_t len; - u8 *buf; + const u8 *buf; int i; buf = nvmem_cell_read_variable_common(dev, cell_id, sizeof(*val), &len); diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c index d6d3f24685a8..81fbad5e939d 100644 --- a/drivers/nvmem/qfprom.c +++ b/drivers/nvmem/qfprom.c @@ -122,6 +122,7 @@ static const struct qfprom_soc_compatible_data sc7280_qfprom = { .keepout = sc7280_qfprom_keepout, .nkeepout = ARRAY_SIZE(sc7280_qfprom_keepout) }; + /** * qfprom_disable_fuse_blowing() - Undo enabling of fuse blowing. * @priv: Our driver data. @@ -195,9 +196,9 @@ static int qfprom_enable_fuse_blowing(const struct qfprom_priv *priv, } /* - * Hardware requires 1.8V min for fuse blowing; this may be - * a rail shared do don't specify a max--regulator constraints - * will handle. + * Hardware requires a minimum voltage for fuse blowing. + * This may be a shared rail so don't specify a maximum. + * Regulator constraints will cap to the actual maximum. */ ret = regulator_set_voltage(priv->vcc, qfprom_blow_uV, INT_MAX); if (ret) { @@ -399,7 +400,7 @@ static int qfprom_probe(struct platform_device *pdev) if (major_version == 7 && minor_version == 8) priv->soc_data = &qfprom_7_8_data; - if (major_version == 7 && minor_version == 15) + else if (major_version == 7 && minor_version == 15) priv->soc_data = &qfprom_7_15_data; priv->vcc = devm_regulator_get(&pdev->dev, "vcc"); diff --git a/drivers/nvmem/sprd-efuse.c b/drivers/nvmem/sprd-efuse.c index 59523245db8a..4f1fcbfec394 100644 --- a/drivers/nvmem/sprd-efuse.c +++ b/drivers/nvmem/sprd-efuse.c @@ -234,7 +234,7 @@ static int sprd_efuse_raw_prog(struct sprd_efuse *efuse, u32 blk, bool doub, status = readl(efuse->base + SPRD_EFUSE_ERR_FLAG); if (status) { dev_err(efuse->dev, - "write error status %d of block %d\n", ret, blk); + "write error status %u of block %d\n", status, blk); writel(SPRD_EFUSE_ERR_CLR_MASK, efuse->base + SPRD_EFUSE_ERR_CLR); diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c index e26ef1bbf198..275b9155e473 100644 --- a/drivers/nvmem/sunxi_sid.c +++ b/drivers/nvmem/sunxi_sid.c @@ -142,6 +142,7 @@ static int sunxi_sid_probe(struct platform_device *pdev) nvmem_cfg->dev = dev; nvmem_cfg->name = "sunxi-sid"; + nvmem_cfg->type = NVMEM_TYPE_OTP; nvmem_cfg->read_only = true; nvmem_cfg->size = cfg->size; nvmem_cfg->word_size = 1; diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 18450437d5d5..3dfeae8912df 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -75,9 +75,7 @@ config OF_NET def_bool y config OF_RESERVED_MEM - bool - depends on OF_EARLY_FLATTREE - default y if DMA_DECLARE_COHERENT || DMA_CMA + def_bool OF_EARLY_FLATTREE config OF_RESOLVE bool diff --git a/drivers/of/address.c b/drivers/of/address.c index aca94c348bd4..94f017d808c4 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -23,9 +23,8 @@ #define OF_CHECK_COUNTS(na, ns) (OF_CHECK_ADDR_COUNT(na) && (ns) > 0) static struct of_bus *of_match_bus(struct device_node *np); -static int __of_address_to_resource(struct device_node *dev, - const __be32 *addrp, u64 size, unsigned int flags, - const char *name, struct resource *r); +static int __of_address_to_resource(struct device_node *dev, int index, + int bar_no, struct resource *r); static bool of_mmio_is_nonposted(struct device_node *np); /* Debug utility */ @@ -77,9 +76,7 @@ static u64 of_bus_default_map(__be32 *addr, const __be32 *range, s = of_read_number(range + na + pna, ns); da = of_read_number(addr, na); - pr_debug("default map, cp=%llx, s=%llx, da=%llx\n", - (unsigned long long)cp, (unsigned long long)s, - (unsigned long long)da); + pr_debug("default map, cp=%llx, s=%llx, da=%llx\n", cp, s, da); if (da < cp || da >= (cp + s)) return OF_BAD_ADDR; @@ -185,9 +182,7 @@ static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns, s = of_read_number(range + na + pna, ns); da = of_read_number(addr + 1, na - 1); - pr_debug("PCI map, cp=%llx, s=%llx, da=%llx\n", - (unsigned long long)cp, (unsigned long long)s, - (unsigned long long)da); + pr_debug("PCI map, cp=%llx, s=%llx, da=%llx\n", cp, s, da); if (da < cp || da >= (cp + s)) return OF_BAD_ADDR; @@ -198,62 +193,16 @@ static int of_bus_pci_translate(__be32 *addr, u64 offset, int na) { return of_bus_default_translate(addr + 1, offset, na - 1); } - -const __be32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, - unsigned int *flags) -{ - const __be32 *prop; - unsigned int psize; - struct device_node *parent; - struct of_bus *bus; - int onesize, i, na, ns; - - /* Get parent & match bus type */ - parent = of_get_parent(dev); - if (parent == NULL) - return NULL; - bus = of_match_bus(parent); - if (strcmp(bus->name, "pci")) { - of_node_put(parent); - return NULL; - } - bus->count_cells(dev, &na, &ns); - of_node_put(parent); - if (!OF_CHECK_ADDR_COUNT(na)) - return NULL; - - /* Get "reg" or "assigned-addresses" property */ - prop = of_get_property(dev, bus->addresses, &psize); - if (prop == NULL) - return NULL; - psize /= 4; - - onesize = na + ns; - for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) { - u32 val = be32_to_cpu(prop[0]); - if ((val & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) { - if (size) - *size = of_read_number(prop + na, ns); - if (flags) - *flags = bus->get_flags(prop); - return prop; - } - } - return NULL; -} -EXPORT_SYMBOL(of_get_pci_address); +#endif /* CONFIG_PCI */ int of_pci_address_to_resource(struct device_node *dev, int bar, struct resource *r) { - const __be32 *addrp; - u64 size; - unsigned int flags; - addrp = of_get_pci_address(dev, bar, &size, &flags); - if (addrp == NULL) - return -EINVAL; - return __of_address_to_resource(dev, addrp, size, flags, NULL, r); + if (!IS_ENABLED(CONFIG_PCI)) + return -ENOSYS; + + return __of_address_to_resource(dev, -1, bar, r); } EXPORT_SYMBOL_GPL(of_pci_address_to_resource); @@ -280,6 +229,9 @@ int of_pci_range_to_resource(struct of_pci_range *range, res->parent = res->child = res->sibling = NULL; res->name = np->full_name; + if (!IS_ENABLED(CONFIG_PCI)) + return -ENOSYS; + if (res->flags & IORESOURCE_IO) { unsigned long port; err = pci_register_io_range(&np->fwnode, range->cpu_addr, @@ -310,7 +262,6 @@ invalid_range: return err; } EXPORT_SYMBOL(of_pci_range_to_resource); -#endif /* CONFIG_PCI */ /* * ISA bus specific translator @@ -344,9 +295,7 @@ static u64 of_bus_isa_map(__be32 *addr, const __be32 *range, int na, int ns, s = of_read_number(range + na + pna, ns); da = of_read_number(addr + 1, na - 1); - pr_debug("ISA map, cp=%llx, s=%llx, da=%llx\n", - (unsigned long long)cp, (unsigned long long)s, - (unsigned long long)da); + pr_debug("ISA map, cp=%llx, s=%llx, da=%llx\n", cp, s, da); if (da < cp || da >= (cp + s)) return OF_BAD_ADDR; @@ -501,7 +450,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, finish: of_dump_addr("parent translation for:", addr, pna); - pr_debug("with offset: %llx\n", (unsigned long long)offset); + pr_debug("with offset: %llx\n", offset); /* Translate it into parent bus space */ return pbus->translate(addr, offset, pna); @@ -675,8 +624,8 @@ u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr) } EXPORT_SYMBOL(of_translate_dma_address); -const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, - unsigned int *flags) +const __be32 *__of_get_address(struct device_node *dev, int index, int bar_no, + u64 *size, unsigned int *flags) { const __be32 *prop; unsigned int psize; @@ -689,6 +638,10 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, if (parent == NULL) return NULL; bus = of_match_bus(parent); + if (strcmp(bus->name, "pci") && (bar_no >= 0)) { + of_node_put(parent); + return NULL; + } bus->count_cells(dev, &na, &ns); of_node_put(parent); if (!OF_CHECK_ADDR_COUNT(na)) @@ -701,17 +654,21 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, psize /= 4; onesize = na + ns; - for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) - if (i == index) { + for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) { + u32 val = be32_to_cpu(prop[0]); + /* PCI bus matches on BAR number instead of index */ + if (((bar_no >= 0) && ((val & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0))) || + ((index >= 0) && (i == index))) { if (size) *size = of_read_number(prop + na, ns); if (flags) *flags = bus->get_flags(prop); return prop; } + } return NULL; } -EXPORT_SYMBOL(of_get_address); +EXPORT_SYMBOL(__of_get_address); static int parser_init(struct of_pci_range_parser *parser, struct device_node *node, const char *name) @@ -834,11 +791,22 @@ static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr, return port; } -static int __of_address_to_resource(struct device_node *dev, - const __be32 *addrp, u64 size, unsigned int flags, - const char *name, struct resource *r) +static int __of_address_to_resource(struct device_node *dev, int index, int bar_no, + struct resource *r) { u64 taddr; + const __be32 *addrp; + u64 size; + unsigned int flags; + const char *name = NULL; + + addrp = __of_get_address(dev, index, bar_no, &size, &flags); + if (addrp == NULL) + return -EINVAL; + + /* Get optional "reg-names" property to add a name to a resource */ + if (index >= 0) + of_property_read_string_index(dev, "reg-names", index, &name); if (flags & IORESOURCE_MEM) taddr = of_translate_address(dev, addrp); @@ -876,19 +844,7 @@ static int __of_address_to_resource(struct device_node *dev, int of_address_to_resource(struct device_node *dev, int index, struct resource *r) { - const __be32 *addrp; - u64 size; - unsigned int flags; - const char *name = NULL; - - addrp = of_get_address(dev, index, &size, &flags); - if (addrp == NULL) - return -EINVAL; - - /* Get optional "reg-names" property to add a name to a resource */ - of_property_read_string_index(dev, "reg-names", index, &name); - - return __of_address_to_resource(dev, addrp, size, flags, name, r); + return __of_address_to_resource(dev, index, -1, r); } EXPORT_SYMBOL_GPL(of_address_to_resource); diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index ba17a80b8c79..e0f96e3ef1da 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -510,11 +510,11 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, if (size && early_init_dt_reserve_memory_arch(base, size, nomap) == 0) - pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n", - uname, &base, (unsigned long)size / SZ_1M); + pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %lu MiB\n", + uname, &base, (unsigned long)(size / SZ_1M)); else - pr_info("Reserved memory: failed to reserve memory for node '%s': base %pa, size %ld MiB\n", - uname, &base, (unsigned long)size / SZ_1M); + pr_info("Reserved memory: failed to reserve memory for node '%s': base %pa, size %lu MiB\n", + uname, &base, (unsigned long)(size / SZ_1M)); len -= t_len; if (first) { @@ -900,8 +900,7 @@ static void __init early_init_dt_check_for_initrd(unsigned long node) phys_initrd_start = start; phys_initrd_size = end - start; - pr_debug("initrd_start=0x%llx initrd_end=0x%llx\n", - (unsigned long long)start, (unsigned long long)end); + pr_debug("initrd_start=0x%llx initrd_end=0x%llx\n", start, end); } #else static inline void early_init_dt_check_for_initrd(unsigned long node) @@ -1027,8 +1026,7 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname, if (size == 0) continue; - pr_debug(" - %llx , %llx\n", (unsigned long long)base, - (unsigned long long)size); + pr_debug(" - %llx, %llx\n", base, size); early_init_dt_add_memory_arch(base, size); diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h index d717efbd637d..631489f7f8c0 100644 --- a/drivers/of/of_private.h +++ b/drivers/of/of_private.h @@ -171,4 +171,8 @@ static inline int of_dma_get_range(struct device_node *np, } #endif +void fdt_init_reserved_mem(void); +void fdt_reserved_mem_save_node(unsigned long node, const char *uname, + phys_addr_t base, phys_addr_t size); + #endif /* _LINUX_OF_PRIVATE_H */ diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 15e2417974d6..fd3964d24224 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -22,6 +22,8 @@ #include <linux/slab.h> #include <linux/memblock.h> +#include "of_private.h" + #define MAX_RESERVED_REGIONS 64 static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS]; static int reserved_mem_count; @@ -40,7 +42,7 @@ static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, *res_base = base; if (nomap) - return memblock_remove(base, size); + return memblock_mark_nomap(base, size); return memblock_reserve(base, size); } @@ -134,9 +136,9 @@ static int __init __reserved_mem_alloc_size(unsigned long node, ret = early_init_dt_alloc_reserved_memory_arch(size, align, start, end, nomap, &base); if (ret == 0) { - pr_debug("allocated memory for '%s' node: base %pa, size %ld MiB\n", + pr_debug("allocated memory for '%s' node: base %pa, size %lu MiB\n", uname, &base, - (unsigned long)size / SZ_1M); + (unsigned long)(size / SZ_1M)); break; } len -= t_len; @@ -146,8 +148,8 @@ static int __init __reserved_mem_alloc_size(unsigned long node, ret = early_init_dt_alloc_reserved_memory_arch(size, align, 0, 0, nomap, &base); if (ret == 0) - pr_debug("allocated memory for '%s' node: base %pa, size %ld MiB\n", - uname, &base, (unsigned long)size / SZ_1M); + pr_debug("allocated memory for '%s' node: base %pa, size %lu MiB\n", + uname, &base, (unsigned long)(size / SZ_1M)); } if (base == 0) { @@ -273,9 +275,10 @@ void __init fdt_init_reserved_mem(void) if (err != 0 && err != -ENOENT) { pr_info("node %s compatible matching fail\n", rmem->name); - memblock_free(rmem->base, rmem->size); if (nomap) - memblock_add(rmem->base, rmem->size); + memblock_clear_nomap(rmem->base, rmem->size); + else + memblock_free(rmem->base, rmem->size); } } } diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 819a20acaa93..8c056972a6dd 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -1209,11 +1209,7 @@ static void __init of_unittest_match_node(void) } } -static struct resource test_bus_res = { - .start = 0xfffffff8, - .end = 0xfffffff9, - .flags = IORESOURCE_MEM, -}; +static struct resource test_bus_res = DEFINE_RES_MEM(0xfffffff8, 2); static const struct platform_device_info test_bus_info = { .name = "unittest-bus", }; diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c index 7e6d713fa5ac..5d1b9aacb130 100644 --- a/drivers/parport/probe.c +++ b/drivers/parport/probe.c @@ -8,8 +8,8 @@ #include <linux/module.h> #include <linux/parport.h> -#include <linux/ctype.h> #include <linux/string.h> +#include <linux/string_helpers.h> #include <linux/slab.h> #include <linux/uaccess.h> @@ -74,11 +74,7 @@ static void parse_data(struct parport *port, int device, char *str) u = sep + strlen (sep) - 1; while (u >= p && *u == ' ') *u-- = '\0'; - u = p; - while (*u) { - *u = toupper(*u); - u++; - } + string_upper(p, p); if (!strcmp(p, "MFG") || !strcmp(p, "MANUFACTURER")) { kfree(info->mfr); info->mfr = kstrdup(sep, GFP_KERNEL); @@ -90,8 +86,7 @@ static void parse_data(struct parport *port, int device, char *str) kfree(info->class_name); info->class_name = kstrdup(sep, GFP_KERNEL); - for (u = sep; *u; u++) - *u = toupper(*u); + string_upper(sep, sep); for (i = 0; classes[i].token; i++) { if (!strcmp(classes[i].token, sep)) { info->class = i; diff --git a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h index 254d2570f8c9..30db2d68c17a 100644 --- a/drivers/pci/controller/cadence/pcie-cadence.h +++ b/drivers/pci/controller/cadence/pcie-cadence.h @@ -263,9 +263,12 @@ struct cdns_pcie_ops { * struct cdns_pcie - private data for Cadence PCIe controller drivers * @reg_base: IO mapped register base * @mem_res: start/end offsets in the physical system memory to map PCI accesses + * @dev: PCIe controller * @is_rc: tell whether the PCIe controller mode is Root Complex or Endpoint. - * @bus: In Root Complex mode, the bus number - * @ops: Platform specific ops to control various inputs from Cadence PCIe + * @phy_count: number of supported PHY devices + * @phy: list of pointers to specific PHY control blocks + * @link: list of pointers to corresponding device link representations + * @ops: Platform-specific ops to control various inputs from Cadence PCIe * wrapper */ struct cdns_pcie { diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 0cf1333c0440..80fc98acf097 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -37,6 +37,7 @@ #define IMX8MQ_GPR_PCIE_REF_USE_PAD BIT(9) #define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN BIT(10) #define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE BIT(11) +#define IMX8MQ_GPR_PCIE_VREG_BYPASS BIT(12) #define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE GENMASK(11, 8) #define IMX8MQ_PCIE2_BASE_ADDR 0x33c00000 @@ -80,6 +81,7 @@ struct imx6_pcie { u32 tx_swing_full; u32 tx_swing_low; struct regulator *vpcie; + struct regulator *vph; void __iomem *phy_base; /* power domain for pcie */ @@ -621,6 +623,17 @@ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) imx6_pcie_grp_offset(imx6_pcie), IMX8MQ_GPR_PCIE_REF_USE_PAD, IMX8MQ_GPR_PCIE_REF_USE_PAD); + /* + * Regarding the datasheet, the PCIE_VPH is suggested + * to be 1.8V. If the PCIE_VPH is supplied by 3.3V, the + * VREG_BYPASS should be cleared to zero. + */ + if (imx6_pcie->vph && + regulator_get_voltage(imx6_pcie->vph) > 3000000) + regmap_update_bits(imx6_pcie->iomuxc_gpr, + imx6_pcie_grp_offset(imx6_pcie), + IMX8MQ_GPR_PCIE_VREG_BYPASS, + 0); break; case IMX7D: regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, @@ -1002,10 +1015,8 @@ static int imx6_pcie_probe(struct platform_device *pdev) return ret; } imx6_pcie->phy_base = devm_ioremap_resource(dev, &res); - if (IS_ERR(imx6_pcie->phy_base)) { - dev_err(dev, "Unable to map PCIe PHY\n"); + if (IS_ERR(imx6_pcie->phy_base)) return PTR_ERR(imx6_pcie->phy_base); - } } dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1130,6 +1141,13 @@ static int imx6_pcie_probe(struct platform_device *pdev) imx6_pcie->vpcie = NULL; } + imx6_pcie->vph = devm_regulator_get_optional(&pdev->dev, "vph"); + if (IS_ERR(imx6_pcie->vph)) { + if (PTR_ERR(imx6_pcie->vph) != -ENODEV) + return PTR_ERR(imx6_pcie->vph); + imx6_pcie->vph = NULL; + } + platform_set_drvdata(pdev, imx6_pcie); ret = imx6_pcie_attach_pd(dev); @@ -1175,6 +1193,7 @@ static const struct imx6_pcie_drvdata drvdata[] = { .variant = IMX6QP, .flags = IMX6_PCIE_FLAG_IMX6_PHY | IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE, + .dbi_length = 0x200, }, [IMX7D] = { .variant = IMX7D, diff --git a/drivers/pci/controller/dwc/pcie-intel-gw.c b/drivers/pci/controller/dwc/pcie-intel-gw.c index f89a7d24ba28..d15cf35fa7f2 100644 --- a/drivers/pci/controller/dwc/pcie-intel-gw.c +++ b/drivers/pci/controller/dwc/pcie-intel-gw.c @@ -39,6 +39,10 @@ #define PCIE_APP_IRN_PM_TO_ACK BIT(9) #define PCIE_APP_IRN_LINK_AUTO_BW_STAT BIT(11) #define PCIE_APP_IRN_BW_MGT BIT(12) +#define PCIE_APP_IRN_INTA BIT(13) +#define PCIE_APP_IRN_INTB BIT(14) +#define PCIE_APP_IRN_INTC BIT(15) +#define PCIE_APP_IRN_INTD BIT(16) #define PCIE_APP_IRN_MSG_LTR BIT(18) #define PCIE_APP_IRN_SYS_ERR_RC BIT(29) #define PCIE_APP_INTX_OFST 12 @@ -48,10 +52,8 @@ PCIE_APP_IRN_RX_VDM_MSG | PCIE_APP_IRN_SYS_ERR_RC | \ PCIE_APP_IRN_PM_TO_ACK | PCIE_APP_IRN_MSG_LTR | \ PCIE_APP_IRN_BW_MGT | PCIE_APP_IRN_LINK_AUTO_BW_STAT | \ - (PCIE_APP_INTX_OFST + PCI_INTERRUPT_INTA) | \ - (PCIE_APP_INTX_OFST + PCI_INTERRUPT_INTB) | \ - (PCIE_APP_INTX_OFST + PCI_INTERRUPT_INTC) | \ - (PCIE_APP_INTX_OFST + PCI_INTERRUPT_INTD)) + PCIE_APP_IRN_INTA | PCIE_APP_IRN_INTB | \ + PCIE_APP_IRN_INTC | PCIE_APP_IRN_INTD) #define BUS_IATU_OFFSET SZ_256M #define RESET_INTERVAL_MS 100 diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c index 504669e3afe0..3ec7b29d5dc7 100644 --- a/drivers/pci/controller/dwc/pcie-tegra194.c +++ b/drivers/pci/controller/dwc/pcie-tegra194.c @@ -1826,7 +1826,7 @@ static int tegra_pcie_ep_raise_msi_irq(struct tegra_pcie_dw *pcie, u16 irq) if (unlikely(irq > 31)) return -EINVAL; - appl_writel(pcie, (1 << irq), APPL_MSI_CTRL_1); + appl_writel(pcie, BIT(irq), APPL_MSI_CTRL_1); return 0; } @@ -2214,6 +2214,8 @@ static int tegra_pcie_dw_resume_noirq(struct device *dev) goto fail_host_init; } + dw_pcie_setup_rc(&pcie->pci.pp); + ret = tegra_pcie_dw_start_link(&pcie->pci); if (ret < 0) goto fail_host_init; diff --git a/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c index ee0156921ebc..306950272fd6 100644 --- a/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c +++ b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c @@ -42,17 +42,6 @@ struct ls_pcie_g4 { int irq; }; -static inline u32 ls_pcie_g4_lut_readl(struct ls_pcie_g4 *pcie, u32 off) -{ - return ioread32(pcie->pci.csr_axi_slave_base + PCIE_LUT_OFF + off); -} - -static inline void ls_pcie_g4_lut_writel(struct ls_pcie_g4 *pcie, - u32 off, u32 val) -{ - iowrite32(val, pcie->pci.csr_axi_slave_base + PCIE_LUT_OFF + off); -} - static inline u32 ls_pcie_g4_pf_readl(struct ls_pcie_g4 *pcie, u32 off) { return ioread32(pcie->pci.csr_axi_slave_base + PCIE_PF_OFF + off); diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c index e3f5e7ab7606..c95ebe808f92 100644 --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c @@ -57,7 +57,7 @@ #define PIO_COMPLETION_STATUS_UR 1 #define PIO_COMPLETION_STATUS_CRS 2 #define PIO_COMPLETION_STATUS_CA 4 -#define PIO_NON_POSTED_REQ BIT(0) +#define PIO_NON_POSTED_REQ BIT(10) #define PIO_ADDR_LS (PIO_BASE_ADDR + 0x8) #define PIO_ADDR_MS (PIO_BASE_ADDR + 0xc) #define PIO_WR_DATA (PIO_BASE_ADDR + 0x10) @@ -125,6 +125,7 @@ #define LTSSM_MASK 0x3f #define LTSSM_L0 0x10 #define RC_BAR_CONFIG 0x300 +#define VENDOR_ID_REG (LMI_BASE_ADDR + 0x44) /* PCIe core controller registers */ #define CTRL_CORE_BASE_ADDR 0x18000 @@ -385,6 +386,16 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie) reg |= (IS_RC_MSK << IS_RC_SHIFT); advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); + /* + * Replace incorrect PCI vendor id value 0x1b4b by correct value 0x11ab. + * VENDOR_ID_REG contains vendor id in low 16 bits and subsystem vendor + * id in high 16 bits. Updating this register changes readback value of + * read-only vendor id bits in PCIE_CORE_DEV_ID_REG register. Workaround + * for erratum 4.1: "The value of device and vendor ID is incorrect". + */ + reg = (PCI_VENDOR_ID_MARVELL << 16) | PCI_VENDOR_ID_MARVELL; + advk_writel(pcie, reg, VENDOR_ID_REG); + /* Set Advanced Error Capabilities and Control PF0 register */ reg = PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX | PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN | diff --git a/drivers/pci/controller/pci-ftpci100.c b/drivers/pci/controller/pci-ftpci100.c index da3cd216da00..aefef1986201 100644 --- a/drivers/pci/controller/pci-ftpci100.c +++ b/drivers/pci/controller/pci-ftpci100.c @@ -34,12 +34,12 @@ * Special configuration registers directly in the first few words * in I/O space. */ -#define PCI_IOSIZE 0x00 -#define PCI_PROT 0x04 /* AHB protection */ -#define PCI_CTRL 0x08 /* PCI control signal */ -#define PCI_SOFTRST 0x10 /* Soft reset counter and response error enable */ -#define PCI_CONFIG 0x28 /* PCI configuration command register */ -#define PCI_DATA 0x2C +#define FTPCI_IOSIZE 0x00 +#define FTPCI_PROT 0x04 /* AHB protection */ +#define FTPCI_CTRL 0x08 /* PCI control signal */ +#define FTPCI_SOFTRST 0x10 /* Soft reset counter and response error enable */ +#define FTPCI_CONFIG 0x28 /* PCI configuration command register */ +#define FTPCI_DATA 0x2C #define FARADAY_PCI_STATUS_CMD 0x04 /* Status and command */ #define FARADAY_PCI_PMC 0x40 /* Power management control */ @@ -195,9 +195,9 @@ static int faraday_raw_pci_read_config(struct faraday_pci *p, int bus_number, PCI_CONF_FUNCTION(PCI_FUNC(fn)) | PCI_CONF_WHERE(config) | PCI_CONF_ENABLE, - p->base + PCI_CONFIG); + p->base + FTPCI_CONFIG); - *value = readl(p->base + PCI_DATA); + *value = readl(p->base + FTPCI_DATA); if (size == 1) *value = (*value >> (8 * (config & 3))) & 0xFF; @@ -230,17 +230,17 @@ static int faraday_raw_pci_write_config(struct faraday_pci *p, int bus_number, PCI_CONF_FUNCTION(PCI_FUNC(fn)) | PCI_CONF_WHERE(config) | PCI_CONF_ENABLE, - p->base + PCI_CONFIG); + p->base + FTPCI_CONFIG); switch (size) { case 4: - writel(value, p->base + PCI_DATA); + writel(value, p->base + FTPCI_DATA); break; case 2: - writew(value, p->base + PCI_DATA + (config & 3)); + writew(value, p->base + FTPCI_DATA + (config & 3)); break; case 1: - writeb(value, p->base + PCI_DATA + (config & 3)); + writeb(value, p->base + FTPCI_DATA + (config & 3)); break; default: ret = PCIBIOS_BAD_REGISTER_NUMBER; @@ -469,7 +469,7 @@ static int faraday_pci_probe(struct platform_device *pdev) if (!faraday_res_to_memcfg(io->start - win->offset, resource_size(io), &val)) { /* setup I/O space size */ - writel(val, p->base + PCI_IOSIZE); + writel(val, p->base + FTPCI_IOSIZE); } else { dev_err(dev, "illegal IO mem size\n"); return -EINVAL; @@ -477,11 +477,11 @@ static int faraday_pci_probe(struct platform_device *pdev) } /* Setup hostbridge */ - val = readl(p->base + PCI_CTRL); + val = readl(p->base + FTPCI_CTRL); val |= PCI_COMMAND_IO; val |= PCI_COMMAND_MEMORY; val |= PCI_COMMAND_MASTER; - writel(val, p->base + PCI_CTRL); + writel(val, p->base + FTPCI_CTRL); /* Mask and clear all interrupts */ faraday_raw_pci_write_config(p, 0, 0, FARADAY_PCI_CTRL2 + 2, 2, 0xF000); if (variant->cascaded_irq) { diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index bebe3eeebc4e..a53bd8728d0d 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -444,7 +444,6 @@ enum hv_pcibus_state { hv_pcibus_probed, hv_pcibus_installed, hv_pcibus_removing, - hv_pcibus_removed, hv_pcibus_maximum }; @@ -453,7 +452,6 @@ struct hv_pcibus_device { /* Protocol version negotiated with the host */ enum pci_protocol_version_t protocol_version; enum hv_pcibus_state state; - refcount_t remove_lock; struct hv_device *hdev; resource_size_t low_mmio_space; resource_size_t high_mmio_space; @@ -461,7 +459,6 @@ struct hv_pcibus_device { struct resource *low_mmio_res; struct resource *high_mmio_res; struct completion *survey_event; - struct completion remove_event; struct pci_bus *pci_bus; spinlock_t config_lock; /* Avoid two threads writing index page */ spinlock_t device_list_lock; /* Protect lists below */ @@ -593,9 +590,6 @@ static void put_pcichild(struct hv_pci_dev *hpdev) kfree(hpdev); } -static void get_hvpcibus(struct hv_pcibus_device *hv_pcibus); -static void put_hvpcibus(struct hv_pcibus_device *hv_pcibus); - /* * There is no good way to get notified from vmbus_onoffer_rescind(), * so let's use polling here, since this is not a hot path. @@ -2064,10 +2058,8 @@ static void pci_devices_present_work(struct work_struct *work) } spin_unlock_irqrestore(&hbus->device_list_lock, flags); - if (!dr) { - put_hvpcibus(hbus); + if (!dr) return; - } /* First, mark all existing children as reported missing. */ spin_lock_irqsave(&hbus->device_list_lock, flags); @@ -2150,7 +2142,6 @@ static void pci_devices_present_work(struct work_struct *work) break; } - put_hvpcibus(hbus); kfree(dr); } @@ -2191,12 +2182,10 @@ static int hv_pci_start_relations_work(struct hv_pcibus_device *hbus, list_add_tail(&dr->list_entry, &hbus->dr_list); spin_unlock_irqrestore(&hbus->device_list_lock, flags); - if (pending_dr) { + if (pending_dr) kfree(dr_wrk); - } else { - get_hvpcibus(hbus); + else queue_work(hbus->wq, &dr_wrk->wrk); - } return 0; } @@ -2339,8 +2328,6 @@ static void hv_eject_device_work(struct work_struct *work) put_pcichild(hpdev); put_pcichild(hpdev); /* hpdev has been freed. Do not use it any more. */ - - put_hvpcibus(hbus); } /** @@ -2364,7 +2351,6 @@ static void hv_pci_eject_device(struct hv_pci_dev *hpdev) hpdev->state = hv_pcichild_ejecting; get_pcichild(hpdev); INIT_WORK(&hpdev->wrk, hv_eject_device_work); - get_hvpcibus(hbus); queue_work(hbus->wq, &hpdev->wrk); } @@ -2964,17 +2950,6 @@ static int hv_send_resources_released(struct hv_device *hdev) return 0; } -static void get_hvpcibus(struct hv_pcibus_device *hbus) -{ - refcount_inc(&hbus->remove_lock); -} - -static void put_hvpcibus(struct hv_pcibus_device *hbus) -{ - if (refcount_dec_and_test(&hbus->remove_lock)) - complete(&hbus->remove_event); -} - #define HVPCI_DOM_MAP_SIZE (64 * 1024) static DECLARE_BITMAP(hvpci_dom_map, HVPCI_DOM_MAP_SIZE); @@ -3094,14 +3069,12 @@ static int hv_pci_probe(struct hv_device *hdev, hbus->sysdata.domain = dom; hbus->hdev = hdev; - refcount_set(&hbus->remove_lock, 1); INIT_LIST_HEAD(&hbus->children); INIT_LIST_HEAD(&hbus->dr_list); INIT_LIST_HEAD(&hbus->resources_for_children); spin_lock_init(&hbus->config_lock); spin_lock_init(&hbus->device_list_lock); spin_lock_init(&hbus->retarget_msi_interrupt_lock); - init_completion(&hbus->remove_event); hbus->wq = alloc_ordered_workqueue("hv_pci_%x", 0, hbus->sysdata.domain); if (!hbus->wq) { @@ -3243,8 +3216,9 @@ static int hv_pci_bus_exit(struct hv_device *hdev, bool keep_devs) struct pci_packet teardown_packet; u8 buffer[sizeof(struct pci_message)]; } pkt; - struct hv_dr_state *dr; struct hv_pci_compl comp_pkt; + struct hv_pci_dev *hpdev, *tmp; + unsigned long flags; int ret; /* @@ -3256,9 +3230,16 @@ static int hv_pci_bus_exit(struct hv_device *hdev, bool keep_devs) if (!keep_devs) { /* Delete any children which might still exist. */ - dr = kzalloc(sizeof(*dr), GFP_KERNEL); - if (dr && hv_pci_start_relations_work(hbus, dr)) - kfree(dr); + spin_lock_irqsave(&hbus->device_list_lock, flags); + list_for_each_entry_safe(hpdev, tmp, &hbus->children, list_entry) { + list_del(&hpdev->list_entry); + if (hpdev->pci_slot) + pci_destroy_slot(hpdev->pci_slot); + /* For the two refs got in new_pcichild_device() */ + put_pcichild(hpdev); + put_pcichild(hpdev); + } + spin_unlock_irqrestore(&hbus->device_list_lock, flags); } ret = hv_send_resources_released(hdev); @@ -3301,13 +3282,23 @@ static int hv_pci_remove(struct hv_device *hdev) hbus = hv_get_drvdata(hdev); if (hbus->state == hv_pcibus_installed) { + tasklet_disable(&hdev->channel->callback_event); + hbus->state = hv_pcibus_removing; + tasklet_enable(&hdev->channel->callback_event); + destroy_workqueue(hbus->wq); + hbus->wq = NULL; + /* + * At this point, no work is running or can be scheduled + * on hbus-wq. We can't race with hv_pci_devices_present() + * or hv_pci_eject_device(), it's safe to proceed. + */ + /* Remove the bus from PCI's point of view. */ pci_lock_rescan_remove(); pci_stop_root_bus(hbus->pci_bus); hv_pci_remove_slots(hbus); pci_remove_root_bus(hbus->pci_bus); pci_unlock_rescan_remove(); - hbus->state = hv_pcibus_removed; } ret = hv_pci_bus_exit(hdev, false); @@ -3320,9 +3311,6 @@ static int hv_pci_remove(struct hv_device *hdev) hv_pci_free_bridge_windows(hbus); irq_domain_remove(hbus->irq_domain); irq_domain_free_fwnode(hbus->sysdata.fwnode); - put_hvpcibus(hbus); - wait_for_completion(&hbus->remove_event); - destroy_workqueue(hbus->wq); hv_put_dom_num(hbus->sysdata.domain); diff --git a/drivers/pci/controller/pci-tegra.c b/drivers/pci/controller/pci-tegra.c index 8069bd9232d4..c979229a6d0d 100644 --- a/drivers/pci/controller/pci-tegra.c +++ b/drivers/pci/controller/pci-tegra.c @@ -2539,6 +2539,7 @@ static const struct of_device_id tegra_pcie_of_match[] = { { .compatible = "nvidia,tegra20-pcie", .data = &tegra20_pcie }, { }, }; +MODULE_DEVICE_TABLE(of, tegra_pcie_of_match); static void *tegra_pcie_ports_seq_start(struct seq_file *s, loff_t *pos) { diff --git a/drivers/pci/controller/pci-xgene.c b/drivers/pci/controller/pci-xgene.c index 7f503dd4ff81..e64536047b65 100644 --- a/drivers/pci/controller/pci-xgene.c +++ b/drivers/pci/controller/pci-xgene.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0+ -/** +/* * APM X-Gene PCIe Driver * * Copyright (c) 2014 Applied Micro Circuits Corporation. @@ -485,7 +485,7 @@ static void xgene_pcie_setup_ib_reg(struct xgene_pcie_port *port, { void __iomem *cfg_base = port->cfg_base; struct device *dev = port->dev; - void *bar_addr; + void __iomem *bar_addr; u32 pim_reg; u64 cpu_addr = entry->res->start; u64 pci_addr = cpu_addr - entry->offset; diff --git a/drivers/pci/controller/pcie-iproc-msi.c b/drivers/pci/controller/pcie-iproc-msi.c index eede4e8f3f75..35a82124a126 100644 --- a/drivers/pci/controller/pcie-iproc-msi.c +++ b/drivers/pci/controller/pcie-iproc-msi.c @@ -49,7 +49,7 @@ enum iproc_msi_reg { struct iproc_msi; /** - * iProc MSI group + * struct iproc_msi_grp - iProc MSI group * * One MSI group is allocated per GIC interrupt, serviced by one iProc MSI * event queue. @@ -65,7 +65,7 @@ struct iproc_msi_grp { }; /** - * iProc event queue based MSI + * struct iproc_msi - iProc event queue based MSI * * Only meant to be used on platforms without MSI support integrated into the * GIC. @@ -171,7 +171,7 @@ static struct irq_chip iproc_msi_irq_chip = { static struct msi_domain_info iproc_msi_domain_info = { .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | - MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX, + MSI_FLAG_PCI_MSIX, .chip = &iproc_msi_irq_chip, }; @@ -250,20 +250,23 @@ static int iproc_msi_irq_domain_alloc(struct irq_domain *domain, struct iproc_msi *msi = domain->host_data; int hwirq, i; + if (msi->nr_cpus > 1 && nr_irqs > 1) + return -EINVAL; + mutex_lock(&msi->bitmap_lock); - /* Allocate 'nr_cpus' number of MSI vectors each time */ - hwirq = bitmap_find_next_zero_area(msi->bitmap, msi->nr_msi_vecs, 0, - msi->nr_cpus, 0); - if (hwirq < msi->nr_msi_vecs) { - bitmap_set(msi->bitmap, hwirq, msi->nr_cpus); - } else { - mutex_unlock(&msi->bitmap_lock); - return -ENOSPC; - } + /* + * Allocate 'nr_irqs' multiplied by 'nr_cpus' number of MSI vectors + * each time + */ + hwirq = bitmap_find_free_region(msi->bitmap, msi->nr_msi_vecs, + order_base_2(msi->nr_cpus * nr_irqs)); mutex_unlock(&msi->bitmap_lock); + if (hwirq < 0) + return -ENOSPC; + for (i = 0; i < nr_irqs; i++) { irq_domain_set_info(domain, virq + i, hwirq + i, &iproc_msi_bottom_irq_chip, @@ -284,7 +287,8 @@ static void iproc_msi_irq_domain_free(struct irq_domain *domain, mutex_lock(&msi->bitmap_lock); hwirq = hwirq_to_canonical_hwirq(msi, data->hwirq); - bitmap_clear(msi->bitmap, hwirq, msi->nr_cpus); + bitmap_release_region(msi->bitmap, hwirq, + order_base_2(msi->nr_cpus * nr_irqs)); mutex_unlock(&msi->bitmap_lock); @@ -539,6 +543,9 @@ int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node) mutex_init(&msi->bitmap_lock); msi->nr_cpus = num_possible_cpus(); + if (msi->nr_cpus == 1) + iproc_msi_domain_info.flags |= MSI_FLAG_MULTI_PCI_MSI; + msi->nr_irqs = of_irq_count(node); if (!msi->nr_irqs) { dev_err(pcie->dev, "found no MSI GIC interrupt\n"); diff --git a/drivers/pci/controller/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c index 02e52f698eeb..30ac5fbefbbf 100644 --- a/drivers/pci/controller/pcie-iproc.c +++ b/drivers/pci/controller/pcie-iproc.c @@ -89,8 +89,8 @@ #define IPROC_PCIE_REG_INVALID 0xffff /** - * iProc PCIe outbound mapping controller specific parameters - * + * struct iproc_pcie_ob_map - iProc PCIe outbound mapping controller-specific + * parameters * @window_sizes: list of supported outbound mapping window sizes in MB * @nr_sizes: number of supported outbound mapping window sizes */ @@ -136,22 +136,20 @@ static const struct iproc_pcie_ob_map paxb_v2_ob_map[] = { }; /** - * iProc PCIe inbound mapping type + * enum iproc_pcie_ib_map_type - iProc PCIe inbound mapping type + * @IPROC_PCIE_IB_MAP_MEM: DDR memory + * @IPROC_PCIE_IB_MAP_IO: device I/O memory + * @IPROC_PCIE_IB_MAP_INVALID: invalid or unused */ enum iproc_pcie_ib_map_type { - /* for DDR memory */ IPROC_PCIE_IB_MAP_MEM = 0, - - /* for device I/O memory */ IPROC_PCIE_IB_MAP_IO, - - /* invalid or unused */ IPROC_PCIE_IB_MAP_INVALID }; /** - * iProc PCIe inbound mapping controller specific parameters - * + * struct iproc_pcie_ib_map - iProc PCIe inbound mapping controller-specific + * parameters * @type: inbound mapping region type * @size_unit: inbound mapping region size unit, could be SZ_1K, SZ_1M, or * SZ_1G @@ -437,7 +435,7 @@ static inline void iproc_pcie_write_reg(struct iproc_pcie *pcie, writel(val, pcie->base + offset); } -/** +/* * APB error forwarding can be disabled during access of configuration * registers of the endpoint device, to prevent unsupported requests * (typically seen during enumeration with multi-function devices) from @@ -619,7 +617,7 @@ static int iproc_pcie_config_read(struct pci_bus *bus, unsigned int devfn, return PCIBIOS_SUCCESSFUL; } -/** +/* * Note access to the configuration registers are protected at the higher layer * by 'pci_lock' in drivers/pci/access.c */ @@ -897,7 +895,7 @@ static inline int iproc_pcie_ob_write(struct iproc_pcie *pcie, int window_idx, return 0; } -/** +/* * Some iProc SoCs require the SW to configure the outbound address mapping * * Outbound address translation: diff --git a/drivers/pci/controller/pcie-iproc.h b/drivers/pci/controller/pcie-iproc.h index c2676e442f55..dcca315897c8 100644 --- a/drivers/pci/controller/pcie-iproc.h +++ b/drivers/pci/controller/pcie-iproc.h @@ -7,7 +7,13 @@ #define _PCIE_IPROC_H /** - * iProc PCIe interface type + * enum iproc_pcie_type - iProc PCIe interface type + * @IPROC_PCIE_PAXB_BCMA: BCMA-based host controllers + * @IPROC_PCIE_PAXB: PAXB-based host controllers for + * NS, NSP, Cygnus, NS2, and Pegasus SOCs + * @IPROC_PCIE_PAXB_V2: PAXB-based host controllers for Stingray SoCs + * @IPROC_PCIE_PAXC: PAXC-based host controllers + * @IPROC_PCIE_PAXC_V2: PAXC-based host controllers (second generation) * * PAXB is the wrapper used in root complex that can be connected to an * external endpoint device. @@ -24,7 +30,7 @@ enum iproc_pcie_type { }; /** - * iProc PCIe outbound mapping + * struct iproc_pcie_ob - iProc PCIe outbound mapping * @axi_offset: offset from the AXI address to the internal address used by * the iProc PCIe core * @nr_windows: total number of supported outbound mapping windows @@ -35,7 +41,7 @@ struct iproc_pcie_ob { }; /** - * iProc PCIe inbound mapping + * struct iproc_pcie_ib - iProc PCIe inbound mapping * @nr_regions: total number of supported inbound mapping regions */ struct iproc_pcie_ib { @@ -47,13 +53,13 @@ struct iproc_pcie_ib_map; struct iproc_msi; /** - * iProc PCIe device - * + * struct iproc_pcie - iProc PCIe device * @dev: pointer to device data structure * @type: iProc PCIe interface type * @reg_offsets: register offsets * @base: PCIe host controller I/O register base * @base_addr: PCIe host controller register base physical address + * @mem: host bridge memory window resource * @phy: optional PHY device that controls the Serdes * @map_irq: function callback to map interrupts * @ep_is_internal: indicates an internal emulated endpoint device is connected diff --git a/drivers/pci/controller/pcie-mediatek-gen3.c b/drivers/pci/controller/pcie-mediatek-gen3.c index 3c5b97716d40..f3aeb8d4eaca 100644 --- a/drivers/pci/controller/pcie-mediatek-gen3.c +++ b/drivers/pci/controller/pcie-mediatek-gen3.c @@ -1012,6 +1012,7 @@ static const struct of_device_id mtk_pcie_of_match[] = { { .compatible = "mediatek,mt8192-pcie" }, {}, }; +MODULE_DEVICE_TABLE(of, mtk_pcie_of_match); static struct platform_driver mtk_pcie_driver = { .probe = mtk_pcie_probe, diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c index 62a042e75d9a..25bee693834f 100644 --- a/drivers/pci/controller/pcie-mediatek.c +++ b/drivers/pci/controller/pcie-mediatek.c @@ -991,10 +991,8 @@ static int mtk_pcie_subsys_powerup(struct mtk_pcie *pcie) regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "subsys"); if (regs) { pcie->base = devm_ioremap_resource(dev, regs); - if (IS_ERR(pcie->base)) { - dev_err(dev, "failed to map shared register\n"); + if (IS_ERR(pcie->base)) return PTR_ERR(pcie->base); - } } pcie->free_ck = devm_clk_get(dev, "free_ck"); diff --git a/drivers/pci/controller/pcie-microchip-host.c b/drivers/pci/controller/pcie-microchip-host.c index 89c68c56d93b..fdab8202ae5d 100644 --- a/drivers/pci/controller/pcie-microchip-host.c +++ b/drivers/pci/controller/pcie-microchip-host.c @@ -341,7 +341,7 @@ static struct event_map local_status_to_event[] = { LOCAL_STATUS_TO_EVENT_MAP(PM_MSI_INT_SYS_ERR), }; -struct { +static struct { u32 base; u32 offset; u32 mask; diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c index f1d08a1b1591..78d04ac29cd5 100644 --- a/drivers/pci/controller/pcie-rockchip-host.c +++ b/drivers/pci/controller/pcie-rockchip-host.c @@ -592,10 +592,6 @@ static int rockchip_pcie_parse_host_dt(struct rockchip_pcie *rockchip) if (err) return err; - err = rockchip_pcie_setup_irq(rockchip); - if (err) - return err; - rockchip->vpcie12v = devm_regulator_get_optional(dev, "vpcie12v"); if (IS_ERR(rockchip->vpcie12v)) { if (PTR_ERR(rockchip->vpcie12v) != -ENODEV) @@ -973,8 +969,6 @@ static int rockchip_pcie_probe(struct platform_device *pdev) if (err) goto err_vpcie; - rockchip_pcie_enable_interrupts(rockchip); - err = rockchip_pcie_init_irq_domain(rockchip); if (err < 0) goto err_deinit_port; @@ -992,6 +986,12 @@ static int rockchip_pcie_probe(struct platform_device *pdev) bridge->sysdata = rockchip; bridge->ops = &rockchip_pcie_ops; + err = rockchip_pcie_setup_irq(rockchip); + if (err) + goto err_remove_irq_domain; + + rockchip_pcie_enable_interrupts(rockchip); + err = pci_host_probe(bridge); if (err < 0) goto err_remove_irq_domain; diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c index d2a1920bb055..1c40d2506aef 100644 --- a/drivers/pci/ecam.c +++ b/drivers/pci/ecam.c @@ -32,7 +32,7 @@ struct pci_config_window *pci_ecam_create(struct device *dev, struct pci_config_window *cfg; unsigned int bus_range, bus_range_max, bsz; struct resource *conflict; - int i, err; + int err; if (busr->start > busr->end) return ERR_PTR(-EINVAL); @@ -50,6 +50,7 @@ struct pci_config_window *pci_ecam_create(struct device *dev, cfg->busr.start = busr->start; cfg->busr.end = busr->end; cfg->busr.flags = IORESOURCE_BUS; + cfg->bus_shift = bus_shift; bus_range = resource_size(&cfg->busr); bus_range_max = resource_size(cfgres) >> bus_shift; if (bus_range > bus_range_max) { @@ -77,13 +78,6 @@ struct pci_config_window *pci_ecam_create(struct device *dev, cfg->winp = kcalloc(bus_range, sizeof(*cfg->winp), GFP_KERNEL); if (!cfg->winp) goto err_exit_malloc; - for (i = 0; i < bus_range; i++) { - cfg->winp[i] = - pci_remap_cfgspace(cfgres->start + i * bsz, - bsz); - if (!cfg->winp[i]) - goto err_exit_iomap; - } } else { cfg->win = pci_remap_cfgspace(cfgres->start, bus_range * bsz); if (!cfg->win) @@ -129,6 +123,44 @@ void pci_ecam_free(struct pci_config_window *cfg) } EXPORT_SYMBOL_GPL(pci_ecam_free); +static int pci_ecam_add_bus(struct pci_bus *bus) +{ + struct pci_config_window *cfg = bus->sysdata; + unsigned int bsz = 1 << cfg->bus_shift; + unsigned int busn = bus->number; + phys_addr_t start; + + if (!per_bus_mapping) + return 0; + + if (busn < cfg->busr.start || busn > cfg->busr.end) + return -EINVAL; + + busn -= cfg->busr.start; + start = cfg->res.start + busn * bsz; + + cfg->winp[busn] = pci_remap_cfgspace(start, bsz); + if (!cfg->winp[busn]) + return -ENOMEM; + + return 0; +} + +static void pci_ecam_remove_bus(struct pci_bus *bus) +{ + struct pci_config_window *cfg = bus->sysdata; + unsigned int busn = bus->number; + + if (!per_bus_mapping || busn < cfg->busr.start || busn > cfg->busr.end) + return; + + busn -= cfg->busr.start; + if (cfg->winp[busn]) { + iounmap(cfg->winp[busn]); + cfg->winp[busn] = NULL; + } +} + /* * Function to implement the pci_ops ->map_bus method */ @@ -167,6 +199,8 @@ EXPORT_SYMBOL_GPL(pci_ecam_map_bus); /* ECAM ops */ const struct pci_ecam_ops pci_generic_ecam_ops = { .pci_ops = { + .add_bus = pci_ecam_add_bus, + .remove_bus = pci_ecam_remove_bus, .map_bus = pci_ecam_map_bus, .read = pci_generic_config_read, .write = pci_generic_config_write, @@ -178,6 +212,8 @@ EXPORT_SYMBOL_GPL(pci_generic_ecam_ops); /* ECAM ops for 32-bit access only (non-compliant) */ const struct pci_ecam_ops pci_32b_ops = { .pci_ops = { + .add_bus = pci_ecam_add_bus, + .remove_bus = pci_ecam_remove_bus, .map_bus = pci_ecam_map_bus, .read = pci_generic_config_read32, .write = pci_generic_config_write32, @@ -187,6 +223,8 @@ const struct pci_ecam_ops pci_32b_ops = { /* ECAM ops for 32-bit read only (non-compliant) */ const struct pci_ecam_ops pci_32b_read_ops = { .pci_ops = { + .add_bus = pci_ecam_add_bus, + .remove_bus = pci_ecam_remove_bus, .map_bus = pci_ecam_map_bus, .read = pci_generic_config_read32, .write = pci_generic_config_write, diff --git a/drivers/pci/hotplug/cpci_hotplug.h b/drivers/pci/hotplug/cpci_hotplug.h index f33ff2bca414..3fdd1b9bd8c3 100644 --- a/drivers/pci/hotplug/cpci_hotplug.h +++ b/drivers/pci/hotplug/cpci_hotplug.h @@ -75,6 +75,9 @@ int cpci_hp_unregister_bus(struct pci_bus *bus); int cpci_hp_start(void); int cpci_hp_stop(void); +/* Global variables */ +extern int cpci_debug; + /* * Internal function prototypes, these functions should not be used by * board/chassis drivers. diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c index 2c16adb7f4ec..6c48066acb44 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c @@ -19,8 +19,6 @@ #define MY_NAME "cpci_hotplug" -extern int cpci_debug; - #define dbg(format, arg...) \ do { \ if (cpci_debug) \ diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index b8aacb41a83c..f99a7927e5a8 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c @@ -296,9 +296,10 @@ static int ctrl_slot_cleanup(struct controller *ctrl) * * Won't work for more than one PCI-PCI bridge in a slot. * - * @bus_num - bus number of PCI device - * @dev_num - device number of PCI device - * @slot - Pointer to u8 where slot number will be returned + * @bus: pointer to the PCI bus structure + * @bus_num: bus number of PCI device + * @dev_num: device number of PCI device + * @slot: Pointer to u8 where slot number will be returned * * Output: SUCCESS or FAILURE */ diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 68de958a9be8..1b26ca0b3701 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c @@ -1877,7 +1877,7 @@ static void interrupt_event_handler(struct controller *ctrl) /** * cpqhp_pushbutton_thread - handle pushbutton events - * @slot: target slot (struct) + * @t: pointer to struct timer_list which holds all timer-related callbacks * * Scheduled procedure to handle blocking stuff for the pushbuttons. * Handles all pending events and exits. diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 5ac31f683b85..058d5937d8a9 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -73,7 +73,7 @@ static ssize_t power_read_file(struct pci_slot *pci_slot, char *buf) if (retval) return retval; - return sprintf(buf, "%d\n", value); + return sysfs_emit(buf, "%d\n", value); } static ssize_t power_write_file(struct pci_slot *pci_slot, const char *buf, @@ -130,7 +130,7 @@ static ssize_t attention_read_file(struct pci_slot *pci_slot, char *buf) if (retval) return retval; - return sprintf(buf, "%d\n", value); + return sysfs_emit(buf, "%d\n", value); } static ssize_t attention_write_file(struct pci_slot *pci_slot, const char *buf, @@ -175,7 +175,7 @@ static ssize_t latch_read_file(struct pci_slot *pci_slot, char *buf) if (retval) return retval; - return sprintf(buf, "%d\n", value); + return sysfs_emit(buf, "%d\n", value); } static struct pci_slot_attribute hotplug_slot_attr_latch = { @@ -192,7 +192,7 @@ static ssize_t presence_read_file(struct pci_slot *pci_slot, char *buf) if (retval) return retval; - return sprintf(buf, "%d\n", value); + return sysfs_emit(buf, "%d\n", value); } static struct pci_slot_attribute hotplug_slot_attr_presence = { diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 4fd200d8b0a9..d4a930881054 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -47,6 +47,9 @@ extern int pciehp_poll_time; * struct controller - PCIe hotplug controller * @pcie: pointer to the controller's PCIe port service device * @slot_cap: cached copy of the Slot Capabilities register + * @inband_presence_disabled: In-Band Presence Detect Disable supported by + * controller and disabled per spec recommendation (PCIe r5.0, appendix I + * implementation note) * @slot_ctrl: cached copy of the Slot Control register * @ctrl_lock: serializes writes to the Slot Control register * @cmd_started: jiffies when the Slot Control register was last written; diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index fb3840e222ad..9d06939736c0 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -563,6 +563,32 @@ void pciehp_power_off_slot(struct controller *ctrl) PCI_EXP_SLTCTL_PWR_OFF); } +static void pciehp_ignore_dpc_link_change(struct controller *ctrl, + struct pci_dev *pdev, int irq) +{ + /* + * Ignore link changes which occurred while waiting for DPC recovery. + * Could be several if DPC triggered multiple times consecutively. + */ + synchronize_hardirq(irq); + atomic_and(~PCI_EXP_SLTSTA_DLLSC, &ctrl->pending_events); + if (pciehp_poll_mode) + pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, + PCI_EXP_SLTSTA_DLLSC); + ctrl_info(ctrl, "Slot(%s): Link Down/Up ignored (recovered by DPC)\n", + slot_name(ctrl)); + + /* + * If the link is unexpectedly down after successful recovery, + * the corresponding link change may have been ignored above. + * Synthesize it to ensure that it is acted on. + */ + down_read(&ctrl->reset_lock); + if (!pciehp_check_link_active(ctrl)) + pciehp_request(ctrl, PCI_EXP_SLTSTA_DLLSC); + up_read(&ctrl->reset_lock); +} + static irqreturn_t pciehp_isr(int irq, void *dev_id) { struct controller *ctrl = (struct controller *)dev_id; @@ -707,6 +733,16 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id) } /* + * Ignore Link Down/Up events caused by Downstream Port Containment + * if recovery from the error succeeded. + */ + if ((events & PCI_EXP_SLTSTA_DLLSC) && pci_dpc_recovered(pdev) && + ctrl->state == ON_STATE) { + events &= ~PCI_EXP_SLTSTA_DLLSC; + pciehp_ignore_dpc_link_change(ctrl, pdev, irq); + } + + /* * Disable requests have higher priority than Presence Detect Changed * or Data Link Layer State Changed events. */ diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c index dbfa0b55d31a..068b7810a574 100644 --- a/drivers/pci/hotplug/rpadlpar_sysfs.c +++ b/drivers/pci/hotplug/rpadlpar_sysfs.c @@ -50,7 +50,7 @@ static ssize_t add_slot_store(struct kobject *kobj, struct kobj_attribute *attr, static ssize_t add_slot_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { - return sprintf(buf, "0\n"); + return sysfs_emit(buf, "0\n"); } static ssize_t remove_slot_store(struct kobject *kobj, @@ -80,7 +80,7 @@ static ssize_t remove_slot_store(struct kobject *kobj, static ssize_t remove_slot_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { - return sprintf(buf, "0\n"); + return sysfs_emit(buf, "0\n"); } static struct kobj_attribute add_slot_attr = diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c index 45658bb5c554..64beed7a26be 100644 --- a/drivers/pci/hotplug/shpchp_sysfs.c +++ b/drivers/pci/hotplug/shpchp_sysfs.c @@ -24,50 +24,54 @@ static ssize_t show_ctrl(struct device *dev, struct device_attribute *attr, char *buf) { struct pci_dev *pdev; - char *out = buf; int index, busnr; struct resource *res; struct pci_bus *bus; + size_t len = 0; pdev = to_pci_dev(dev); bus = pdev->subordinate; - out += sprintf(buf, "Free resources: memory\n"); + len += sysfs_emit_at(buf, len, "Free resources: memory\n"); pci_bus_for_each_resource(bus, res, index) { if (res && (res->flags & IORESOURCE_MEM) && !(res->flags & IORESOURCE_PREFETCH)) { - out += sprintf(out, "start = %8.8llx, length = %8.8llx\n", - (unsigned long long)res->start, - (unsigned long long)resource_size(res)); + len += sysfs_emit_at(buf, len, + "start = %8.8llx, length = %8.8llx\n", + (unsigned long long)res->start, + (unsigned long long)resource_size(res)); } } - out += sprintf(out, "Free resources: prefetchable memory\n"); + len += sysfs_emit_at(buf, len, "Free resources: prefetchable memory\n"); pci_bus_for_each_resource(bus, res, index) { if (res && (res->flags & IORESOURCE_MEM) && (res->flags & IORESOURCE_PREFETCH)) { - out += sprintf(out, "start = %8.8llx, length = %8.8llx\n", - (unsigned long long)res->start, - (unsigned long long)resource_size(res)); + len += sysfs_emit_at(buf, len, + "start = %8.8llx, length = %8.8llx\n", + (unsigned long long)res->start, + (unsigned long long)resource_size(res)); } } - out += sprintf(out, "Free resources: IO\n"); + len += sysfs_emit_at(buf, len, "Free resources: IO\n"); pci_bus_for_each_resource(bus, res, index) { if (res && (res->flags & IORESOURCE_IO)) { - out += sprintf(out, "start = %8.8llx, length = %8.8llx\n", - (unsigned long long)res->start, - (unsigned long long)resource_size(res)); + len += sysfs_emit_at(buf, len, + "start = %8.8llx, length = %8.8llx\n", + (unsigned long long)res->start, + (unsigned long long)resource_size(res)); } } - out += sprintf(out, "Free resources: bus numbers\n"); + len += sysfs_emit_at(buf, len, "Free resources: bus numbers\n"); for (busnr = bus->busn_res.start; busnr <= bus->busn_res.end; busnr++) { if (!pci_find_bus(pci_domain_nr(bus), busnr)) break; } if (busnr < bus->busn_res.end) - out += sprintf(out, "start = %8.8x, length = %8.8x\n", - busnr, (int)(bus->busn_res.end - busnr)); + len += sysfs_emit_at(buf, len, + "start = %8.8x, length = %8.8x\n", + busnr, (int)(bus->busn_res.end - busnr)); - return out - buf; + return len; } static DEVICE_ATTR(ctrl, S_IRUGO, show_ctrl, NULL); diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index afc06e6ce115..dafdc652fcd0 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -346,7 +346,7 @@ static ssize_t sriov_totalvfs_show(struct device *dev, { struct pci_dev *pdev = to_pci_dev(dev); - return sprintf(buf, "%u\n", pci_sriov_get_totalvfs(pdev)); + return sysfs_emit(buf, "%u\n", pci_sriov_get_totalvfs(pdev)); } static ssize_t sriov_numvfs_show(struct device *dev, @@ -361,7 +361,7 @@ static ssize_t sriov_numvfs_show(struct device *dev, num_vfs = pdev->sriov->num_VFs; device_unlock(&pdev->dev); - return sprintf(buf, "%u\n", num_vfs); + return sysfs_emit(buf, "%u\n", num_vfs); } /* @@ -391,9 +391,16 @@ static ssize_t sriov_numvfs_store(struct device *dev, if (num_vfs == pdev->sriov->num_VFs) goto exit; + /* is PF driver loaded */ + if (!pdev->driver) { + pci_info(pdev, "no driver bound to device; cannot configure SR-IOV\n"); + ret = -ENOENT; + goto exit; + } + /* is PF driver loaded w/callback */ - if (!pdev->driver || !pdev->driver->sriov_configure) { - pci_info(pdev, "Driver does not support SRIOV configuration via sysfs\n"); + if (!pdev->driver->sriov_configure) { + pci_info(pdev, "driver does not support SR-IOV configuration via sysfs\n"); ret = -ENOENT; goto exit; } @@ -435,7 +442,7 @@ static ssize_t sriov_offset_show(struct device *dev, { struct pci_dev *pdev = to_pci_dev(dev); - return sprintf(buf, "%u\n", pdev->sriov->offset); + return sysfs_emit(buf, "%u\n", pdev->sriov->offset); } static ssize_t sriov_stride_show(struct device *dev, @@ -444,7 +451,7 @@ static ssize_t sriov_stride_show(struct device *dev, { struct pci_dev *pdev = to_pci_dev(dev); - return sprintf(buf, "%u\n", pdev->sriov->stride); + return sysfs_emit(buf, "%u\n", pdev->sriov->stride); } static ssize_t sriov_vf_device_show(struct device *dev, @@ -453,7 +460,7 @@ static ssize_t sriov_vf_device_show(struct device *dev, { struct pci_dev *pdev = to_pci_dev(dev); - return sprintf(buf, "%x\n", pdev->sriov->vf_device); + return sysfs_emit(buf, "%x\n", pdev->sriov->vf_device); } static ssize_t sriov_drivers_autoprobe_show(struct device *dev, @@ -462,7 +469,7 @@ static ssize_t sriov_drivers_autoprobe_show(struct device *dev, { struct pci_dev *pdev = to_pci_dev(dev); - return sprintf(buf, "%u\n", pdev->sriov->drivers_autoprobe); + return sysfs_emit(buf, "%u\n", pdev->sriov->drivers_autoprobe); } static ssize_t sriov_drivers_autoprobe_store(struct device *dev, diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 217dc9f0231f..9232255c8515 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -464,11 +464,11 @@ static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr, return retval; entry = irq_get_msi_desc(irq); - if (entry) - return sprintf(buf, "%s\n", - entry->msi_attrib.is_msix ? "msix" : "msi"); + if (!entry) + return -ENODEV; - return -ENODEV; + return sysfs_emit(buf, "%s\n", + entry->msi_attrib.is_msix ? "msix" : "msi"); } static int populate_msi_sysfs(struct pci_dev *pdev) diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c index 196382630363..50cdde3e9a8b 100644 --- a/drivers/pci/p2pdma.c +++ b/drivers/pci/p2pdma.c @@ -48,12 +48,16 @@ static ssize_t size_show(struct device *dev, struct device_attribute *attr, char *buf) { struct pci_dev *pdev = to_pci_dev(dev); + struct pci_p2pdma *p2pdma; size_t size = 0; - if (pdev->p2pdma->pool) - size = gen_pool_size(pdev->p2pdma->pool); + rcu_read_lock(); + p2pdma = rcu_dereference(pdev->p2pdma); + if (p2pdma && p2pdma->pool) + size = gen_pool_size(p2pdma->pool); + rcu_read_unlock(); - return scnprintf(buf, PAGE_SIZE, "%zd\n", size); + return sysfs_emit(buf, "%zd\n", size); } static DEVICE_ATTR_RO(size); @@ -61,12 +65,16 @@ static ssize_t available_show(struct device *dev, struct device_attribute *attr, char *buf) { struct pci_dev *pdev = to_pci_dev(dev); + struct pci_p2pdma *p2pdma; size_t avail = 0; - if (pdev->p2pdma->pool) - avail = gen_pool_avail(pdev->p2pdma->pool); + rcu_read_lock(); + p2pdma = rcu_dereference(pdev->p2pdma); + if (p2pdma && p2pdma->pool) + avail = gen_pool_avail(p2pdma->pool); + rcu_read_unlock(); - return scnprintf(buf, PAGE_SIZE, "%zd\n", avail); + return sysfs_emit(buf, "%zd\n", avail); } static DEVICE_ATTR_RO(available); @@ -74,9 +82,16 @@ static ssize_t published_show(struct device *dev, struct device_attribute *attr, char *buf) { struct pci_dev *pdev = to_pci_dev(dev); + struct pci_p2pdma *p2pdma; + bool published = false; - return scnprintf(buf, PAGE_SIZE, "%d\n", - pdev->p2pdma->p2pmem_published); + rcu_read_lock(); + p2pdma = rcu_dereference(pdev->p2pdma); + if (p2pdma) + published = p2pdma->p2pmem_published; + rcu_read_unlock(); + + return sysfs_emit(buf, "%d\n", published); } static DEVICE_ATTR_RO(published); @@ -95,8 +110,9 @@ static const struct attribute_group p2pmem_group = { static void pci_p2pdma_release(void *data) { struct pci_dev *pdev = data; - struct pci_p2pdma *p2pdma = pdev->p2pdma; + struct pci_p2pdma *p2pdma; + p2pdma = rcu_dereference_protected(pdev->p2pdma, 1); if (!p2pdma) return; @@ -128,16 +144,14 @@ static int pci_p2pdma_setup(struct pci_dev *pdev) if (error) goto out_pool_destroy; - pdev->p2pdma = p2p; - error = sysfs_create_group(&pdev->dev.kobj, &p2pmem_group); if (error) goto out_pool_destroy; + rcu_assign_pointer(pdev->p2pdma, p2p); return 0; out_pool_destroy: - pdev->p2pdma = NULL; gen_pool_destroy(p2p->pool); out: devm_kfree(&pdev->dev, p2p); @@ -159,6 +173,7 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size, { struct pci_p2pdma_pagemap *p2p_pgmap; struct dev_pagemap *pgmap; + struct pci_p2pdma *p2pdma; void *addr; int error; @@ -200,7 +215,8 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size, goto pgmap_free; } - error = gen_pool_add_owner(pdev->p2pdma->pool, (unsigned long)addr, + p2pdma = rcu_dereference_protected(pdev->p2pdma, 1); + error = gen_pool_add_owner(p2pdma->pool, (unsigned long)addr, pci_bus_address(pdev, bar) + offset, range_len(&pgmap->range), dev_to_node(&pdev->dev), pgmap->ref); @@ -308,10 +324,41 @@ static const struct pci_p2pdma_whitelist_entry { {} }; +/* + * This lookup function tries to find the PCI device corresponding to a given + * host bridge. + * + * It assumes the host bridge device is the first PCI device in the + * bus->devices list and that the devfn is 00.0. These assumptions should hold + * for all the devices in the whitelist above. + * + * This function is equivalent to pci_get_slot(host->bus, 0), however it does + * not take the pci_bus_sem lock seeing __host_bridge_whitelist() must not + * sleep. + * + * For this to be safe, the caller should hold a reference to a device on the + * bridge, which should ensure the host_bridge device will not be freed + * or removed from the head of the devices list. + */ +static struct pci_dev *pci_host_bridge_dev(struct pci_host_bridge *host) +{ + struct pci_dev *root; + + root = list_first_entry_or_null(&host->bus->devices, + struct pci_dev, bus_list); + + if (!root) + return NULL; + if (root->devfn != PCI_DEVFN(0, 0)) + return NULL; + + return root; +} + static bool __host_bridge_whitelist(struct pci_host_bridge *host, - bool same_host_bridge) + bool same_host_bridge, bool warn) { - struct pci_dev *root = pci_get_slot(host->bus, PCI_DEVFN(0, 0)); + struct pci_dev *root = pci_host_bridge_dev(host); const struct pci_p2pdma_whitelist_entry *entry; unsigned short vendor, device; @@ -320,7 +367,6 @@ static bool __host_bridge_whitelist(struct pci_host_bridge *host, vendor = root->vendor; device = root->device; - pci_dev_put(root); for (entry = pci_p2pdma_whitelist; entry->vendor; entry++) { if (vendor != entry->vendor || device != entry->device) @@ -331,6 +377,10 @@ static bool __host_bridge_whitelist(struct pci_host_bridge *host, return true; } + if (warn) + pci_warn(root, "Host bridge not in P2PDMA whitelist: %04x:%04x\n", + vendor, device); + return false; } @@ -338,44 +388,90 @@ static bool __host_bridge_whitelist(struct pci_host_bridge *host, * If we can't find a common upstream bridge take a look at the root * complex and compare it to a whitelist of known good hardware. */ -static bool host_bridge_whitelist(struct pci_dev *a, struct pci_dev *b) +static bool host_bridge_whitelist(struct pci_dev *a, struct pci_dev *b, + bool warn) { struct pci_host_bridge *host_a = pci_find_host_bridge(a->bus); struct pci_host_bridge *host_b = pci_find_host_bridge(b->bus); if (host_a == host_b) - return __host_bridge_whitelist(host_a, true); + return __host_bridge_whitelist(host_a, true, warn); - if (__host_bridge_whitelist(host_a, false) && - __host_bridge_whitelist(host_b, false)) + if (__host_bridge_whitelist(host_a, false, warn) && + __host_bridge_whitelist(host_b, false, warn)) return true; return false; } +static unsigned long map_types_idx(struct pci_dev *client) +{ + return (pci_domain_nr(client->bus) << 16) | + (client->bus->number << 8) | client->devfn; +} + +/* + * Calculate the P2PDMA mapping type and distance between two PCI devices. + * + * If the two devices are the same PCI function, return + * PCI_P2PDMA_MAP_BUS_ADDR and a distance of 0. + * + * If they are two functions of the same device, return + * PCI_P2PDMA_MAP_BUS_ADDR and a distance of 2 (one hop up to the bridge, + * then one hop back down to another function of the same device). + * + * In the case where two devices are connected to the same PCIe switch, + * return a distance of 4. This corresponds to the following PCI tree: + * + * -+ Root Port + * \+ Switch Upstream Port + * +-+ Switch Downstream Port 0 + * + \- Device A + * \-+ Switch Downstream Port 1 + * \- Device B + * + * The distance is 4 because we traverse from Device A to Downstream Port 0 + * to the common Switch Upstream Port, back down to Downstream Port 1 and + * then to Device B. The mapping type returned depends on the ACS + * redirection setting of the ports along the path. + * + * If ACS redirect is set on any port in the path, traffic between the + * devices will go through the host bridge, so return + * PCI_P2PDMA_MAP_THRU_HOST_BRIDGE; otherwise return + * PCI_P2PDMA_MAP_BUS_ADDR. + * + * Any two devices that have a data path that goes through the host bridge + * will consult a whitelist. If the host bridge is in the whitelist, return + * PCI_P2PDMA_MAP_THRU_HOST_BRIDGE with the distance set to the number of + * ports per above. If the device is not in the whitelist, return + * PCI_P2PDMA_MAP_NOT_SUPPORTED. + */ static enum pci_p2pdma_map_type -__upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client, - int *dist, bool *acs_redirects, struct seq_buf *acs_list) +calc_map_type_and_dist(struct pci_dev *provider, struct pci_dev *client, + int *dist, bool verbose) { + enum pci_p2pdma_map_type map_type = PCI_P2PDMA_MAP_THRU_HOST_BRIDGE; struct pci_dev *a = provider, *b = client, *bb; + bool acs_redirects = false; + struct pci_p2pdma *p2pdma; + struct seq_buf acs_list; + int acs_cnt = 0; int dist_a = 0; int dist_b = 0; - int acs_cnt = 0; + char buf[128]; - if (acs_redirects) - *acs_redirects = false; + seq_buf_init(&acs_list, buf, sizeof(buf)); /* * Note, we don't need to take references to devices returned by * pci_upstream_bridge() seeing we hold a reference to a child * device which will already hold a reference to the upstream bridge. */ - while (a) { dist_b = 0; if (pci_bridge_has_acs_redir(a)) { - seq_buf_print_bus_devfn(acs_list, a); + seq_buf_print_bus_devfn(&acs_list, a); acs_cnt++; } @@ -393,10 +489,8 @@ __upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client, dist_a++; } - if (dist) - *dist = dist_a + dist_b; - - return PCI_P2PDMA_MAP_THRU_HOST_BRIDGE; + *dist = dist_a + dist_b; + goto map_through_host_bridge; check_b_path_acs: bb = b; @@ -406,124 +500,45 @@ check_b_path_acs: break; if (pci_bridge_has_acs_redir(bb)) { - seq_buf_print_bus_devfn(acs_list, bb); + seq_buf_print_bus_devfn(&acs_list, bb); acs_cnt++; } bb = pci_upstream_bridge(bb); } - if (dist) - *dist = dist_a + dist_b; - - if (acs_cnt) { - if (acs_redirects) - *acs_redirects = true; - - return PCI_P2PDMA_MAP_THRU_HOST_BRIDGE; - } - - return PCI_P2PDMA_MAP_BUS_ADDR; -} - -static unsigned long map_types_idx(struct pci_dev *client) -{ - return (pci_domain_nr(client->bus) << 16) | - (client->bus->number << 8) | client->devfn; -} - -/* - * Find the distance through the nearest common upstream bridge between - * two PCI devices. - * - * If the two devices are the same device then 0 will be returned. - * - * If there are two virtual functions of the same device behind the same - * bridge port then 2 will be returned (one step down to the PCIe switch, - * then one step back to the same device). - * - * In the case where two devices are connected to the same PCIe switch, the - * value 4 will be returned. This corresponds to the following PCI tree: - * - * -+ Root Port - * \+ Switch Upstream Port - * +-+ Switch Downstream Port - * + \- Device A - * \-+ Switch Downstream Port - * \- Device B - * - * The distance is 4 because we traverse from Device A through the downstream - * port of the switch, to the common upstream port, back up to the second - * downstream port and then to Device B. - * - * Any two devices that cannot communicate using p2pdma will return - * PCI_P2PDMA_MAP_NOT_SUPPORTED. - * - * Any two devices that have a data path that goes through the host bridge - * will consult a whitelist. If the host bridges are on the whitelist, - * this function will return PCI_P2PDMA_MAP_THRU_HOST_BRIDGE. - * - * If either bridge is not on the whitelist this function returns - * PCI_P2PDMA_MAP_NOT_SUPPORTED. - * - * If a bridge which has any ACS redirection bits set is in the path, - * acs_redirects will be set to true. In this case, a list of all infringing - * bridge addresses will be populated in acs_list (assuming it's non-null) - * for printk purposes. - */ -static enum pci_p2pdma_map_type -upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client, - int *dist, bool *acs_redirects, struct seq_buf *acs_list) -{ - enum pci_p2pdma_map_type map_type; - - map_type = __upstream_bridge_distance(provider, client, dist, - acs_redirects, acs_list); + *dist = dist_a + dist_b; - if (map_type == PCI_P2PDMA_MAP_THRU_HOST_BRIDGE) { - if (!cpu_supports_p2pdma() && - !host_bridge_whitelist(provider, client)) - map_type = PCI_P2PDMA_MAP_NOT_SUPPORTED; + if (!acs_cnt) { + map_type = PCI_P2PDMA_MAP_BUS_ADDR; + goto done; } - if (provider->p2pdma) - xa_store(&provider->p2pdma->map_types, map_types_idx(client), - xa_mk_value(map_type), GFP_KERNEL); - - return map_type; -} - -static enum pci_p2pdma_map_type -upstream_bridge_distance_warn(struct pci_dev *provider, struct pci_dev *client, - int *dist) -{ - struct seq_buf acs_list; - bool acs_redirects; - int ret; - - seq_buf_init(&acs_list, kmalloc(PAGE_SIZE, GFP_KERNEL), PAGE_SIZE); - if (!acs_list.buffer) - return -ENOMEM; - - ret = upstream_bridge_distance(provider, client, dist, &acs_redirects, - &acs_list); - if (acs_redirects) { + if (verbose) { + acs_list.buffer[acs_list.len-1] = 0; /* drop final semicolon */ pci_warn(client, "ACS redirect is set between the client and provider (%s)\n", pci_name(provider)); - /* Drop final semicolon */ - acs_list.buffer[acs_list.len-1] = 0; pci_warn(client, "to disable ACS redirect for this path, add the kernel parameter: pci=disable_acs_redir=%s\n", acs_list.buffer); } + acs_redirects = true; - if (ret == PCI_P2PDMA_MAP_NOT_SUPPORTED) { - pci_warn(client, "cannot be used for peer-to-peer DMA as the client and provider (%s) do not share an upstream bridge or whitelisted host bridge\n", - pci_name(provider)); +map_through_host_bridge: + if (!cpu_supports_p2pdma() && + !host_bridge_whitelist(provider, client, acs_redirects)) { + if (verbose) + pci_warn(client, "cannot be used for peer-to-peer DMA as the client and provider (%s) do not share an upstream bridge or whitelisted host bridge\n", + pci_name(provider)); + map_type = PCI_P2PDMA_MAP_NOT_SUPPORTED; } - - kfree(acs_list.buffer); - - return ret; +done: + rcu_read_lock(); + p2pdma = rcu_dereference(provider->p2pdma); + if (p2pdma) + xa_store(&p2pdma->map_types, map_types_idx(client), + xa_mk_value(map_type), GFP_KERNEL); + rcu_read_unlock(); + return map_type; } /** @@ -546,11 +561,11 @@ upstream_bridge_distance_warn(struct pci_dev *provider, struct pci_dev *client, int pci_p2pdma_distance_many(struct pci_dev *provider, struct device **clients, int num_clients, bool verbose) { + enum pci_p2pdma_map_type map; bool not_supported = false; struct pci_dev *pci_client; int total_dist = 0; - int distance; - int i, ret; + int i, distance; if (num_clients == 0) return -1; @@ -564,16 +579,12 @@ int pci_p2pdma_distance_many(struct pci_dev *provider, struct device **clients, return -1; } - if (verbose) - ret = upstream_bridge_distance_warn(provider, - pci_client, &distance); - else - ret = upstream_bridge_distance(provider, pci_client, - &distance, NULL, NULL); + map = calc_map_type_and_dist(provider, pci_client, &distance, + verbose); pci_dev_put(pci_client); - if (ret == PCI_P2PDMA_MAP_NOT_SUPPORTED) + if (map == PCI_P2PDMA_MAP_NOT_SUPPORTED) not_supported = true; if (not_supported && !verbose) @@ -595,7 +606,15 @@ EXPORT_SYMBOL_GPL(pci_p2pdma_distance_many); */ bool pci_has_p2pmem(struct pci_dev *pdev) { - return pdev->p2pdma && pdev->p2pdma->p2pmem_published; + struct pci_p2pdma *p2pdma; + bool res; + + rcu_read_lock(); + p2pdma = rcu_dereference(pdev->p2pdma); + res = p2pdma && p2pdma->p2pmem_published; + rcu_read_unlock(); + + return res; } EXPORT_SYMBOL_GPL(pci_has_p2pmem); @@ -675,6 +694,7 @@ void *pci_alloc_p2pmem(struct pci_dev *pdev, size_t size) { void *ret = NULL; struct percpu_ref *ref; + struct pci_p2pdma *p2pdma; /* * Pairs with synchronize_rcu() in pci_p2pdma_release() to @@ -682,16 +702,16 @@ void *pci_alloc_p2pmem(struct pci_dev *pdev, size_t size) * read-lock. */ rcu_read_lock(); - if (unlikely(!pdev->p2pdma)) + p2pdma = rcu_dereference(pdev->p2pdma); + if (unlikely(!p2pdma)) goto out; - ret = (void *)gen_pool_alloc_owner(pdev->p2pdma->pool, size, - (void **) &ref); + ret = (void *)gen_pool_alloc_owner(p2pdma->pool, size, (void **) &ref); if (!ret) goto out; if (unlikely(!percpu_ref_tryget_live(ref))) { - gen_pool_free(pdev->p2pdma->pool, (unsigned long) ret, size); + gen_pool_free(p2pdma->pool, (unsigned long) ret, size); ret = NULL; goto out; } @@ -710,8 +730,9 @@ EXPORT_SYMBOL_GPL(pci_alloc_p2pmem); void pci_free_p2pmem(struct pci_dev *pdev, void *addr, size_t size) { struct percpu_ref *ref; + struct pci_p2pdma *p2pdma = rcu_dereference_protected(pdev->p2pdma, 1); - gen_pool_free_owner(pdev->p2pdma->pool, (uintptr_t)addr, size, + gen_pool_free_owner(p2pdma->pool, (uintptr_t)addr, size, (void **) &ref); percpu_ref_put(ref); } @@ -725,9 +746,13 @@ EXPORT_SYMBOL_GPL(pci_free_p2pmem); */ pci_bus_addr_t pci_p2pmem_virt_to_bus(struct pci_dev *pdev, void *addr) { + struct pci_p2pdma *p2pdma; + if (!addr) return 0; - if (!pdev->p2pdma) + + p2pdma = rcu_dereference_protected(pdev->p2pdma, 1); + if (!p2pdma) return 0; /* @@ -735,7 +760,7 @@ pci_bus_addr_t pci_p2pmem_virt_to_bus(struct pci_dev *pdev, void *addr) * bus address as the physical address. So gen_pool_virt_to_phys() * actually returns the bus address despite the misleading name. */ - return gen_pool_virt_to_phys(pdev->p2pdma->pool, (unsigned long)addr); + return gen_pool_virt_to_phys(p2pdma->pool, (unsigned long)addr); } EXPORT_SYMBOL_GPL(pci_p2pmem_virt_to_bus); @@ -806,19 +831,40 @@ EXPORT_SYMBOL_GPL(pci_p2pmem_free_sgl); */ void pci_p2pmem_publish(struct pci_dev *pdev, bool publish) { - if (pdev->p2pdma) - pdev->p2pdma->p2pmem_published = publish; + struct pci_p2pdma *p2pdma; + + rcu_read_lock(); + p2pdma = rcu_dereference(pdev->p2pdma); + if (p2pdma) + p2pdma->p2pmem_published = publish; + rcu_read_unlock(); } EXPORT_SYMBOL_GPL(pci_p2pmem_publish); -static enum pci_p2pdma_map_type pci_p2pdma_map_type(struct pci_dev *provider, - struct pci_dev *client) +static enum pci_p2pdma_map_type pci_p2pdma_map_type(struct dev_pagemap *pgmap, + struct device *dev) { + enum pci_p2pdma_map_type type = PCI_P2PDMA_MAP_NOT_SUPPORTED; + struct pci_dev *provider = to_p2p_pgmap(pgmap)->provider; + struct pci_dev *client; + struct pci_p2pdma *p2pdma; + if (!provider->p2pdma) return PCI_P2PDMA_MAP_NOT_SUPPORTED; - return xa_to_value(xa_load(&provider->p2pdma->map_types, - map_types_idx(client))); + if (!dev_is_pci(dev)) + return PCI_P2PDMA_MAP_NOT_SUPPORTED; + + client = to_pci_dev(dev); + + rcu_read_lock(); + p2pdma = rcu_dereference(provider->p2pdma); + + if (p2pdma) + type = xa_to_value(xa_load(&p2pdma->map_types, + map_types_idx(client))); + rcu_read_unlock(); + return type; } static int __pci_p2pdma_map_sg(struct pci_p2pdma_pagemap *p2p_pgmap, @@ -853,14 +899,8 @@ int pci_p2pdma_map_sg_attrs(struct device *dev, struct scatterlist *sg, { struct pci_p2pdma_pagemap *p2p_pgmap = to_p2p_pgmap(sg_page(sg)->pgmap); - struct pci_dev *client; - - if (WARN_ON_ONCE(!dev_is_pci(dev))) - return 0; - client = to_pci_dev(dev); - - switch (pci_p2pdma_map_type(p2p_pgmap->provider, client)) { + switch (pci_p2pdma_map_type(sg_page(sg)->pgmap, dev)) { case PCI_P2PDMA_MAP_THRU_HOST_BRIDGE: return dma_map_sg_attrs(dev, sg, nents, dir, attrs); case PCI_P2PDMA_MAP_BUS_ADDR: @@ -884,17 +924,9 @@ EXPORT_SYMBOL_GPL(pci_p2pdma_map_sg_attrs); void pci_p2pdma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir, unsigned long attrs) { - struct pci_p2pdma_pagemap *p2p_pgmap = - to_p2p_pgmap(sg_page(sg)->pgmap); enum pci_p2pdma_map_type map_type; - struct pci_dev *client; - - if (WARN_ON_ONCE(!dev_is_pci(dev))) - return; - - client = to_pci_dev(dev); - map_type = pci_p2pdma_map_type(p2p_pgmap->provider, client); + map_type = pci_p2pdma_map_type(sg_page(sg)->pgmap, dev); if (map_type == PCI_P2PDMA_MAP_THRU_HOST_BRIDGE) dma_unmap_sg_attrs(dev, sg, nents, dir, attrs); diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c index c32f3b7540e8..0c6446519640 100644 --- a/drivers/pci/pci-label.c +++ b/drivers/pci/pci-label.c @@ -139,14 +139,17 @@ enum acpi_attr_enum { ACPI_ATTR_INDEX_SHOW, }; -static void dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf) +static int dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf) { int len; + len = utf16s_to_utf8s((const wchar_t *)obj->buffer.pointer, obj->buffer.length, UTF16_LITTLE_ENDIAN, - buf, PAGE_SIZE); - buf[len] = '\n'; + buf, PAGE_SIZE - 1); + buf[len++] = '\n'; + + return len; } static int dsm_get_label(struct device *dev, char *buf, @@ -154,7 +157,7 @@ static int dsm_get_label(struct device *dev, char *buf, { acpi_handle handle = ACPI_HANDLE(dev); union acpi_object *obj, *tmp; - int len = -1; + int len = 0; if (!handle) return -1; @@ -175,20 +178,19 @@ static int dsm_get_label(struct device *dev, char *buf, * this entry must return a null string. */ if (attr == ACPI_ATTR_INDEX_SHOW) { - scnprintf(buf, PAGE_SIZE, "%llu\n", tmp->integer.value); + len = sysfs_emit(buf, "%llu\n", tmp->integer.value); } else if (attr == ACPI_ATTR_LABEL_SHOW) { if (tmp[1].type == ACPI_TYPE_STRING) - scnprintf(buf, PAGE_SIZE, "%s\n", - tmp[1].string.pointer); + len = sysfs_emit(buf, "%s\n", + tmp[1].string.pointer); else if (tmp[1].type == ACPI_TYPE_BUFFER) - dsm_label_utf16s_to_utf8s(tmp + 1, buf); + len = dsm_label_utf16s_to_utf8s(tmp + 1, buf); } - len = strlen(buf) > 0 ? strlen(buf) : -1; } ACPI_FREE(obj); - return len; + return len > 0 ? len : -1; } static ssize_t label_show(struct device *dev, struct device_attribute *attr, diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index beb8d1f4fafe..5d63df7c1820 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -537,7 +537,7 @@ static ssize_t devspec_show(struct device *dev, if (np == NULL) return 0; - return sysfs_emit(buf, "%pOF", np); + return sysfs_emit(buf, "%pOF\n", np); } static DEVICE_ATTR_RO(devspec); #endif diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 8d4ebe095d0c..aacf575c15cf 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -5030,6 +5030,16 @@ static int pci_dev_reset_slot_function(struct pci_dev *dev, int probe) return pci_reset_hotplug_slot(dev->slot->hotplug, probe); } +static int pci_reset_bus_function(struct pci_dev *dev, int probe) +{ + int rc; + + rc = pci_dev_reset_slot_function(dev, probe); + if (rc != -ENOTTY) + return rc; + return pci_parent_bus_reset(dev, probe); +} + static void pci_dev_lock(struct pci_dev *dev) { pci_cfg_access_lock(dev); @@ -5038,7 +5048,7 @@ static void pci_dev_lock(struct pci_dev *dev) } /* Return 1 on successful lock, 0 on contention */ -static int pci_dev_trylock(struct pci_dev *dev) +int pci_dev_trylock(struct pci_dev *dev) { if (pci_cfg_access_trylock(dev)) { if (device_trylock(&dev->dev)) @@ -5048,12 +5058,14 @@ static int pci_dev_trylock(struct pci_dev *dev) return 0; } +EXPORT_SYMBOL_GPL(pci_dev_trylock); -static void pci_dev_unlock(struct pci_dev *dev) +void pci_dev_unlock(struct pci_dev *dev) { device_unlock(&dev->dev); pci_cfg_access_unlock(dev); } +EXPORT_SYMBOL_GPL(pci_dev_unlock); static void pci_dev_save_and_disable(struct pci_dev *dev) { @@ -5150,10 +5162,7 @@ int __pci_reset_function_locked(struct pci_dev *dev) rc = pci_pm_reset(dev, 0); if (rc != -ENOTTY) return rc; - rc = pci_dev_reset_slot_function(dev, 0); - if (rc != -ENOTTY) - return rc; - return pci_parent_bus_reset(dev, 0); + return pci_reset_bus_function(dev, 0); } EXPORT_SYMBOL_GPL(__pci_reset_function_locked); @@ -5185,11 +5194,8 @@ int pci_probe_reset_function(struct pci_dev *dev) rc = pci_pm_reset(dev, 1); if (rc != -ENOTTY) return rc; - rc = pci_dev_reset_slot_function(dev, 1); - if (rc != -ENOTTY) - return rc; - return pci_parent_bus_reset(dev, 1); + return pci_reset_bus_function(dev, 1); } /** @@ -6449,34 +6455,40 @@ static ssize_t resource_alignment_show(struct bus_type *bus, char *buf) spin_lock(&resource_alignment_lock); if (resource_alignment_param) - count = scnprintf(buf, PAGE_SIZE, "%s", resource_alignment_param); + count = sysfs_emit(buf, "%s\n", resource_alignment_param); spin_unlock(&resource_alignment_lock); - /* - * When set by the command line, resource_alignment_param will not - * have a trailing line feed, which is ugly. So conditionally add - * it here. - */ - if (count >= 2 && buf[count - 2] != '\n' && count < PAGE_SIZE - 1) { - buf[count - 1] = '\n'; - buf[count++] = 0; - } - return count; } static ssize_t resource_alignment_store(struct bus_type *bus, const char *buf, size_t count) { - char *param = kstrndup(buf, count, GFP_KERNEL); + char *param, *old, *end; + + if (count >= (PAGE_SIZE - 1)) + return -EINVAL; + param = kstrndup(buf, count, GFP_KERNEL); if (!param) return -ENOMEM; + end = strchr(param, '\n'); + if (end) + *end = '\0'; + spin_lock(&resource_alignment_lock); - kfree(resource_alignment_param); - resource_alignment_param = param; + old = resource_alignment_param; + if (strlen(param)) { + resource_alignment_param = param; + } else { + kfree(param); + resource_alignment_param = NULL; + } spin_unlock(&resource_alignment_lock); + + kfree(old); + return count; } diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 37c913bbc6e1..93dcdd431072 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -324,8 +324,8 @@ struct pci_sriov { /** * pci_dev_set_io_state - Set the new error state if possible. * - * @dev - pci device to set new error_state - * @new - the state we want dev to be in + * @dev: PCI device to set new error_state + * @new: the state we want dev to be in * * Must be called with device_lock held. * @@ -385,6 +385,8 @@ static inline bool pci_dev_is_disconnected(const struct pci_dev *dev) /* pci_dev priv_flags */ #define PCI_DEV_ADDED 0 +#define PCI_DPC_RECOVERED 1 +#define PCI_DPC_RECOVERING 2 static inline void pci_dev_assign_added(struct pci_dev *dev, bool added) { @@ -439,10 +441,12 @@ void pci_restore_dpc_state(struct pci_dev *dev); void pci_dpc_init(struct pci_dev *pdev); void dpc_process_error(struct pci_dev *pdev); pci_ers_result_t dpc_reset_link(struct pci_dev *pdev); +bool pci_dpc_recovered(struct pci_dev *pdev); #else static inline void pci_save_dpc_state(struct pci_dev *dev) {} static inline void pci_restore_dpc_state(struct pci_dev *dev) {} static inline void pci_dpc_init(struct pci_dev *pdev) {} +static inline bool pci_dpc_recovered(struct pci_dev *pdev) { return false; } #endif #ifdef CONFIG_PCIEPORTBUS diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c index ec943cee5ecc..df4ba9b384c2 100644 --- a/drivers/pci/pcie/aer.c +++ b/drivers/pci/pcie/aer.c @@ -529,21 +529,23 @@ static const char *aer_agent_string[] = { char *buf) \ { \ unsigned int i; \ - char *str = buf; \ struct pci_dev *pdev = to_pci_dev(dev); \ u64 *stats = pdev->aer_stats->stats_array; \ + size_t len = 0; \ \ for (i = 0; i < ARRAY_SIZE(strings_array); i++) { \ if (strings_array[i]) \ - str += sprintf(str, "%s %llu\n", \ - strings_array[i], stats[i]); \ + len += sysfs_emit_at(buf, len, "%s %llu\n", \ + strings_array[i], \ + stats[i]); \ else if (stats[i]) \ - str += sprintf(str, #stats_array "_bit[%d] %llu\n",\ - i, stats[i]); \ + len += sysfs_emit_at(buf, len, \ + #stats_array "_bit[%d] %llu\n",\ + i, stats[i]); \ } \ - str += sprintf(str, "TOTAL_%s %llu\n", total_string, \ - pdev->aer_stats->total_field); \ - return str-buf; \ + len += sysfs_emit_at(buf, len, "TOTAL_%s %llu\n", total_string, \ + pdev->aer_stats->total_field); \ + return len; \ } \ static DEVICE_ATTR_RO(name) @@ -563,7 +565,7 @@ aer_stats_dev_attr(aer_dev_nonfatal, dev_nonfatal_errs, char *buf) \ { \ struct pci_dev *pdev = to_pci_dev(dev); \ - return sprintf(buf, "%llu\n", pdev->aer_stats->field); \ + return sysfs_emit(buf, "%llu\n", pdev->aer_stats->field); \ } \ static DEVICE_ATTR_RO(name) @@ -983,7 +985,7 @@ static void aer_recover_work_func(struct work_struct *work) pdev = pci_get_domain_bus_and_slot(entry.domain, entry.bus, entry.devfn); if (!pdev) { - pr_err("AER recover: Can not find pci_dev for %04x:%02x:%02x:%x\n", + pr_err("no pci_dev for %04x:%02x:%02x.%x\n", entry.domain, entry.bus, PCI_SLOT(entry.devfn), PCI_FUNC(entry.devfn)); continue; @@ -1022,7 +1024,7 @@ void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn, &aer_recover_ring_lock)) schedule_work(&aer_recover_work); else - pr_err("AER recover: Buffer overflow when recovering AER for %04x:%02x:%02x:%x\n", + pr_err("buffer overflow in recovery for %04x:%02x:%02x.%x\n", domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); } EXPORT_SYMBOL_GPL(aer_recover_queue); diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index ac0557a305af..013a47f587ce 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -1208,7 +1208,7 @@ static ssize_t aspm_attr_show_common(struct device *dev, struct pci_dev *pdev = to_pci_dev(dev); struct pcie_link_state *link = pcie_aspm_get_link(pdev); - return sprintf(buf, "%d\n", (link->aspm_enabled & state) ? 1 : 0); + return sysfs_emit(buf, "%d\n", (link->aspm_enabled & state) ? 1 : 0); } static ssize_t aspm_attr_store_common(struct device *dev, @@ -1265,7 +1265,7 @@ static ssize_t clkpm_show(struct device *dev, struct pci_dev *pdev = to_pci_dev(dev); struct pcie_link_state *link = pcie_aspm_get_link(pdev); - return sprintf(buf, "%d\n", link->clkpm_enabled); + return sysfs_emit(buf, "%d\n", link->clkpm_enabled); } static ssize_t clkpm_store(struct device *dev, diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c index e05aba86a317..c556e7beafe3 100644 --- a/drivers/pci/pcie/dpc.c +++ b/drivers/pci/pcie/dpc.c @@ -71,6 +71,58 @@ void pci_restore_dpc_state(struct pci_dev *dev) pci_write_config_word(dev, dev->dpc_cap + PCI_EXP_DPC_CTL, *cap); } +static DECLARE_WAIT_QUEUE_HEAD(dpc_completed_waitqueue); + +#ifdef CONFIG_HOTPLUG_PCI_PCIE +static bool dpc_completed(struct pci_dev *pdev) +{ + u16 status; + + pci_read_config_word(pdev, pdev->dpc_cap + PCI_EXP_DPC_STATUS, &status); + if ((status != 0xffff) && (status & PCI_EXP_DPC_STATUS_TRIGGER)) + return false; + + if (test_bit(PCI_DPC_RECOVERING, &pdev->priv_flags)) + return false; + + return true; +} + +/** + * pci_dpc_recovered - whether DPC triggered and has recovered successfully + * @pdev: PCI device + * + * Return true if DPC was triggered for @pdev and has recovered successfully. + * Wait for recovery if it hasn't completed yet. Called from the PCIe hotplug + * driver to recognize and ignore Link Down/Up events caused by DPC. + */ +bool pci_dpc_recovered(struct pci_dev *pdev) +{ + struct pci_host_bridge *host; + + if (!pdev->dpc_cap) + return false; + + /* + * Synchronization between hotplug and DPC is not supported + * if DPC is owned by firmware and EDR is not enabled. + */ + host = pci_find_host_bridge(pdev->bus); + if (!host->native_dpc && !IS_ENABLED(CONFIG_PCIE_EDR)) + return false; + + /* + * Need a timeout in case DPC never completes due to failure of + * dpc_wait_rp_inactive(). The spec doesn't mandate a time limit, + * but reports indicate that DPC completes within 4 seconds. + */ + wait_event_timeout(dpc_completed_waitqueue, dpc_completed(pdev), + msecs_to_jiffies(4000)); + + return test_and_clear_bit(PCI_DPC_RECOVERED, &pdev->priv_flags); +} +#endif /* CONFIG_HOTPLUG_PCI_PCIE */ + static int dpc_wait_rp_inactive(struct pci_dev *pdev) { unsigned long timeout = jiffies + HZ; @@ -91,8 +143,11 @@ static int dpc_wait_rp_inactive(struct pci_dev *pdev) pci_ers_result_t dpc_reset_link(struct pci_dev *pdev) { + pci_ers_result_t ret; u16 cap; + set_bit(PCI_DPC_RECOVERING, &pdev->priv_flags); + /* * DPC disables the Link automatically in hardware, so it has * already been reset by the time we get here. @@ -106,18 +161,27 @@ pci_ers_result_t dpc_reset_link(struct pci_dev *pdev) if (!pcie_wait_for_link(pdev, false)) pci_info(pdev, "Data Link Layer Link Active not cleared in 1000 msec\n"); - if (pdev->dpc_rp_extensions && dpc_wait_rp_inactive(pdev)) - return PCI_ERS_RESULT_DISCONNECT; + if (pdev->dpc_rp_extensions && dpc_wait_rp_inactive(pdev)) { + clear_bit(PCI_DPC_RECOVERED, &pdev->priv_flags); + ret = PCI_ERS_RESULT_DISCONNECT; + goto out; + } pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS, PCI_EXP_DPC_STATUS_TRIGGER); if (!pcie_wait_for_link(pdev, true)) { pci_info(pdev, "Data Link Layer Link Active not set in 1000 msec\n"); - return PCI_ERS_RESULT_DISCONNECT; + clear_bit(PCI_DPC_RECOVERED, &pdev->priv_flags); + ret = PCI_ERS_RESULT_DISCONNECT; + } else { + set_bit(PCI_DPC_RECOVERED, &pdev->priv_flags); + ret = PCI_ERS_RESULT_RECOVERED; } - - return PCI_ERS_RESULT_RECOVERED; +out: + clear_bit(PCI_DPC_RECOVERING, &pdev->priv_flags); + wake_up_all(&dpc_completed_waitqueue); + return ret; } static void dpc_process_rp_pio_error(struct pci_dev *pdev) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 275204646c68..cd6fcd848853 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -19,6 +19,7 @@ #include <linux/hypervisor.h> #include <linux/irqdomain.h> #include <linux/pm_runtime.h> +#include <linux/list_sort.h> #include "pci.h" #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ @@ -874,14 +875,31 @@ static void pci_set_bus_msi_domain(struct pci_bus *bus) dev_set_msi_domain(&bus->dev, d); } +static int res_cmp(void *priv, const struct list_head *a, + const struct list_head *b) +{ + struct resource_entry *entry1, *entry2; + + entry1 = container_of(a, struct resource_entry, node); + entry2 = container_of(b, struct resource_entry, node); + + if (entry1->res->flags != entry2->res->flags) + return entry1->res->flags > entry2->res->flags; + + if (entry1->offset != entry2->offset) + return entry1->offset > entry2->offset; + + return entry1->res->start > entry2->res->start; +} + static int pci_register_host_bridge(struct pci_host_bridge *bridge) { struct device *parent = bridge->dev.parent; - struct resource_entry *window, *n; + struct resource_entry *window, *next, *n; struct pci_bus *bus, *b; - resource_size_t offset; + resource_size_t offset, next_offset; LIST_HEAD(resources); - struct resource *res; + struct resource *res, *next_res; char addr[64], *fmt; const char *name; int err; @@ -961,11 +979,35 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) if (nr_node_ids > 1 && pcibus_to_node(bus) == NUMA_NO_NODE) dev_warn(&bus->dev, "Unknown NUMA node; performance will be reduced\n"); + /* Sort and coalesce contiguous windows */ + list_sort(NULL, &resources, res_cmp); + resource_list_for_each_entry_safe(window, n, &resources) { + if (list_is_last(&window->node, &resources)) + break; + + next = list_next_entry(window, node); + offset = window->offset; + res = window->res; + next_offset = next->offset; + next_res = next->res; + + if (res->flags != next_res->flags || offset != next_offset) + continue; + + if (res->end + 1 == next_res->start) { + next_res->start = res->start; + res->flags = res->start = res->end = 0; + } + } + /* Add initial resources to the bus */ resource_list_for_each_entry_safe(window, n, &resources) { - list_move_tail(&window->node, &bridge->windows); offset = window->offset; res = window->res; + if (!res->end) + continue; + + list_move_tail(&window->node, &bridge->windows); if (res->flags & IORESOURCE_BUS) pci_bus_insert_busn_res(bus, bus->number, res->end); @@ -1576,6 +1618,26 @@ static void set_pcie_untrusted(struct pci_dev *dev) dev->untrusted = true; } +static void pci_set_removable(struct pci_dev *dev) +{ + struct pci_dev *parent = pci_upstream_bridge(dev); + + /* + * We (only) consider everything downstream from an external_facing + * device to be removable by the user. We're mainly concerned with + * consumer platforms with user accessible thunderbolt ports that are + * vulnerable to DMA attacks, and we expect those ports to be marked by + * the firmware as external_facing. Devices in traditional hotplug + * slots can technically be removed, but the expectation is that unless + * the port is marked with external_facing, such devices are less + * accessible to user / may not be removed by end user, and thus not + * exposed as "removable" to userspace. + */ + if (parent && + (parent->external_facing || dev_is_removable(&parent->dev))) + dev_set_removable(&dev->dev, DEVICE_REMOVABLE); +} + /** * pci_ext_cfg_is_aliased - Is ext config space just an alias of std config? * @dev: PCI device @@ -1823,6 +1885,8 @@ int pci_setup_device(struct pci_dev *dev) /* Early fixups, before probing the BARs */ pci_fixup_device(pci_fixup_early, dev); + pci_set_removable(dev); + pci_info(dev, "[%04x:%04x] type %02x class %#08x\n", dev->vendor, dev->device, dev->hdr_type, dev->class); @@ -2227,6 +2291,7 @@ static void pci_release_dev(struct device *dev) pci_bus_put(pci_dev->bus); kfree(pci_dev->driver_override); bitmap_free(pci_dev->dma_alias_mask); + dev_dbg(dev, "device released\n"); kfree(pci_dev); } diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 22b2bb1109c9..6d74386eadc2 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -27,6 +27,7 @@ #include <linux/nvme.h> #include <linux/platform_data/x86/apple.h> #include <linux/pm_runtime.h> +#include <linux/suspend.h> #include <linux/switchtec.h> #include <asm/dma.h> /* isa_dma_bridge_buggy */ #include "pci.h" @@ -3656,6 +3657,16 @@ static void quirk_apple_poweroff_thunderbolt(struct pci_dev *dev) return; if (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM) return; + + /* + * SXIO/SXFP/SXLF turns off power to the Thunderbolt controller. + * We don't know how to turn it back on again, but firmware does, + * so we can only use SXIO/SXFP/SXLF if we're suspending via + * firmware. + */ + if (!pm_suspend_via_firmware()) + return; + bridge = ACPI_HANDLE(&dev->dev); if (!bridge) return; diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index d627dd9179b4..751a26668e3a 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c @@ -39,19 +39,19 @@ static const struct sysfs_ops pci_slot_sysfs_ops = { static ssize_t address_read_file(struct pci_slot *slot, char *buf) { if (slot->number == 0xff) - return sprintf(buf, "%04x:%02x\n", - pci_domain_nr(slot->bus), - slot->bus->number); - else - return sprintf(buf, "%04x:%02x:%02x\n", - pci_domain_nr(slot->bus), - slot->bus->number, - slot->number); + return sysfs_emit(buf, "%04x:%02x\n", + pci_domain_nr(slot->bus), + slot->bus->number); + + return sysfs_emit(buf, "%04x:%02x:%02x\n", + pci_domain_nr(slot->bus), + slot->bus->number, + slot->number); } static ssize_t bus_speed_read(enum pci_bus_speed speed, char *buf) { - return sprintf(buf, "%s\n", pci_speed_string(speed)); + return sysfs_emit(buf, "%s\n", pci_speed_string(speed)); } static ssize_t max_speed_read_file(struct pci_slot *slot, char *buf) diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c index ba52459928f7..0b301f8be9ed 100644 --- a/drivers/pci/switch/switchtec.c +++ b/drivers/pci/switch/switchtec.c @@ -280,7 +280,7 @@ static ssize_t device_version_show(struct device *dev, ver = ioread32(&stdev->mmio_sys_info->device_version); - return sprintf(buf, "%x\n", ver); + return sysfs_emit(buf, "%x\n", ver); } static DEVICE_ATTR_RO(device_version); @@ -292,7 +292,7 @@ static ssize_t fw_version_show(struct device *dev, ver = ioread32(&stdev->mmio_sys_info->firmware_version); - return sprintf(buf, "%08x\n", ver); + return sysfs_emit(buf, "%08x\n", ver); } static DEVICE_ATTR_RO(fw_version); @@ -344,7 +344,7 @@ static ssize_t component_vendor_show(struct device *dev, /* component_vendor field not supported after gen3 */ if (stdev->gen != SWITCHTEC_GEN3) - return sprintf(buf, "none\n"); + return sysfs_emit(buf, "none\n"); return io_string_show(buf, &si->gen3.component_vendor, sizeof(si->gen3.component_vendor)); @@ -359,9 +359,9 @@ static ssize_t component_id_show(struct device *dev, /* component_id field not supported after gen3 */ if (stdev->gen != SWITCHTEC_GEN3) - return sprintf(buf, "none\n"); + return sysfs_emit(buf, "none\n"); - return sprintf(buf, "PM%04X\n", id); + return sysfs_emit(buf, "PM%04X\n", id); } static DEVICE_ATTR_RO(component_id); @@ -373,9 +373,9 @@ static ssize_t component_revision_show(struct device *dev, /* component_revision field not supported after gen3 */ if (stdev->gen != SWITCHTEC_GEN3) - return sprintf(buf, "255\n"); + return sysfs_emit(buf, "255\n"); - return sprintf(buf, "%d\n", rev); + return sysfs_emit(buf, "%d\n", rev); } static DEVICE_ATTR_RO(component_revision); @@ -384,7 +384,7 @@ static ssize_t partition_show(struct device *dev, { struct switchtec_dev *stdev = to_stdev(dev); - return sprintf(buf, "%d\n", stdev->partition); + return sysfs_emit(buf, "%d\n", stdev->partition); } static DEVICE_ATTR_RO(partition); @@ -393,7 +393,7 @@ static ssize_t partition_count_show(struct device *dev, { struct switchtec_dev *stdev = to_stdev(dev); - return sprintf(buf, "%d\n", stdev->partition_count); + return sysfs_emit(buf, "%d\n", stdev->partition_count); } static DEVICE_ATTR_RO(partition_count); diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 54c1f2f0985f..7dd35f1b9cc5 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -61,6 +61,15 @@ config USB_LGM_PHY interface to interact with USB GEN-II and USB 3.x PHY that is part of the Intel network SOC. +config PHY_CAN_TRANSCEIVER + tristate "CAN transceiver PHY" + select GENERIC_PHY + help + This option enables support for CAN transceivers as a PHY. This + driver provides function for putting the transceivers in various + functional modes using gpios and sets the attribute max link + rate, for CAN drivers. + source "drivers/phy/allwinner/Kconfig" source "drivers/phy/amlogic/Kconfig" source "drivers/phy/broadcom/Kconfig" diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index adac1b1a39d1..01e9efffc726 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_GENERIC_PHY) += phy-core.o obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) += phy-core-mipi-dphy.o +obj-$(CONFIG_PHY_CAN_TRANSCEIVER) += phy-can-transceiver.o obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o obj-$(CONFIG_PHY_XGENE) += phy-xgene.o obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o diff --git a/drivers/phy/broadcom/phy-bcm-ns-usb3.c b/drivers/phy/broadcom/phy-bcm-ns-usb3.c index eb10ffa13a62..b1adaecc26f8 100644 --- a/drivers/phy/broadcom/phy-bcm-ns-usb3.c +++ b/drivers/phy/broadcom/phy-bcm-ns-usb3.c @@ -215,10 +215,8 @@ static int bcm_ns_usb3_mdio_probe(struct mdio_device *mdiodev) return err; usb3->dmp = devm_ioremap_resource(dev, &res); - if (IS_ERR(usb3->dmp)) { - dev_err(dev, "Failed to map DMP regs\n"); + if (IS_ERR(usb3->dmp)) return PTR_ERR(usb3->dmp); - } usb3->phy = devm_phy_create(dev, NULL, &ops); if (IS_ERR(usb3->phy)) { diff --git a/drivers/phy/hisilicon/Kconfig b/drivers/phy/hisilicon/Kconfig index 1c73053bcc98..4d008cfc279c 100644 --- a/drivers/phy/hisilicon/Kconfig +++ b/drivers/phy/hisilicon/Kconfig @@ -23,6 +23,16 @@ config PHY_HI3660_USB To compile this driver as a module, choose M here. +config PHY_HI3670_USB + tristate "hi3670 USB PHY support" + depends on (ARCH_HISI && ARM64) || COMPILE_TEST + select GENERIC_PHY + select MFD_SYSCON + help + Enable this to support the HISILICON HI3670 USB PHY. + + To compile this driver as a module, choose M here. + config PHY_HISTB_COMBPHY tristate "HiSilicon STB SoCs COMBPHY support" depends on (ARCH_HISI && ARM64) || COMPILE_TEST diff --git a/drivers/phy/hisilicon/Makefile b/drivers/phy/hisilicon/Makefile index 92e874ae9c74..51729868145b 100644 --- a/drivers/phy/hisilicon/Makefile +++ b/drivers/phy/hisilicon/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_PHY_HI6220_USB) += phy-hi6220-usb.o obj-$(CONFIG_PHY_HI3660_USB) += phy-hi3660-usb3.o +obj-$(CONFIG_PHY_HI3670_USB) += phy-hi3670-usb3.o obj-$(CONFIG_PHY_HISTB_COMBPHY) += phy-histb-combphy.o obj-$(CONFIG_PHY_HISI_INNO_USB2) += phy-hisi-inno-usb2.o obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o diff --git a/drivers/staging/hikey9xx/phy-hi3670-usb3.c b/drivers/phy/hisilicon/phy-hi3670-usb3.c index e7e579ce0302..b9ffe08abaab 100644 --- a/drivers/staging/hikey9xx/phy-hi3670-usb3.c +++ b/drivers/phy/hisilicon/phy-hi3670-usb3.c @@ -148,10 +148,8 @@ static int hi3670_phy_cr_clk(struct regmap *usb31misc) return ret; /* Clock down */ - ret = regmap_update_bits(usb31misc, USB_MISC_CFG54, - CFG54_USB31PHY_CR_CLK, 0); - - return ret; + return regmap_update_bits(usb31misc, USB_MISC_CFG54, + CFG54_USB31PHY_CR_CLK, 0); } static int hi3670_phy_cr_set_sel(struct regmap *usb31misc) @@ -215,17 +213,14 @@ static int hi3670_phy_cr_set_addr(struct regmap *usb31misc, u32 addr) return ret; reg = FIELD_PREP(CFG54_USB31PHY_CR_ADDR_MASK, addr); - ret = regmap_update_bits(usb31misc, USB_MISC_CFG54, - CFG54_USB31PHY_CR_ADDR_MASK, reg); - return ret; + return regmap_update_bits(usb31misc, USB_MISC_CFG54, + CFG54_USB31PHY_CR_ADDR_MASK, reg); } static int hi3670_phy_cr_read(struct regmap *usb31misc, u32 addr, u32 *val) { - int reg; - int i; - int ret; + int reg, i, ret; for (i = 0; i < 100; i++) { ret = hi3670_phy_cr_clk(usb31misc); @@ -286,9 +281,7 @@ static int hi3670_phy_cr_write(struct regmap *usb31misc, u32 addr, u32 val) if (ret) return ret; - ret = hi3670_phy_cr_wait_ack(usb31misc); - - return ret; + return hi3670_phy_cr_wait_ack(usb31misc); } static int hi3670_phy_set_params(struct hi3670_priv *priv) diff --git a/drivers/phy/intel/phy-intel-keembay-emmc.c b/drivers/phy/intel/phy-intel-keembay-emmc.c index eb7c635ed89a..0eb11ac7c2e2 100644 --- a/drivers/phy/intel/phy-intel-keembay-emmc.c +++ b/drivers/phy/intel/phy-intel-keembay-emmc.c @@ -95,7 +95,8 @@ static int keembay_emmc_phy_power(struct phy *phy, bool on_off) else freqsel = 0x0; - if (mhz < 50 || mhz > 200) + /* Check for EMMC clock rate*/ + if (mhz > 175) dev_warn(&phy->dev, "Unsupported rate: %d MHz\n", mhz); /* diff --git a/drivers/phy/marvell/phy-mmp3-hsic.c b/drivers/phy/marvell/phy-mmp3-hsic.c index 47c1e8894939..7cccf01848d8 100644 --- a/drivers/phy/marvell/phy-mmp3-hsic.c +++ b/drivers/phy/marvell/phy-mmp3-hsic.c @@ -47,10 +47,8 @@ static int mmp3_hsic_phy_probe(struct platform_device *pdev) resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(dev, resource); - if (IS_ERR(base)) { - dev_err(dev, "failed to remap PHY regs\n"); + if (IS_ERR(base)) return PTR_ERR(base); - } phy = devm_phy_create(dev, NULL, &mmp3_hsic_phy_ops); if (IS_ERR(phy)) { diff --git a/drivers/phy/mediatek/phy-mtk-hdmi.c b/drivers/phy/mediatek/phy-mtk-hdmi.c index 8313bd517e4c..8ad8f717ef43 100644 --- a/drivers/phy/mediatek/phy-mtk-hdmi.c +++ b/drivers/phy/mediatek/phy-mtk-hdmi.c @@ -119,9 +119,7 @@ static int mtk_hdmi_phy_probe(struct platform_device *pdev) mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); hdmi_phy->regs = devm_ioremap_resource(dev, mem); if (IS_ERR(hdmi_phy->regs)) { - ret = PTR_ERR(hdmi_phy->regs); - dev_err(dev, "Failed to get memory resource: %d\n", ret); - return ret; + return PTR_ERR(hdmi_phy->regs); } ref_clk = devm_clk_get(dev, "pll_ref"); diff --git a/drivers/phy/mediatek/phy-mtk-mipi-dsi.c b/drivers/phy/mediatek/phy-mtk-mipi-dsi.c index c51114d8e437..01cf31633019 100644 --- a/drivers/phy/mediatek/phy-mtk-mipi-dsi.c +++ b/drivers/phy/mediatek/phy-mtk-mipi-dsi.c @@ -151,9 +151,7 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev) mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mipi_tx->regs = devm_ioremap_resource(dev, mem); if (IS_ERR(mipi_tx->regs)) { - ret = PTR_ERR(mipi_tx->regs); - dev_err(dev, "Failed to get memory resource: %d\n", ret); - return ret; + return PTR_ERR(mipi_tx->regs); } ref_clk = devm_clk_get(dev, NULL); diff --git a/drivers/phy/phy-can-transceiver.c b/drivers/phy/phy-can-transceiver.c new file mode 100644 index 000000000000..c2cb93b4df71 --- /dev/null +++ b/drivers/phy/phy-can-transceiver.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * phy-can-transceiver.c - phy driver for CAN transceivers + * + * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com + * + */ +#include<linux/phy/phy.h> +#include<linux/platform_device.h> +#include<linux/module.h> +#include<linux/gpio.h> +#include<linux/gpio/consumer.h> + +struct can_transceiver_data { + u32 flags; +#define CAN_TRANSCEIVER_STB_PRESENT BIT(0) +#define CAN_TRANSCEIVER_EN_PRESENT BIT(1) +}; + +struct can_transceiver_phy { + struct phy *generic_phy; + struct gpio_desc *standby_gpio; + struct gpio_desc *enable_gpio; +}; + +/* Power on function */ +static int can_transceiver_phy_power_on(struct phy *phy) +{ + struct can_transceiver_phy *can_transceiver_phy = phy_get_drvdata(phy); + + if (can_transceiver_phy->standby_gpio) + gpiod_set_value_cansleep(can_transceiver_phy->standby_gpio, 0); + if (can_transceiver_phy->enable_gpio) + gpiod_set_value_cansleep(can_transceiver_phy->enable_gpio, 1); + + return 0; +} + +/* Power off function */ +static int can_transceiver_phy_power_off(struct phy *phy) +{ + struct can_transceiver_phy *can_transceiver_phy = phy_get_drvdata(phy); + + if (can_transceiver_phy->standby_gpio) + gpiod_set_value_cansleep(can_transceiver_phy->standby_gpio, 1); + if (can_transceiver_phy->enable_gpio) + gpiod_set_value_cansleep(can_transceiver_phy->enable_gpio, 0); + + return 0; +} + +static const struct phy_ops can_transceiver_phy_ops = { + .power_on = can_transceiver_phy_power_on, + .power_off = can_transceiver_phy_power_off, + .owner = THIS_MODULE, +}; + +static const struct can_transceiver_data tcan1042_drvdata = { + .flags = CAN_TRANSCEIVER_STB_PRESENT, +}; + +static const struct can_transceiver_data tcan1043_drvdata = { + .flags = CAN_TRANSCEIVER_STB_PRESENT | CAN_TRANSCEIVER_EN_PRESENT, +}; + +static const struct of_device_id can_transceiver_phy_ids[] = { + { + .compatible = "ti,tcan1042", + .data = &tcan1042_drvdata + }, + { + .compatible = "ti,tcan1043", + .data = &tcan1043_drvdata + }, + { } +}; +MODULE_DEVICE_TABLE(of, can_transceiver_phy_ids); + +static int can_transceiver_phy_probe(struct platform_device *pdev) +{ + struct phy_provider *phy_provider; + struct device *dev = &pdev->dev; + struct can_transceiver_phy *can_transceiver_phy; + const struct can_transceiver_data *drvdata; + const struct of_device_id *match; + struct phy *phy; + struct gpio_desc *standby_gpio; + struct gpio_desc *enable_gpio; + u32 max_bitrate = 0; + + can_transceiver_phy = devm_kzalloc(dev, sizeof(struct can_transceiver_phy), GFP_KERNEL); + if (!can_transceiver_phy) + return -ENOMEM; + + match = of_match_node(can_transceiver_phy_ids, pdev->dev.of_node); + drvdata = match->data; + + phy = devm_phy_create(dev, dev->of_node, + &can_transceiver_phy_ops); + if (IS_ERR(phy)) { + dev_err(dev, "failed to create can transceiver phy\n"); + return PTR_ERR(phy); + } + + device_property_read_u32(dev, "max-bitrate", &max_bitrate); + if (!max_bitrate) + dev_warn(dev, "Invalid value for transceiver max bitrate. Ignoring bitrate limit\n"); + phy->attrs.max_link_rate = max_bitrate; + + can_transceiver_phy->generic_phy = phy; + + if (drvdata->flags & CAN_TRANSCEIVER_STB_PRESENT) { + standby_gpio = devm_gpiod_get(dev, "standby", GPIOD_OUT_HIGH); + if (IS_ERR(standby_gpio)) + return PTR_ERR(standby_gpio); + can_transceiver_phy->standby_gpio = standby_gpio; + } + + if (drvdata->flags & CAN_TRANSCEIVER_EN_PRESENT) { + enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); + if (IS_ERR(enable_gpio)) + return PTR_ERR(enable_gpio); + can_transceiver_phy->enable_gpio = enable_gpio; + } + + phy_set_drvdata(can_transceiver_phy->generic_phy, can_transceiver_phy); + + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + + return PTR_ERR_OR_ZERO(phy_provider); +} + +static struct platform_driver can_transceiver_phy_driver = { + .probe = can_transceiver_phy_probe, + .driver = { + .name = "can-transceiver-phy", + .of_match_table = can_transceiver_phy_ids, + }, +}; + +module_platform_driver(can_transceiver_phy_driver); + +MODULE_AUTHOR("Faiz Abbas <faiz_abbas@ti.com>"); +MODULE_AUTHOR("Aswath Govindraju <a-govindraju@ti.com>"); +MODULE_DESCRIPTION("CAN TRANSCEIVER PHY driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/phy/phy-core-mipi-dphy.c b/drivers/phy/phy-core-mipi-dphy.c index 77fe65367ce5..288c9c67aa74 100644 --- a/drivers/phy/phy-core-mipi-dphy.c +++ b/drivers/phy/phy-core-mipi-dphy.c @@ -15,7 +15,7 @@ /* * Minimum D-PHY timings based on MIPI D-PHY specification. Derived * from the valid ranges specified in Section 6.9, Table 14, Page 41 - * of the D-PHY specification (v2.1). + * of the D-PHY specification (v1.2). */ int phy_mipi_dphy_get_default_config(unsigned long pixel_clock, unsigned int bpp, diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index ccb575b13777..91e28d6ce450 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -697,16 +697,18 @@ struct phy *phy_get(struct device *dev, const char *string) struct phy *phy; struct device_link *link; - if (string == NULL) { - dev_WARN(dev, "missing string\n"); - return ERR_PTR(-EINVAL); - } - if (dev->of_node) { - index = of_property_match_string(dev->of_node, "phy-names", - string); + if (string) + index = of_property_match_string(dev->of_node, "phy-names", + string); + else + index = 0; phy = _of_phy_get(dev->of_node, index); } else { + if (string == NULL) { + dev_WARN(dev, "missing string\n"); + return ERR_PTR(-EINVAL); + } phy = phy_find(dev, string); } if (IS_ERR(phy)) diff --git a/drivers/phy/phy-xgene.c b/drivers/phy/phy-xgene.c index f4cd590fbde7..d0f4546648f0 100644 --- a/drivers/phy/phy-xgene.c +++ b/drivers/phy/phy-xgene.c @@ -961,7 +961,8 @@ static void xgene_phy_sata_cfg_lanes(struct xgene_phy_ctx *ctx) serdes_wr(ctx, lane, RXTX_REG1, val); /* Latch VTT value based on the termination to ground and - enable TX FIFO */ + * enable TX FIFO + */ serdes_rd(ctx, lane, RXTX_REG2, &val); val = RXTX_REG2_VTT_ENA_SET(val, 0x1); val = RXTX_REG2_VTT_SEL_SET(val, 0x1); diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c index 7877f70cf86f..cfe359488f5c 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c @@ -35,6 +35,7 @@ #define PLL_READY_GATE_EN BIT(3) /* QPHY_PCS_STATUS bit */ #define PHYSTATUS BIT(6) +#define PHYSTATUS_4_20 BIT(7) /* QPHY_PCS_READY_STATUS & QPHY_COM_PCS_READY_STATUS bit */ #define PCS_READY BIT(0) @@ -143,6 +144,13 @@ static const unsigned int msm8996_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_PCS_READY_STATUS] = 0x168, }; +static const unsigned int ipq_pciephy_gen3_regs_layout[QPHY_LAYOUT_SIZE] = { + [QPHY_SW_RESET] = 0x00, + [QPHY_START_CTRL] = 0x44, + [QPHY_PCS_STATUS] = 0x14, + [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, +}; + static const unsigned int pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_COM_SW_RESET] = 0x400, [QPHY_COM_POWER_DOWN_CONTROL] = 0x404, @@ -614,6 +622,113 @@ static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl[] = { QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG2, 0x08), }; +static const struct qmp_phy_init_tbl ipq6018_pcie_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER1, 0x7d), + QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER2, 0x01), + QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE0, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE0, 0x05), + QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE1, 0x08), + QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE1, 0x04), + QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CLKBUFLR_EN, 0x18), + QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_ENABLE1, 0x90), + QMP_PHY_INIT_CFG(QSERDES_PLL_SYS_CLK_CTRL, 0x02), + QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_BUF_ENABLE, 0x07), + QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_IVCO, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE0, 0xd4), + QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE0, 0x14), + QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE1, 0xaa), + QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE1, 0x29), + QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TRIM, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE0, 0x09), + QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE1, 0x09), + QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE1, 0x16), + QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE0, 0x28), + QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE1, 0x28), + QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CTRL_BY_PSM, 0x01), + QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_EN_SEL, 0x08), + QMP_PHY_INIT_CFG(QSERDES_PLL_RESETSM_CNTRL, 0x20), + QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP_EN, 0x42), + QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE0, 0x68), + QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE1, 0x53), + QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE0, 0xab), + QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE0, 0xaa), + QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE1, 0x55), + QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE1, 0x55), + QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE1, 0x05), + QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE0, 0xa0), + QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE1, 0xa0), + QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE0, 0x24), + QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE1, 0xb4), + QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE1, 0x03), + QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_SELECT, 0x32), + QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x01), + QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x00), + QMP_PHY_INIT_CFG(QSERDES_PLL_CMN_CONFIG, 0x06), + QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05), + QMP_PHY_INIT_CFG(QSERDES_PLL_CORECLK_DIV_MODE1, 0x08), +}; + +static const struct qmp_phy_init_tbl ipq6018_pcie_tx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_TX0_RES_CODE_LANE_OFFSET_TX, 0x02), + QMP_PHY_INIT_CFG(QSERDES_TX0_LANE_MODE_1, 0x06), + QMP_PHY_INIT_CFG(QSERDES_TX0_RCV_DETECT_LVL_2, 0x12), +}; + +static const struct qmp_phy_init_tbl ipq6018_pcie_rx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_FO_GAIN, 0x0c), + QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_SO_GAIN, 0x02), + QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), + QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_PI_CONTROLS, 0x70), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL2, 0x61), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL3, 0x04), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL4, 0x1e), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_IDAC_TSETTLE_LOW, 0xc0), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_IDAC_TSETTLE_HIGH, 0x00), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x73), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), + QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_ENABLES, 0x1c), + QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_CNTRL, 0x03), + QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_DEGLITCH_CNTRL, 0x14), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_LOW, 0xf0), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH, 0x01), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH2, 0x2f), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH3, 0xd3), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH4, 0x40), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_LOW, 0x01), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH, 0x02), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH2, 0xc8), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH3, 0x09), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH4, 0xb1), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_LOW, 0x00), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH, 0x02), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH2, 0xc8), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH3, 0x09), + QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH4, 0xb1), + QMP_PHY_INIT_CFG(QSERDES_RX0_DFE_EN_TIMER, 0x04), +}; + +static const struct qmp_phy_init_tbl ipq6018_pcie_pcs_tbl[] = { + QMP_PHY_INIT_CFG(PCS_COM_FLL_CNTRL1, 0x01), + QMP_PHY_INIT_CFG(PCS_COM_REFGEN_REQ_CONFIG1, 0x0d), + QMP_PHY_INIT_CFG(PCS_COM_G12S1_TXDEEMPH_M3P5DB, 0x10), + QMP_PHY_INIT_CFG(PCS_COM_RX_SIGDET_LVL, 0xaa), + QMP_PHY_INIT_CFG(PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), + QMP_PHY_INIT_CFG(PCS_COM_RX_DCC_CAL_CONFIG, 0x01), + QMP_PHY_INIT_CFG(PCS_COM_EQ_CONFIG5, 0x01), + QMP_PHY_INIT_CFG(PCS_PCIE_POWER_STATE_CONFIG2, 0x0d), + QMP_PHY_INIT_CFG(PCS_PCIE_POWER_STATE_CONFIG4, 0x07), + QMP_PHY_INIT_CFG(PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), + QMP_PHY_INIT_CFG(PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), + QMP_PHY_INIT_CFG(PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), + QMP_PHY_INIT_CFG(PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), + QMP_PHY_INIT_CFG(PCS_PCIE_EQ_CONFIG1, 0x11), + QMP_PHY_INIT_CFG(PCS_PCIE_PRESET_P10_PRE, 0x00), + QMP_PHY_INIT_CFG(PCS_PCIE_PRESET_P10_POST, 0x58), +}; + static const struct qmp_phy_init_tbl ipq8074_pcie_serdes_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x18), QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), @@ -2110,6 +2225,101 @@ static const struct qmp_phy_init_tbl sdx55_usb3_uniphy_rx_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), }; +static const struct qmp_phy_init_tbl sdx55_qmp_pcie_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BG_TIMER, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN, 0x18), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYS_CLK_CTRL, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x19), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x19), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x46), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_CFG, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x7f), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x4b), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x50), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0, 0xfb), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE1, 0xfb), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE1, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x12), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE0, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_CONFIG, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_MISC1, 0x88), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTERNAL_DIG_CORECLK_DIV, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_MODE, 0x17), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_DC_LEVEL_CTRL, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x56), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1d), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0x4b), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x22), +}; + +static const struct qmp_phy_init_tbl sdx55_qmp_pcie_tx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_1, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_2, 0xf6), + QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_3, 0x13), + QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_VMODE_CTRL1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_PI_QEC_CTRL, 0x00), +}; + +static const struct qmp_phy_init_tbl sdx55_qmp_pcie_rx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_FO_GAIN_RATE2, 0x0c), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_UCDR_PI_CONTROLS, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_AUX_DATA_TCOARSE_TFINE, 0x7f), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_3, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_DAC_ENABLE1, 0x0c), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_DAC_ENABLE2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_VGA_CAL_CNTRL2, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x27), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B1, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B2, 0x5a), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B3, 0x09), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B4, 0x37), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B0, 0xbd), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B1, 0xf9), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B2, 0xbf), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B3, 0xce), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B4, 0x62), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B0, 0xbf), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B1, 0x7d), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B2, 0xbf), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B3, 0xcf), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B4, 0xd6), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_PHPRE_CTRL, 0xa0), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), + QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_MARG_COARSE_CTRL2, 0x12), +}; + +static const struct qmp_phy_init_tbl sdx55_qmp_pcie_pcs_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_RX_SIGDET_LVL, 0x77), + QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG2, 0x01), + QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG4, 0x16), + QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG5, 0x02), +}; + +static const struct qmp_phy_init_tbl sdx55_qmp_pcie_pcs_misc_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_EQ_CONFIG1, 0x17), + QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G3_RXEQEVAL_TIME, 0x13), + QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_RXEQEVAL_TIME, 0x13), + QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG2, 0x01), + QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG5, 0x02), + QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_LANE1_INSIG_SW_CTRL2, 0x00), + QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_LANE1_INSIG_MX_CTRL2, 0x00), +}; + static const struct qmp_phy_init_tbl sm8350_ufsphy_serdes_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0xd9), QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x11), @@ -2411,6 +2621,8 @@ struct qmp_phy_cfg { unsigned int start_ctrl; unsigned int pwrdn_ctrl; unsigned int mask_com_pcs_ready; + /* bit offset of PHYSTATUS in QPHY_PCS_STATUS register */ + unsigned int phy_status; /* true, if PHY has a separate PHY_COM control block */ bool has_phy_com_ctrl; @@ -2624,6 +2836,7 @@ static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = { .start_ctrl = SERDES_START | PCS_START, .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, }; static const struct qmp_phy_cfg msm8996_pciephy_cfg = { @@ -2649,6 +2862,7 @@ static const struct qmp_phy_cfg msm8996_pciephy_cfg = { .start_ctrl = PCS_START | PLL_READY_GATE_EN, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, .mask_com_pcs_ready = PCS_READY, + .phy_status = PHYSTATUS, .has_phy_com_ctrl = true, .has_lane_rst = true, @@ -2678,6 +2892,7 @@ static const struct qmp_phy_cfg msm8996_ufs_cfg = { .start_ctrl = SERDES_START, .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, .no_pcs_sw_reset = true, }; @@ -2704,6 +2919,7 @@ static const struct qmp_phy_cfg msm8996_usb3phy_cfg = { .start_ctrl = SERDES_START | PCS_START, .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, }; static const char * const ipq8074_pciephy_clk_l[] = { @@ -2736,6 +2952,37 @@ static const struct qmp_phy_cfg ipq8074_pciephy_cfg = { .start_ctrl = SERDES_START | PCS_START, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, + + .has_phy_com_ctrl = false, + .has_lane_rst = false, + .has_pwrdn_delay = true, + .pwrdn_delay_min = 995, /* us */ + .pwrdn_delay_max = 1005, /* us */ +}; + +static const struct qmp_phy_cfg ipq6018_pciephy_cfg = { + .type = PHY_TYPE_PCIE, + .nlanes = 1, + + .serdes_tbl = ipq6018_pcie_serdes_tbl, + .serdes_tbl_num = ARRAY_SIZE(ipq6018_pcie_serdes_tbl), + .tx_tbl = ipq6018_pcie_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(ipq6018_pcie_tx_tbl), + .rx_tbl = ipq6018_pcie_rx_tbl, + .rx_tbl_num = ARRAY_SIZE(ipq6018_pcie_rx_tbl), + .pcs_tbl = ipq6018_pcie_pcs_tbl, + .pcs_tbl_num = ARRAY_SIZE(ipq6018_pcie_pcs_tbl), + .clk_list = ipq8074_pciephy_clk_l, + .num_clks = ARRAY_SIZE(ipq8074_pciephy_clk_l), + .reset_list = ipq8074_pciephy_reset_l, + .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l), + .vreg_list = NULL, + .num_vregs = 0, + .regs = ipq_pciephy_gen3_regs_layout, + + .start_ctrl = SERDES_START | PCS_START, + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, .has_phy_com_ctrl = false, .has_lane_rst = false, @@ -2768,6 +3015,7 @@ static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = { .start_ctrl = PCS_START | SERDES_START, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, .has_pwrdn_delay = true, .pwrdn_delay_min = 995, /* us */ @@ -2796,6 +3044,7 @@ static const struct qmp_phy_cfg sdm845_qhp_pciephy_cfg = { .start_ctrl = PCS_START | SERDES_START, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, .has_pwrdn_delay = true, .pwrdn_delay_min = 995, /* us */ @@ -2834,6 +3083,7 @@ static const struct qmp_phy_cfg sm8250_qmp_gen3x1_pciephy_cfg = { .start_ctrl = PCS_START | SERDES_START, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, .has_pwrdn_delay = true, .pwrdn_delay_min = 995, /* us */ @@ -2872,6 +3122,7 @@ static const struct qmp_phy_cfg sm8250_qmp_gen3x2_pciephy_cfg = { .start_ctrl = PCS_START | SERDES_START, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, .is_dual_lane_phy = true, .has_pwrdn_delay = true, @@ -2901,6 +3152,7 @@ static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = { .start_ctrl = SERDES_START | PCS_START, .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, .has_pwrdn_delay = true, .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, @@ -2932,6 +3184,7 @@ static const struct qmp_phy_cfg sc7180_usb3phy_cfg = { .start_ctrl = SERDES_START | PCS_START, .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, .has_pwrdn_delay = true, .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, @@ -3003,6 +3256,7 @@ static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = { .start_ctrl = SERDES_START | PCS_START, .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, .has_pwrdn_delay = true, .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, @@ -3029,6 +3283,7 @@ static const struct qmp_phy_cfg sdm845_ufsphy_cfg = { .start_ctrl = SERDES_START, .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, .is_dual_lane_phy = true, .no_pcs_sw_reset = true, @@ -3056,6 +3311,7 @@ static const struct qmp_phy_cfg msm8998_pciephy_cfg = { .start_ctrl = SERDES_START | PCS_START, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, }; static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { @@ -3080,6 +3336,7 @@ static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { .start_ctrl = SERDES_START | PCS_START, .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, .is_dual_lane_phy = true, }; @@ -3104,6 +3361,7 @@ static const struct qmp_phy_cfg sm8150_ufsphy_cfg = { .start_ctrl = SERDES_START, .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, .is_dual_lane_phy = true, }; @@ -3130,6 +3388,8 @@ static const struct qmp_phy_cfg sm8150_usb3phy_cfg = { .start_ctrl = SERDES_START | PCS_START, .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, + .has_pwrdn_delay = true, .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, @@ -3161,6 +3421,7 @@ static const struct qmp_phy_cfg sm8150_usb3_uniphy_cfg = { .start_ctrl = SERDES_START | PCS_START, .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, .has_pwrdn_delay = true, .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, @@ -3189,6 +3450,7 @@ static const struct qmp_phy_cfg sm8250_usb3phy_cfg = { .start_ctrl = SERDES_START | PCS_START, .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, .has_pwrdn_delay = true, .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, @@ -3220,6 +3482,7 @@ static const struct qmp_phy_cfg sm8250_usb3_uniphy_cfg = { .start_ctrl = SERDES_START | PCS_START, .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, .has_pwrdn_delay = true, .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, @@ -3288,12 +3551,45 @@ static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = { .start_ctrl = SERDES_START | PCS_START, .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, .has_pwrdn_delay = true, .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, }; +static const struct qmp_phy_cfg sdx55_qmp_pciephy_cfg = { + .type = PHY_TYPE_PCIE, + .nlanes = 2, + + .serdes_tbl = sdx55_qmp_pcie_serdes_tbl, + .serdes_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_serdes_tbl), + .tx_tbl = sdx55_qmp_pcie_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_tx_tbl), + .rx_tbl = sdx55_qmp_pcie_rx_tbl, + .rx_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_rx_tbl), + .pcs_tbl = sdx55_qmp_pcie_pcs_tbl, + .pcs_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_pcs_tbl), + .pcs_misc_tbl = sdx55_qmp_pcie_pcs_misc_tbl, + .pcs_misc_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_pcs_misc_tbl), + .clk_list = sdm845_pciephy_clk_l, + .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), + .reset_list = sdm845_pciephy_reset_l, + .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = sm8250_pcie_regs_layout, + + .start_ctrl = PCS_START | SERDES_START, + .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS_4_20, + + .is_dual_lane_phy = true, + .has_pwrdn_delay = true, + .pwrdn_delay_min = 995, /* us */ + .pwrdn_delay_max = 1005, /* us */ +}; + static const struct qmp_phy_cfg sm8350_ufsphy_cfg = { .type = PHY_TYPE_UFS, .nlanes = 2, @@ -3314,6 +3610,7 @@ static const struct qmp_phy_cfg sm8350_ufsphy_cfg = { .start_ctrl = SERDES_START, .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, .is_dual_lane_phy = true, }; @@ -3340,6 +3637,7 @@ static const struct qmp_phy_cfg sm8350_usb3phy_cfg = { .start_ctrl = SERDES_START | PCS_START, .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, .has_pwrdn_delay = true, .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, @@ -3371,6 +3669,7 @@ static const struct qmp_phy_cfg sm8350_usb3_uniphy_cfg = { .start_ctrl = SERDES_START | PCS_START, .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, .has_pwrdn_delay = true, .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, @@ -3993,10 +4292,8 @@ static int qcom_qmp_phy_com_init(struct qmp_phy *qphy) } ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); - if (ret) { - dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret); + if (ret) goto err_rst; - } if (cfg->has_phy_dp_com_ctrl) { qphy_setbits(dp_com, QPHY_V3_DP_COM_POWER_DOWN_CTRL, @@ -4238,7 +4535,7 @@ static int qcom_qmp_phy_power_on(struct phy *phy) ready = PCS_READY; } else { status = pcs + cfg->regs[QPHY_PCS_STATUS]; - mask = PHYSTATUS; + mask = cfg->phy_status; ready = 0; } @@ -4430,10 +4727,8 @@ static int __maybe_unused qcom_qmp_phy_runtime_resume(struct device *dev) } ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); - if (ret) { - dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret); + if (ret) return ret; - } ret = clk_prepare_enable(qphy->pipe_clk); if (ret) { @@ -4928,6 +5223,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = { .compatible = "qcom,ipq8074-qmp-pcie-phy", .data = &ipq8074_pciephy_cfg, }, { + .compatible = "qcom,ipq6018-qmp-pcie-phy", + .data = &ipq6018_pciephy_cfg, + }, { .compatible = "qcom,sc7180-qmp-usb3-phy", .data = &sc7180_usb3phy_cfg, }, { @@ -4991,6 +5289,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = { .compatible = "qcom,sm8250-qmp-modem-pcie-phy", .data = &sm8250_qmp_gen3x2_pciephy_cfg, }, { + .compatible = "qcom,sdx55-qmp-pcie-phy", + .data = &sdx55_qmp_pciephy_cfg, + }, { .compatible = "qcom,sdx55-qmp-usb3-uni-phy", .data = &sdx55_usb3_uniphy_cfg, }, { diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h index 67bd2dd0d8c5..6592b58b13f6 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp.h @@ -6,6 +6,138 @@ #ifndef QCOM_PHY_QMP_H_ #define QCOM_PHY_QMP_H_ +/* QMP V2 PHY for PCIE gen3 ports - QSERDES PLL registers */ + +#define QSERDES_PLL_BG_TIMER 0x00c +#define QSERDES_PLL_SSC_PER1 0x01c +#define QSERDES_PLL_SSC_PER2 0x020 +#define QSERDES_PLL_SSC_STEP_SIZE1_MODE0 0x024 +#define QSERDES_PLL_SSC_STEP_SIZE2_MODE0 0x028 +#define QSERDES_PLL_SSC_STEP_SIZE1_MODE1 0x02c +#define QSERDES_PLL_SSC_STEP_SIZE2_MODE1 0x030 +#define QSERDES_PLL_BIAS_EN_CLKBUFLR_EN 0x03c +#define QSERDES_PLL_CLK_ENABLE1 0x040 +#define QSERDES_PLL_SYS_CLK_CTRL 0x044 +#define QSERDES_PLL_SYSCLK_BUF_ENABLE 0x048 +#define QSERDES_PLL_PLL_IVCO 0x050 +#define QSERDES_PLL_LOCK_CMP1_MODE0 0x054 +#define QSERDES_PLL_LOCK_CMP2_MODE0 0x058 +#define QSERDES_PLL_LOCK_CMP1_MODE1 0x060 +#define QSERDES_PLL_LOCK_CMP2_MODE1 0x064 +#define QSERDES_PLL_BG_TRIM 0x074 +#define QSERDES_PLL_CLK_EP_DIV_MODE0 0x078 +#define QSERDES_PLL_CLK_EP_DIV_MODE1 0x07c +#define QSERDES_PLL_CP_CTRL_MODE0 0x080 +#define QSERDES_PLL_CP_CTRL_MODE1 0x084 +#define QSERDES_PLL_PLL_RCTRL_MODE0 0x088 +#define QSERDES_PLL_PLL_RCTRL_MODE1 0x08C +#define QSERDES_PLL_PLL_CCTRL_MODE0 0x090 +#define QSERDES_PLL_PLL_CCTRL_MODE1 0x094 +#define QSERDES_PLL_BIAS_EN_CTRL_BY_PSM 0x0a4 +#define QSERDES_PLL_SYSCLK_EN_SEL 0x0a8 +#define QSERDES_PLL_RESETSM_CNTRL 0x0b0 +#define QSERDES_PLL_LOCK_CMP_EN 0x0c4 +#define QSERDES_PLL_DEC_START_MODE0 0x0cc +#define QSERDES_PLL_DEC_START_MODE1 0x0d0 +#define QSERDES_PLL_DIV_FRAC_START1_MODE0 0x0d8 +#define QSERDES_PLL_DIV_FRAC_START2_MODE0 0x0dc +#define QSERDES_PLL_DIV_FRAC_START3_MODE0 0x0e0 +#define QSERDES_PLL_DIV_FRAC_START1_MODE1 0x0e4 +#define QSERDES_PLL_DIV_FRAC_START2_MODE1 0x0e8 +#define QSERDES_PLL_DIV_FRAC_START3_MODE1 0x0eC +#define QSERDES_PLL_INTEGLOOP_GAIN0_MODE0 0x100 +#define QSERDES_PLL_INTEGLOOP_GAIN1_MODE0 0x104 +#define QSERDES_PLL_INTEGLOOP_GAIN0_MODE1 0x108 +#define QSERDES_PLL_INTEGLOOP_GAIN1_MODE1 0x10c +#define QSERDES_PLL_VCO_TUNE_MAP 0x120 +#define QSERDES_PLL_VCO_TUNE1_MODE0 0x124 +#define QSERDES_PLL_VCO_TUNE2_MODE0 0x128 +#define QSERDES_PLL_VCO_TUNE1_MODE1 0x12c +#define QSERDES_PLL_VCO_TUNE2_MODE1 0x130 +#define QSERDES_PLL_VCO_TUNE_TIMER1 0x13c +#define QSERDES_PLL_VCO_TUNE_TIMER2 0x140 +#define QSERDES_PLL_CLK_SELECT 0x16c +#define QSERDES_PLL_HSCLK_SEL 0x170 +#define QSERDES_PLL_CORECLK_DIV 0x17c +#define QSERDES_PLL_CORE_CLK_EN 0x184 +#define QSERDES_PLL_CMN_CONFIG 0x18c +#define QSERDES_PLL_SVS_MODE_CLK_SEL 0x194 +#define QSERDES_PLL_CORECLK_DIV_MODE1 0x1b4 + +/* QMP V2 PHY for PCIE gen3 ports - QSERDES TX registers */ + +#define QSERDES_TX0_RES_CODE_LANE_OFFSET_TX 0x03c +#define QSERDES_TX0_HIGHZ_DRVR_EN 0x058 +#define QSERDES_TX0_LANE_MODE_1 0x084 +#define QSERDES_TX0_RCV_DETECT_LVL_2 0x09c + +/* QMP V2 PHY for PCIE gen3 ports - QSERDES RX registers */ + +#define QSERDES_RX0_UCDR_FO_GAIN 0x008 +#define QSERDES_RX0_UCDR_SO_GAIN 0x014 +#define QSERDES_RX0_UCDR_SO_SATURATION_AND_ENABLE 0x034 +#define QSERDES_RX0_UCDR_PI_CONTROLS 0x044 +#define QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL2 0x0ec +#define QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL3 0x0f0 +#define QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL4 0x0f4 +#define QSERDES_RX0_RX_IDAC_TSETTLE_LOW 0x0f8 +#define QSERDES_RX0_RX_IDAC_TSETTLE_HIGH 0x0fc +#define QSERDES_RX0_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x110 +#define QSERDES_RX0_RX_OFFSET_ADAPTOR_CNTRL2 0x114 +#define QSERDES_RX0_SIGDET_ENABLES 0x118 +#define QSERDES_RX0_SIGDET_CNTRL 0x11c +#define QSERDES_RX0_SIGDET_DEGLITCH_CNTRL 0x124 +#define QSERDES_RX0_RX_MODE_00_LOW 0x170 +#define QSERDES_RX0_RX_MODE_00_HIGH 0x174 +#define QSERDES_RX0_RX_MODE_00_HIGH2 0x178 +#define QSERDES_RX0_RX_MODE_00_HIGH3 0x17c +#define QSERDES_RX0_RX_MODE_00_HIGH4 0x180 +#define QSERDES_RX0_RX_MODE_01_LOW 0x184 +#define QSERDES_RX0_RX_MODE_01_HIGH 0x188 +#define QSERDES_RX0_RX_MODE_01_HIGH2 0x18c +#define QSERDES_RX0_RX_MODE_01_HIGH3 0x190 +#define QSERDES_RX0_RX_MODE_01_HIGH4 0x194 +#define QSERDES_RX0_RX_MODE_10_LOW 0x198 +#define QSERDES_RX0_RX_MODE_10_HIGH 0x19c +#define QSERDES_RX0_RX_MODE_10_HIGH2 0x1a0 +#define QSERDES_RX0_RX_MODE_10_HIGH3 0x1a4 +#define QSERDES_RX0_RX_MODE_10_HIGH4 0x1a8 +#define QSERDES_RX0_DFE_EN_TIMER 0x1b4 + +/* QMP V2 PHY for PCIE gen3 ports - PCS registers */ + +#define PCS_COM_FLL_CNTRL1 0x098 +#define PCS_COM_FLL_CNTRL2 0x09c +#define PCS_COM_FLL_CNT_VAL_L 0x0a0 +#define PCS_COM_FLL_CNT_VAL_H_TOL 0x0a4 +#define PCS_COM_FLL_MAN_CODE 0x0a8 +#define PCS_COM_REFGEN_REQ_CONFIG1 0x0dc +#define PCS_COM_G12S1_TXDEEMPH_M3P5DB 0x16c +#define PCS_COM_RX_SIGDET_LVL 0x188 +#define PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_L 0x1a4 +#define PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_H 0x1a8 +#define PCS_COM_RX_DCC_CAL_CONFIG 0x1d8 +#define PCS_COM_EQ_CONFIG5 0x1ec + +/* QMP V2 PHY for PCIE gen3 ports - PCS Misc registers */ + +#define PCS_PCIE_POWER_STATE_CONFIG2 0x40c +#define PCS_PCIE_POWER_STATE_CONFIG4 0x414 +#define PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x41c +#define PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L 0x440 +#define PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_H 0x444 +#define PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L 0x448 +#define PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_H 0x44c +#define PCS_PCIE_OSC_DTCT_CONFIG2 0x45c +#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG2 0x478 +#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG4 0x480 +#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG5 0x484 +#define PCS_PCIE_OSC_DTCT_ACTIONS 0x490 +#define PCS_PCIE_EQ_CONFIG1 0x4a0 +#define PCS_PCIE_EQ_CONFIG2 0x4a4 +#define PCS_PCIE_PRESET_P10_PRE 0x4bc +#define PCS_PCIE_PRESET_P10_POST 0x4e0 + /* Only for QMP V2 PHY - QSERDES COM registers */ #define QSERDES_COM_BG_TIMER 0x00c #define QSERDES_COM_SSC_EN_CENTER 0x010 @@ -420,6 +552,7 @@ #define QSERDES_V4_COM_SYSCLK_EN_SEL 0x094 #define QSERDES_V4_COM_RESETSM_CNTRL 0x09c #define QSERDES_V4_COM_LOCK_CMP_EN 0x0a4 +#define QSERDES_V4_COM_LOCK_CMP_CFG 0x0a8 #define QSERDES_V4_COM_LOCK_CMP1_MODE0 0x0ac #define QSERDES_V4_COM_LOCK_CMP2_MODE0 0x0b0 #define QSERDES_V4_COM_LOCK_CMP1_MODE1 0x0b4 @@ -434,6 +567,8 @@ #define QSERDES_V4_COM_DIV_FRAC_START3_MODE1 0x0e0 #define QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0 0x0ec #define QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0 0x0f0 +#define QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE1 0x0f4 +#define QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE1 0x0f8 #define QSERDES_V4_COM_VCO_TUNE_CTRL 0x108 #define QSERDES_V4_COM_VCO_TUNE_MAP 0x10c #define QSERDES_V4_COM_VCO_TUNE1_MODE0 0x110 @@ -451,11 +586,15 @@ #define QSERDES_V4_COM_C_READY_STATUS 0x178 #define QSERDES_V4_COM_CMN_CONFIG 0x17c #define QSERDES_V4_COM_SVS_MODE_CLK_SEL 0x184 +#define QSERDES_V4_COM_CMN_MISC1 0x19c +#define QSERDES_V4_COM_INTERNAL_DIG_CORECLK_DIV 0x1a0 +#define QSERDES_V4_COM_CMN_MODE 0x1a4 +#define QSERDES_V4_COM_VCO_DC_LEVEL_CTRL 0x1a8 #define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0 0x1ac #define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0 0x1b0 #define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1 0x1b4 -#define QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL 0x1bc #define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1 0x1b8 +#define QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL 0x1bc /* Only for QMP V4 PHY - TX registers */ #define QSERDES_V4_TX_CLKBUF_ENABLE 0x08 @@ -485,6 +624,13 @@ #define QSERDES_V4_TX_VMODE_CTRL1 0xe8 #define QSERDES_V4_TX_PI_QEC_CTRL 0x104 +/* Only for QMP V4_20 PHY - TX registers */ +#define QSERDES_V4_20_TX_LANE_MODE_1 0x88 +#define QSERDES_V4_20_TX_LANE_MODE_2 0x8c +#define QSERDES_V4_20_TX_LANE_MODE_3 0x90 +#define QSERDES_V4_20_TX_VMODE_CTRL1 0xc4 +#define QSERDES_V4_20_TX_PI_QEC_CTRL 0xe0 + /* Only for QMP V4 PHY - RX registers */ #define QSERDES_V4_RX_UCDR_FO_GAIN 0x008 #define QSERDES_V4_RX_UCDR_SO_GAIN 0x014 @@ -551,6 +697,33 @@ #define QSERDES_V4_DP_PHY_AUX_INTERRUPT_STATUS 0x0d8 #define QSERDES_V4_DP_PHY_STATUS 0x0dc +/* Only for QMP V4_20 PHY - RX registers */ +#define QSERDES_V4_20_RX_FO_GAIN_RATE2 0x008 +#define QSERDES_V4_20_RX_UCDR_PI_CONTROLS 0x058 +#define QSERDES_V4_20_RX_AUX_DATA_TCOARSE_TFINE 0x0ac +#define QSERDES_V4_20_RX_DFE_3 0x110 +#define QSERDES_V4_20_RX_DFE_DAC_ENABLE1 0x134 +#define QSERDES_V4_20_RX_DFE_DAC_ENABLE2 0x138 +#define QSERDES_V4_20_RX_VGA_CAL_CNTRL2 0x150 +#define QSERDES_V4_20_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x178 +#define QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B1 0x1c8 +#define QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B2 0x1cc +#define QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B3 0x1d0 +#define QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B4 0x1d4 +#define QSERDES_V4_20_RX_RX_MODE_RATE2_B0 0x1d8 +#define QSERDES_V4_20_RX_RX_MODE_RATE2_B1 0x1dc +#define QSERDES_V4_20_RX_RX_MODE_RATE2_B2 0x1e0 +#define QSERDES_V4_20_RX_RX_MODE_RATE2_B3 0x1e4 +#define QSERDES_V4_20_RX_RX_MODE_RATE2_B4 0x1e8 +#define QSERDES_V4_20_RX_RX_MODE_RATE3_B0 0x1ec +#define QSERDES_V4_20_RX_RX_MODE_RATE3_B1 0x1f0 +#define QSERDES_V4_20_RX_RX_MODE_RATE3_B2 0x1f4 +#define QSERDES_V4_20_RX_RX_MODE_RATE3_B3 0x1f8 +#define QSERDES_V4_20_RX_RX_MODE_RATE3_B4 0x1fc +#define QSERDES_V4_20_RX_PHPRE_CTRL 0x200 +#define QSERDES_V4_20_RX_DFE_CTLE_POST_CAL_OFFSET 0x20c +#define QSERDES_V4_20_RX_MARG_COARSE_CTRL2 0x23c + /* Only for QMP V4 PHY - UFS PCS registers */ #define QPHY_V4_PCS_UFS_PHY_START 0x000 #define QPHY_V4_PCS_UFS_POWER_DOWN_CONTROL 0x004 @@ -836,6 +1009,12 @@ #define QPHY_V4_PCS_USB3_SIGDET_STARTUP_TIMER_VAL 0x354 #define QPHY_V4_PCS_USB3_TEST_CONTROL 0x358 +/* Only for QMP V4_20 PHY - USB/PCIe PCS registers */ +#define QPHY_V4_20_PCS_RX_SIGDET_LVL 0x188 +#define QPHY_V4_20_PCS_EQ_CONFIG2 0x1d8 +#define QPHY_V4_20_PCS_EQ_CONFIG4 0x1e0 +#define QPHY_V4_20_PCS_EQ_CONFIG5 0x1e4 + /* Only for QMP V4 PHY - UNI has 0x300 offset for PCS_USB3 regs */ #define QPHY_V4_PCS_USB3_UNI_LFPS_DET_HIGH_COUNT_VAL 0x618 #define QPHY_V4_PCS_USB3_UNI_RXEQTRAINING_DFE_TIME_S2 0x638 @@ -861,6 +1040,14 @@ #define QPHY_V4_PCS_PCIE_PRESET_P10_PRE 0xbc #define QPHY_V4_PCS_PCIE_PRESET_P10_POST 0xe0 +#define QPHY_V4_20_PCS_PCIE_EQ_CONFIG1 0x0a0 +#define QPHY_V4_20_PCS_PCIE_G3_RXEQEVAL_TIME 0x0f0 +#define QPHY_V4_20_PCS_PCIE_G4_RXEQEVAL_TIME 0x0f4 +#define QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG2 0x0fc +#define QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG5 0x108 +#define QPHY_V4_20_PCS_LANE1_INSIG_SW_CTRL2 0x824 +#define QPHY_V4_20_PCS_LANE1_INSIG_MX_CTRL2 0x828 + /* Only for QMP V5 PHY - QSERDES COM registers */ #define QSERDES_V5_COM_PLL_IVCO 0x058 #define QSERDES_V5_COM_CP_CTRL_MODE0 0x074 diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c index 8f1bf7e2186b..3c1d3b71c825 100644 --- a/drivers/phy/qualcomm/phy-qcom-qusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c @@ -219,6 +219,22 @@ static const struct qusb2_phy_init_tbl msm8998_init_tbl[] = { QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_DIGITAL_TIMERS_TWO, 0x19), }; +static const struct qusb2_phy_init_tbl sm6115_init_tbl[] = { + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE1, 0xf8), + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE2, 0x53), + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE3, 0x81), + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE4, 0x17), + + QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_TUNE, 0x30), + QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL1, 0x79), + QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL2, 0x21), + + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TEST2, 0x14), + + QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_AUTOPGM_CTL1, 0x9f), + QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00), +}; + static const unsigned int qusb2_v2_regs_layout[] = { [QUSB2PHY_PLL_CORE_INPUT_OVERRIDE] = 0xa8, [QUSB2PHY_PLL_STATUS] = 0x1a0, @@ -342,6 +358,18 @@ static const struct qusb2_phy_cfg sdm660_phy_cfg = { .autoresume_en = BIT(3), }; +static const struct qusb2_phy_cfg sm6115_phy_cfg = { + .tbl = sm6115_init_tbl, + .tbl_num = ARRAY_SIZE(sm6115_init_tbl), + .regs = msm8996_regs_layout, + + .has_pll_test = true, + .se_clk_scheme_default = true, + .disable_ctrl = (CLAMP_N_EN | FREEZIO_N | POWER_DOWN), + .mask_core_ready = PLL_LOCKED, + .autoresume_en = BIT(3), +}; + static const char * const qusb2_phy_vreg_names[] = { "vdda-pll", "vdda-phy-dpdm", }; @@ -889,6 +917,12 @@ static const struct of_device_id qusb2_phy_of_match_table[] = { .compatible = "qcom,sdm660-qusb2-phy", .data = &sdm660_phy_cfg, }, { + .compatible = "qcom,sm4250-qusb2-phy", + .data = &sm6115_phy_cfg, + }, { + .compatible = "qcom,sm6115-qusb2-phy", + .data = &sm6115_phy_cfg, + }, { /* * Deprecated. Only here to support legacy device * trees that didn't include "qcom,qusb2-v2-phy" diff --git a/drivers/phy/ralink/Kconfig b/drivers/phy/ralink/Kconfig index ecc309ba9fee..c2373b30b8a6 100644 --- a/drivers/phy/ralink/Kconfig +++ b/drivers/phy/ralink/Kconfig @@ -4,7 +4,7 @@ # config PHY_MT7621_PCI tristate "MediaTek MT7621 PCI PHY Driver" - depends on RALINK && OF + depends on (RALINK && OF) || COMPILE_TEST select GENERIC_PHY select REGMAP_MMIO help diff --git a/drivers/phy/ralink/phy-mt7621-pci.c b/drivers/phy/ralink/phy-mt7621-pci.c index 2a9465f4bb3a..5e6530f545b5 100644 --- a/drivers/phy/ralink/phy-mt7621-pci.c +++ b/drivers/phy/ralink/phy-mt7621-pci.c @@ -5,6 +5,7 @@ */ #include <dt-bindings/phy/phy.h> +#include <linux/clk.h> #include <linux/bitfield.h> #include <linux/bitops.h> #include <linux/module.h> @@ -14,8 +15,6 @@ #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/sys_soc.h> -#include <mt7621.h> -#include <ralink_regs.h> #define RG_PE1_PIPE_REG 0x02c #define RG_PE1_PIPE_RST BIT(12) @@ -62,8 +61,6 @@ #define RG_PE1_FRC_MSTCKDIV BIT(5) -#define XTAL_MASK GENMASK(8, 6) - #define MAX_PHYS 2 /** @@ -71,6 +68,7 @@ * @dev: pointer to device * @regmap: kernel regmap pointer * @phy: pointer to the kernel PHY device + * @sys_clk: pointer to the system XTAL clock * @port_base: base register * @has_dual_port: if the phy has dual ports. * @bypass_pipe_rst: mark if 'mt7621_bypass_pipe_rst' @@ -80,6 +78,7 @@ struct mt7621_pci_phy { struct device *dev; struct regmap *regmap; struct phy *phy; + struct clk *sys_clk; void __iomem *port_base; bool has_dual_port; bool bypass_pipe_rst; @@ -116,12 +115,14 @@ static void mt7621_bypass_pipe_rst(struct mt7621_pci_phy *phy) } } -static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy) +static int mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy) { struct device *dev = phy->dev; - u32 xtal_mode; + unsigned long clk_rate; - xtal_mode = FIELD_GET(XTAL_MASK, rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0)); + clk_rate = clk_get_rate(phy->sys_clk); + if (!clk_rate) + return -EINVAL; /* Set PCIe Port PHY to disable SSC */ /* Debug Xtal Type */ @@ -139,13 +140,13 @@ static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy) RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN); } - if (xtal_mode <= 5 && xtal_mode >= 3) { /* 40MHz Xtal */ + if (clk_rate == 40000000) { /* 40MHz Xtal */ /* Set Pre-divider ratio (for host mode) */ mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG, RG_PE1_H_PLL_PREDIV, FIELD_PREP(RG_PE1_H_PLL_PREDIV, 0x01)); dev_dbg(dev, "Xtal is 40MHz\n"); - } else if (xtal_mode >= 6) { /* 25MHz Xal */ + } else if (clk_rate == 25000000) { /* 25MHz Xal */ mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG, RG_PE1_H_PLL_PREDIV, FIELD_PREP(RG_PE1_H_PLL_PREDIV, 0x00)); @@ -196,13 +197,15 @@ static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy) mt7621_phy_rmw(phy, RG_PE1_H_PLL_BR_REG, RG_PE1_H_PLL_BR, FIELD_PREP(RG_PE1_H_PLL_BR, 0x00)); - if (xtal_mode <= 5 && xtal_mode >= 3) { /* 40MHz Xtal */ + if (clk_rate == 40000000) { /* 40MHz Xtal */ /* set force mode enable of da_pe1_mstckdiv */ mt7621_phy_rmw(phy, RG_PE1_MSTCKDIV_REG, RG_PE1_MSTCKDIV | RG_PE1_FRC_MSTCKDIV, FIELD_PREP(RG_PE1_MSTCKDIV, 0x01) | RG_PE1_FRC_MSTCKDIV); } + + return 0; } static int mt7621_pci_phy_init(struct phy *phy) @@ -212,9 +215,7 @@ static int mt7621_pci_phy_init(struct phy *phy) if (mphy->bypass_pipe_rst) mt7621_bypass_pipe_rst(mphy); - mt7621_set_phy_for_ssc(mphy); - - return 0; + return mt7621_set_phy_for_ssc(mphy); } static int mt7621_pci_phy_power_on(struct phy *phy) @@ -272,8 +273,8 @@ static struct phy *mt7621_pcie_phy_of_xlate(struct device *dev, mt7621_phy->has_dual_port = args->args[0]; - dev_info(dev, "PHY for 0x%08x (dual port = %d)\n", - (unsigned int)mt7621_phy->port_base, mt7621_phy->has_dual_port); + dev_dbg(dev, "PHY for 0x%px (dual port = %d)\n", + mt7621_phy->port_base, mt7621_phy->has_dual_port); return mt7621_phy->phy; } @@ -324,6 +325,12 @@ static int mt7621_pci_phy_probe(struct platform_device *pdev) return PTR_ERR(phy->phy); } + phy->sys_clk = devm_clk_get(dev, NULL); + if (IS_ERR(phy->sys_clk)) { + dev_err(dev, "failed to get phy clock\n"); + return PTR_ERR(phy->sys_clk); + } + phy_set_drvdata(phy->phy, phy); provider = devm_of_phy_provider_register(dev, mt7621_pcie_phy_of_xlate); diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig index 159285f42e5c..e812adad7242 100644 --- a/drivers/phy/rockchip/Kconfig +++ b/drivers/phy/rockchip/Kconfig @@ -48,6 +48,15 @@ config PHY_ROCKCHIP_INNO_USB2 help Support for Rockchip USB2.0 PHY with Innosilicon IP block. +config PHY_ROCKCHIP_INNO_CSIDPHY + tristate "Rockchip Innosilicon MIPI CSI PHY driver" + depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF + select GENERIC_PHY + select GENERIC_PHY_MIPI_DPHY + help + Enable this to support the Rockchip MIPI CSI PHY with + Innosilicon IP block. + config PHY_ROCKCHIP_INNO_DSIDPHY tristate "Rockchip Innosilicon MIPI/LVDS/TTL PHY driver" depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile index c3cfc7f0af5c..f0eec212b2aa 100644 --- a/drivers/phy/rockchip/Makefile +++ b/drivers/phy/rockchip/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_PHY_ROCKCHIP_DP) += phy-rockchip-dp.o obj-$(CONFIG_PHY_ROCKCHIP_DPHY_RX0) += phy-rockchip-dphy-rx0.o obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o +obj-$(CONFIG_PHY_ROCKCHIP_INNO_CSIDPHY) += phy-rockchip-inno-csidphy.o obj-$(CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY) += phy-rockchip-inno-dsidphy.o obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI) += phy-rockchip-inno-hdmi.o obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o diff --git a/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c b/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c new file mode 100644 index 000000000000..ca13a604ab4f --- /dev/null +++ b/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c @@ -0,0 +1,459 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Rockchip MIPI RX Innosilicon DPHY driver + * + * Copyright (C) 2021 Fuzhou Rockchip Electronics Co., Ltd. + */ + +#include <linux/bitfield.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/phy/phy.h> +#include <linux/phy/phy-mipi-dphy.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/reset.h> + +/* GRF */ +#define RK1808_GRF_PD_VI_CON_OFFSET 0x0430 + +#define RK3326_GRF_PD_VI_CON_OFFSET 0x0430 + +#define RK3368_GRF_SOC_CON6_OFFSET 0x0418 + +/* PHY */ +#define CSIDPHY_CTRL_LANE_ENABLE 0x00 +#define CSIDPHY_CTRL_LANE_ENABLE_CK BIT(6) +#define CSIDPHY_CTRL_LANE_ENABLE_MASK GENMASK(5, 2) +#define CSIDPHY_CTRL_LANE_ENABLE_UNDEFINED BIT(0) + +/* not present on all variants */ +#define CSIDPHY_CTRL_PWRCTL 0x04 +#define CSIDPHY_CTRL_PWRCTL_UNDEFINED GENMASK(7, 5) +#define CSIDPHY_CTRL_PWRCTL_SYNCRST BIT(2) +#define CSIDPHY_CTRL_PWRCTL_LDO_PD BIT(1) +#define CSIDPHY_CTRL_PWRCTL_PLL_PD BIT(0) + +#define CSIDPHY_CTRL_DIG_RST 0x80 +#define CSIDPHY_CTRL_DIG_RST_UNDEFINED 0x1e +#define CSIDPHY_CTRL_DIG_RST_RESET BIT(0) + +/* offset after ths_settle_offset */ +#define CSIDPHY_CLK_THS_SETTLE 0 +#define CSIDPHY_LANE_THS_SETTLE(n) (((n) + 1) * 0x80) +#define CSIDPHY_THS_SETTLE_MASK GENMASK(6, 0) + +/* offset after calib_offset */ +#define CSIDPHY_CLK_CALIB_EN 0 +#define CSIDPHY_LANE_CALIB_EN(n) (((n) + 1) * 0x80) +#define CSIDPHY_CALIB_EN BIT(7) + +/* Configure the count time of the THS-SETTLE by protocol. */ +#define RK1808_CSIDPHY_CLK_WR_THS_SETTLE 0x160 +#define RK3326_CSIDPHY_CLK_WR_THS_SETTLE 0x100 +#define RK3368_CSIDPHY_CLK_WR_THS_SETTLE 0x100 + +/* Calibration reception enable */ +#define RK1808_CSIDPHY_CLK_CALIB_EN 0x168 + +/* + * The higher 16-bit of this register is used for write protection + * only if BIT(x + 16) set to 1 the BIT(x) can be written. + */ +#define HIWORD_UPDATE(val, mask, shift) \ + ((val) << (shift) | (mask) << ((shift) + 16)) + +#define HZ_TO_MHZ(freq) div_u64(freq, 1000 * 1000) + +enum dphy_reg_id { + /* rk1808 & rk3326 */ + GRF_DPHY_CSIPHY_FORCERXMODE, + GRF_DPHY_CSIPHY_CLKLANE_EN, + GRF_DPHY_CSIPHY_DATALANE_EN, +}; + +struct dphy_reg { + u32 offset; + u32 mask; + u32 shift; +}; + +#define PHY_REG(_offset, _width, _shift) \ + { .offset = _offset, .mask = BIT(_width) - 1, .shift = _shift, } + +static const struct dphy_reg rk1808_grf_dphy_regs[] = { + [GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK1808_GRF_PD_VI_CON_OFFSET, 4, 0), + [GRF_DPHY_CSIPHY_CLKLANE_EN] = PHY_REG(RK1808_GRF_PD_VI_CON_OFFSET, 1, 8), + [GRF_DPHY_CSIPHY_DATALANE_EN] = PHY_REG(RK1808_GRF_PD_VI_CON_OFFSET, 4, 4), +}; + +static const struct dphy_reg rk3326_grf_dphy_regs[] = { + [GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK3326_GRF_PD_VI_CON_OFFSET, 4, 0), + [GRF_DPHY_CSIPHY_CLKLANE_EN] = PHY_REG(RK3326_GRF_PD_VI_CON_OFFSET, 1, 8), + [GRF_DPHY_CSIPHY_DATALANE_EN] = PHY_REG(RK3326_GRF_PD_VI_CON_OFFSET, 4, 4), +}; + +static const struct dphy_reg rk3368_grf_dphy_regs[] = { + [GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK3368_GRF_SOC_CON6_OFFSET, 4, 8), +}; + +struct hsfreq_range { + u32 range_h; + u8 cfg_bit; +}; + +struct dphy_drv_data { + int pwrctl_offset; + int ths_settle_offset; + int calib_offset; + const struct hsfreq_range *hsfreq_ranges; + int num_hsfreq_ranges; + const struct dphy_reg *grf_regs; +}; + +struct rockchip_inno_csidphy { + struct device *dev; + void __iomem *phy_base; + struct clk *pclk; + struct regmap *grf; + struct reset_control *rst; + const struct dphy_drv_data *drv_data; + struct phy_configure_opts_mipi_dphy config; + u8 hsfreq; +}; + +static inline void write_grf_reg(struct rockchip_inno_csidphy *priv, + int index, u8 value) +{ + const struct dphy_drv_data *drv_data = priv->drv_data; + const struct dphy_reg *reg = &drv_data->grf_regs[index]; + + if (reg->offset) + regmap_write(priv->grf, reg->offset, + HIWORD_UPDATE(value, reg->mask, reg->shift)); +} + +/* These tables must be sorted by .range_h ascending. */ +static const struct hsfreq_range rk1808_mipidphy_hsfreq_ranges[] = { + { 109, 0x02}, { 149, 0x03}, { 199, 0x06}, { 249, 0x06}, + { 299, 0x06}, { 399, 0x08}, { 499, 0x0b}, { 599, 0x0e}, + { 699, 0x10}, { 799, 0x12}, { 999, 0x16}, {1199, 0x1e}, + {1399, 0x23}, {1599, 0x2d}, {1799, 0x32}, {1999, 0x37}, + {2199, 0x3c}, {2399, 0x41}, {2499, 0x46} +}; + +static const struct hsfreq_range rk3326_mipidphy_hsfreq_ranges[] = { + { 109, 0x00}, { 149, 0x01}, { 199, 0x02}, { 249, 0x03}, + { 299, 0x04}, { 399, 0x05}, { 499, 0x06}, { 599, 0x07}, + { 699, 0x08}, { 799, 0x09}, { 899, 0x0a}, {1099, 0x0b}, + {1249, 0x0c}, {1349, 0x0d}, {1500, 0x0e} +}; + +static const struct hsfreq_range rk3368_mipidphy_hsfreq_ranges[] = { + { 109, 0x00}, { 149, 0x01}, { 199, 0x02}, { 249, 0x03}, + { 299, 0x04}, { 399, 0x05}, { 499, 0x06}, { 599, 0x07}, + { 699, 0x08}, { 799, 0x09}, { 899, 0x0a}, {1099, 0x0b}, + {1249, 0x0c}, {1349, 0x0d}, {1500, 0x0e} +}; + +static void rockchip_inno_csidphy_ths_settle(struct rockchip_inno_csidphy *priv, + int hsfreq, int offset) +{ + const struct dphy_drv_data *drv_data = priv->drv_data; + u32 val; + + val = readl(priv->phy_base + drv_data->ths_settle_offset + offset); + val &= ~CSIDPHY_THS_SETTLE_MASK; + val |= hsfreq; + writel(val, priv->phy_base + drv_data->ths_settle_offset + offset); +} + +static int rockchip_inno_csidphy_configure(struct phy *phy, + union phy_configure_opts *opts) +{ + struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy); + const struct dphy_drv_data *drv_data = priv->drv_data; + struct phy_configure_opts_mipi_dphy *config = &opts->mipi_dphy; + unsigned int hsfreq = 0; + unsigned int i; + u64 data_rate_mbps; + int ret; + + /* pass with phy_mipi_dphy_get_default_config (with pixel rate?) */ + ret = phy_mipi_dphy_config_validate(config); + if (ret) + return ret; + + data_rate_mbps = HZ_TO_MHZ(config->hs_clk_rate); + + dev_dbg(priv->dev, "lanes %d - data_rate_mbps %llu\n", + config->lanes, data_rate_mbps); + for (i = 0; i < drv_data->num_hsfreq_ranges; i++) { + if (drv_data->hsfreq_ranges[i].range_h >= data_rate_mbps) { + hsfreq = drv_data->hsfreq_ranges[i].cfg_bit; + break; + } + } + if (!hsfreq) + return -EINVAL; + + priv->hsfreq = hsfreq; + priv->config = *config; + return 0; +} + +static int rockchip_inno_csidphy_power_on(struct phy *phy) +{ + struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy); + const struct dphy_drv_data *drv_data = priv->drv_data; + u64 data_rate_mbps = HZ_TO_MHZ(priv->config.hs_clk_rate); + u32 val; + int ret, i; + + ret = clk_enable(priv->pclk); + if (ret < 0) + return ret; + + ret = pm_runtime_resume_and_get(priv->dev); + if (ret < 0) { + clk_disable(priv->pclk); + return ret; + } + + /* phy start */ + if (drv_data->pwrctl_offset >= 0) + writel(CSIDPHY_CTRL_PWRCTL_UNDEFINED | + CSIDPHY_CTRL_PWRCTL_SYNCRST, + priv->phy_base + drv_data->pwrctl_offset); + + /* set data lane num and enable clock lane */ + val = FIELD_PREP(CSIDPHY_CTRL_LANE_ENABLE_MASK, GENMASK(priv->config.lanes - 1, 0)) | + FIELD_PREP(CSIDPHY_CTRL_LANE_ENABLE_CK, 1) | + FIELD_PREP(CSIDPHY_CTRL_LANE_ENABLE_UNDEFINED, 1); + writel(val, priv->phy_base + CSIDPHY_CTRL_LANE_ENABLE); + + /* Reset dphy analog part */ + if (drv_data->pwrctl_offset >= 0) + writel(CSIDPHY_CTRL_PWRCTL_UNDEFINED, + priv->phy_base + drv_data->pwrctl_offset); + usleep_range(500, 1000); + + /* Reset dphy digital part */ + writel(CSIDPHY_CTRL_DIG_RST_UNDEFINED, + priv->phy_base + CSIDPHY_CTRL_DIG_RST); + writel(CSIDPHY_CTRL_DIG_RST_UNDEFINED + CSIDPHY_CTRL_DIG_RST_RESET, + priv->phy_base + CSIDPHY_CTRL_DIG_RST); + + /* not into receive mode/wait stopstate */ + write_grf_reg(priv, GRF_DPHY_CSIPHY_FORCERXMODE, 0x0); + + /* enable calibration */ + if (data_rate_mbps > 1500 && drv_data->calib_offset >= 0) { + writel(CSIDPHY_CALIB_EN, + priv->phy_base + drv_data->calib_offset + + CSIDPHY_CLK_CALIB_EN); + for (i = 0; i < priv->config.lanes; i++) + writel(CSIDPHY_CALIB_EN, + priv->phy_base + drv_data->calib_offset + + CSIDPHY_LANE_CALIB_EN(i)); + } + + rockchip_inno_csidphy_ths_settle(priv, priv->hsfreq, + CSIDPHY_CLK_THS_SETTLE); + for (i = 0; i < priv->config.lanes; i++) + rockchip_inno_csidphy_ths_settle(priv, priv->hsfreq, + CSIDPHY_LANE_THS_SETTLE(i)); + + write_grf_reg(priv, GRF_DPHY_CSIPHY_CLKLANE_EN, 0x1); + write_grf_reg(priv, GRF_DPHY_CSIPHY_DATALANE_EN, + GENMASK(priv->config.lanes - 1, 0)); + + return 0; +} + +static int rockchip_inno_csidphy_power_off(struct phy *phy) +{ + struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy); + const struct dphy_drv_data *drv_data = priv->drv_data; + + /* disable all lanes */ + writel(CSIDPHY_CTRL_LANE_ENABLE_UNDEFINED, + priv->phy_base + CSIDPHY_CTRL_LANE_ENABLE); + + /* disable pll and ldo */ + if (drv_data->pwrctl_offset >= 0) + writel(CSIDPHY_CTRL_PWRCTL_UNDEFINED | + CSIDPHY_CTRL_PWRCTL_LDO_PD | + CSIDPHY_CTRL_PWRCTL_PLL_PD, + priv->phy_base + drv_data->pwrctl_offset); + usleep_range(500, 1000); + + pm_runtime_put(priv->dev); + clk_disable(priv->pclk); + + return 0; +} + +static int rockchip_inno_csidphy_init(struct phy *phy) +{ + struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy); + + return clk_prepare(priv->pclk); +} + +static int rockchip_inno_csidphy_exit(struct phy *phy) +{ + struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy); + + clk_unprepare(priv->pclk); + + return 0; +} + +static const struct phy_ops rockchip_inno_csidphy_ops = { + .power_on = rockchip_inno_csidphy_power_on, + .power_off = rockchip_inno_csidphy_power_off, + .init = rockchip_inno_csidphy_init, + .exit = rockchip_inno_csidphy_exit, + .configure = rockchip_inno_csidphy_configure, + .owner = THIS_MODULE, +}; + +static const struct dphy_drv_data rk1808_mipidphy_drv_data = { + .pwrctl_offset = -1, + .ths_settle_offset = RK1808_CSIDPHY_CLK_WR_THS_SETTLE, + .calib_offset = RK1808_CSIDPHY_CLK_CALIB_EN, + .hsfreq_ranges = rk1808_mipidphy_hsfreq_ranges, + .num_hsfreq_ranges = ARRAY_SIZE(rk1808_mipidphy_hsfreq_ranges), + .grf_regs = rk1808_grf_dphy_regs, +}; + +static const struct dphy_drv_data rk3326_mipidphy_drv_data = { + .pwrctl_offset = CSIDPHY_CTRL_PWRCTL, + .ths_settle_offset = RK3326_CSIDPHY_CLK_WR_THS_SETTLE, + .calib_offset = -1, + .hsfreq_ranges = rk3326_mipidphy_hsfreq_ranges, + .num_hsfreq_ranges = ARRAY_SIZE(rk3326_mipidphy_hsfreq_ranges), + .grf_regs = rk3326_grf_dphy_regs, +}; + +static const struct dphy_drv_data rk3368_mipidphy_drv_data = { + .pwrctl_offset = CSIDPHY_CTRL_PWRCTL, + .ths_settle_offset = RK3368_CSIDPHY_CLK_WR_THS_SETTLE, + .calib_offset = -1, + .hsfreq_ranges = rk3368_mipidphy_hsfreq_ranges, + .num_hsfreq_ranges = ARRAY_SIZE(rk3368_mipidphy_hsfreq_ranges), + .grf_regs = rk3368_grf_dphy_regs, +}; + +static const struct of_device_id rockchip_inno_csidphy_match_id[] = { + { + .compatible = "rockchip,px30-csi-dphy", + .data = &rk3326_mipidphy_drv_data, + }, + { + .compatible = "rockchip,rk1808-csi-dphy", + .data = &rk1808_mipidphy_drv_data, + }, + { + .compatible = "rockchip,rk3326-csi-dphy", + .data = &rk3326_mipidphy_drv_data, + }, + { + .compatible = "rockchip,rk3368-csi-dphy", + .data = &rk3368_mipidphy_drv_data, + }, + {} +}; +MODULE_DEVICE_TABLE(of, rockchip_inno_csidphy_match_id); + +static int rockchip_inno_csidphy_probe(struct platform_device *pdev) +{ + struct rockchip_inno_csidphy *priv; + struct device *dev = &pdev->dev; + struct phy_provider *phy_provider; + struct phy *phy; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + platform_set_drvdata(pdev, priv); + + priv->drv_data = of_device_get_match_data(dev); + if (!priv->drv_data) { + dev_err(dev, "Can't find device data\n"); + return -ENODEV; + } + + priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node, + "rockchip,grf"); + if (IS_ERR(priv->grf)) { + dev_err(dev, "Can't find GRF syscon\n"); + return PTR_ERR(priv->grf); + } + + priv->phy_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->phy_base)) + return PTR_ERR(priv->phy_base); + + priv->pclk = devm_clk_get(dev, "pclk"); + if (IS_ERR(priv->pclk)) { + dev_err(dev, "failed to get pclk\n"); + return PTR_ERR(priv->pclk); + } + + priv->rst = devm_reset_control_get(dev, "apb"); + if (IS_ERR(priv->rst)) { + dev_err(dev, "failed to get system reset control\n"); + return PTR_ERR(priv->rst); + } + + phy = devm_phy_create(dev, NULL, &rockchip_inno_csidphy_ops); + if (IS_ERR(phy)) { + dev_err(dev, "failed to create phy\n"); + return PTR_ERR(phy); + } + + phy_set_drvdata(phy, priv); + + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (IS_ERR(phy_provider)) { + dev_err(dev, "failed to register phy provider\n"); + return PTR_ERR(phy_provider); + } + + pm_runtime_enable(dev); + + return 0; +} + +static int rockchip_inno_csidphy_remove(struct platform_device *pdev) +{ + struct rockchip_inno_csidphy *priv = platform_get_drvdata(pdev); + + pm_runtime_disable(priv->dev); + + return 0; +} + +static struct platform_driver rockchip_inno_csidphy_driver = { + .driver = { + .name = "rockchip-inno-csidphy", + .of_match_table = rockchip_inno_csidphy_match_id, + }, + .probe = rockchip_inno_csidphy_probe, + .remove = rockchip_inno_csidphy_remove, +}; + +module_platform_driver(rockchip_inno_csidphy_driver); +MODULE_AUTHOR("Heiko Stuebner <heiko.stuebner@theobroma-systems.com>"); +MODULE_DESCRIPTION("Rockchip MIPI Innosilicon CSI-DPHY driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c index a37f3f342642..80acca4e9e14 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c @@ -620,7 +620,7 @@ static int inno_hdmi_phy_rk3228_clk_set_rate(struct clk_hw *hw, unsigned long parent_rate) { struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); - const struct pre_pll_config *cfg = pre_pll_cfg_table; + const struct pre_pll_config *cfg; unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate); u32 v; int ret; @@ -774,7 +774,7 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw, unsigned long parent_rate) { struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); - const struct pre_pll_config *cfg = pre_pll_cfg_table; + const struct pre_pll_config *cfg; unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate); u32 val; int ret; diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index 46ebdb1460a3..beacac1dd253 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -1256,6 +1256,49 @@ static const struct rockchip_usb2phy_cfg rk3228_phy_cfgs[] = { { /* sentinel */ } }; +static const struct rockchip_usb2phy_cfg rk3308_phy_cfgs[] = { + { + .reg = 0x100, + .num_ports = 2, + .clkout_ctl = { 0x108, 4, 4, 1, 0 }, + .port_cfgs = { + [USB2PHY_PORT_OTG] = { + .phy_sus = { 0x0100, 8, 0, 0, 0x1d1 }, + .bvalid_det_en = { 0x3020, 2, 2, 0, 1 }, + .bvalid_det_st = { 0x3024, 2, 2, 0, 1 }, + .bvalid_det_clr = { 0x3028, 2, 2, 0, 1 }, + .ls_det_en = { 0x3020, 0, 0, 0, 1 }, + .ls_det_st = { 0x3024, 0, 0, 0, 1 }, + .ls_det_clr = { 0x3028, 0, 0, 0, 1 }, + .utmi_avalid = { 0x0120, 10, 10, 0, 1 }, + .utmi_bvalid = { 0x0120, 9, 9, 0, 1 }, + .utmi_ls = { 0x0120, 5, 4, 0, 1 }, + }, + [USB2PHY_PORT_HOST] = { + .phy_sus = { 0x0104, 8, 0, 0, 0x1d1 }, + .ls_det_en = { 0x3020, 1, 1, 0, 1 }, + .ls_det_st = { 0x3024, 1, 1, 0, 1 }, + .ls_det_clr = { 0x3028, 1, 1, 0, 1 }, + .utmi_ls = { 0x0120, 17, 16, 0, 1 }, + .utmi_hstdet = { 0x0120, 19, 19, 0, 1 } + } + }, + .chg_det = { + .opmode = { 0x0100, 3, 0, 5, 1 }, + .cp_det = { 0x0120, 24, 24, 0, 1 }, + .dcp_det = { 0x0120, 23, 23, 0, 1 }, + .dp_det = { 0x0120, 25, 25, 0, 1 }, + .idm_sink_en = { 0x0108, 8, 8, 0, 1 }, + .idp_sink_en = { 0x0108, 7, 7, 0, 1 }, + .idp_src_en = { 0x0108, 9, 9, 0, 1 }, + .rdm_pdwn_en = { 0x0108, 10, 10, 0, 1 }, + .vdm_src_en = { 0x0108, 12, 12, 0, 1 }, + .vdp_src_en = { 0x0108, 11, 11, 0, 1 }, + }, + }, + { /* sentinel */ } +}; + static const struct rockchip_usb2phy_cfg rk3328_phy_cfgs[] = { { .reg = 0x100, @@ -1425,6 +1468,7 @@ static const struct rockchip_usb2phy_cfg rv1108_phy_cfgs[] = { static const struct of_device_id rockchip_usb2phy_dt_match[] = { { .compatible = "rockchip,px30-usb2phy", .data = &rk3328_phy_cfgs }, { .compatible = "rockchip,rk3228-usb2phy", .data = &rk3228_phy_cfgs }, + { .compatible = "rockchip,rk3308-usb2phy", .data = &rk3308_phy_cfgs }, { .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs }, { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs }, { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs }, diff --git a/drivers/phy/socionext/phy-uniphier-pcie.c b/drivers/phy/socionext/phy-uniphier-pcie.c index e4adab375c73..6bdbd1f214dd 100644 --- a/drivers/phy/socionext/phy-uniphier-pcie.c +++ b/drivers/phy/socionext/phy-uniphier-pcie.c @@ -24,11 +24,13 @@ #define PORT_SEL_1 FIELD_PREP(PORT_SEL_MASK, 1) #define PCL_PHY_TEST_I 0x2000 -#define PCL_PHY_TEST_O 0x2004 #define TESTI_DAT_MASK GENMASK(13, 6) #define TESTI_ADR_MASK GENMASK(5, 1) #define TESTI_WR_EN BIT(0) +#define PCL_PHY_TEST_O 0x2004 +#define TESTO_DAT_MASK GENMASK(7, 0) + #define PCL_PHY_RESET 0x200c #define PCL_PHY_RESET_N_MNMODE BIT(8) /* =1:manual */ #define PCL_PHY_RESET_N BIT(0) /* =1:deasssert */ @@ -77,11 +79,12 @@ static void uniphier_pciephy_set_param(struct uniphier_pciephy_priv *priv, val = FIELD_PREP(TESTI_DAT_MASK, 1); val |= FIELD_PREP(TESTI_ADR_MASK, reg); uniphier_pciephy_testio_write(priv, val); - val = readl(priv->base + PCL_PHY_TEST_O); + val = readl(priv->base + PCL_PHY_TEST_O) & TESTO_DAT_MASK; /* update value */ - val &= ~FIELD_PREP(TESTI_DAT_MASK, mask); - val = FIELD_PREP(TESTI_DAT_MASK, mask & param); + val &= ~mask; + val |= mask & param; + val = FIELD_PREP(TESTI_DAT_MASK, val); val |= FIELD_PREP(TESTI_ADR_MASK, reg); uniphier_pciephy_testio_write(priv, val); uniphier_pciephy_testio_write(priv, val | TESTI_WR_EN); diff --git a/drivers/phy/st/phy-stm32-usbphyc.c b/drivers/phy/st/phy-stm32-usbphyc.c index c184f4e34584..3e491dfb2525 100644 --- a/drivers/phy/st/phy-stm32-usbphyc.c +++ b/drivers/phy/st/phy-stm32-usbphyc.c @@ -57,6 +57,7 @@ struct pll_params { struct stm32_usbphyc_phy { struct phy *phy; struct stm32_usbphyc *usbphyc; + struct regulator *vbus; u32 index; bool active; }; @@ -291,9 +292,31 @@ static int stm32_usbphyc_phy_exit(struct phy *phy) return stm32_usbphyc_pll_disable(usbphyc); } +static int stm32_usbphyc_phy_power_on(struct phy *phy) +{ + struct stm32_usbphyc_phy *usbphyc_phy = phy_get_drvdata(phy); + + if (usbphyc_phy->vbus) + return regulator_enable(usbphyc_phy->vbus); + + return 0; +} + +static int stm32_usbphyc_phy_power_off(struct phy *phy) +{ + struct stm32_usbphyc_phy *usbphyc_phy = phy_get_drvdata(phy); + + if (usbphyc_phy->vbus) + return regulator_disable(usbphyc_phy->vbus); + + return 0; +} + static const struct phy_ops stm32_usbphyc_phy_ops = { .init = stm32_usbphyc_phy_init, .exit = stm32_usbphyc_phy_exit, + .power_on = stm32_usbphyc_phy_power_on, + .power_off = stm32_usbphyc_phy_power_off, .owner = THIS_MODULE, }; @@ -519,6 +542,14 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) usbphyc->phys[port]->index = index; usbphyc->phys[port]->active = false; + usbphyc->phys[port]->vbus = devm_regulator_get_optional(&phy->dev, "vbus"); + if (IS_ERR(usbphyc->phys[port]->vbus)) { + ret = PTR_ERR(usbphyc->phys[port]->vbus); + if (ret == -EPROBE_DEFER) + goto put_child; + usbphyc->phys[port]->vbus = NULL; + } + port++; } diff --git a/drivers/phy/tegra/xusb-tegra186.c b/drivers/phy/tegra/xusb-tegra186.c index 5d64f69b39a9..ae3915ed9fef 100644 --- a/drivers/phy/tegra/xusb-tegra186.c +++ b/drivers/phy/tegra/xusb-tegra186.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2016-2019, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2016-2020, NVIDIA CORPORATION. All rights reserved. */ #include <linux/delay.h> @@ -113,6 +113,117 @@ #define ID_OVERRIDE_FLOATING ID_OVERRIDE(8) #define ID_OVERRIDE_GROUNDED ID_OVERRIDE(0) +/* XUSB AO registers */ +#define XUSB_AO_USB_DEBOUNCE_DEL (0x4) +#define UHSIC_LINE_DEB_CNT(x) (((x) & 0xf) << 4) +#define UTMIP_LINE_DEB_CNT(x) ((x) & 0xf) + +#define XUSB_AO_UTMIP_TRIGGERS(x) (0x40 + (x) * 4) +#define CLR_WALK_PTR BIT(0) +#define CAP_CFG BIT(1) +#define CLR_WAKE_ALARM BIT(3) + +#define XUSB_AO_UHSIC_TRIGGERS(x) (0x60 + (x) * 4) +#define HSIC_CLR_WALK_PTR BIT(0) +#define HSIC_CLR_WAKE_ALARM BIT(3) +#define HSIC_CAP_CFG BIT(4) + +#define XUSB_AO_UTMIP_SAVED_STATE(x) (0x70 + (x) * 4) +#define SPEED(x) ((x) & 0x3) +#define UTMI_HS SPEED(0) +#define UTMI_FS SPEED(1) +#define UTMI_LS SPEED(2) +#define UTMI_RST SPEED(3) + +#define XUSB_AO_UHSIC_SAVED_STATE(x) (0x90 + (x) * 4) +#define MODE(x) ((x) & 0x1) +#define MODE_HS MODE(0) +#define MODE_RST MODE(1) + +#define XUSB_AO_UTMIP_SLEEPWALK_CFG(x) (0xd0 + (x) * 4) +#define XUSB_AO_UHSIC_SLEEPWALK_CFG(x) (0xf0 + (x) * 4) +#define FAKE_USBOP_VAL BIT(0) +#define FAKE_USBON_VAL BIT(1) +#define FAKE_USBOP_EN BIT(2) +#define FAKE_USBON_EN BIT(3) +#define FAKE_STROBE_VAL BIT(0) +#define FAKE_DATA_VAL BIT(1) +#define FAKE_STROBE_EN BIT(2) +#define FAKE_DATA_EN BIT(3) +#define WAKE_WALK_EN BIT(14) +#define MASTER_ENABLE BIT(15) +#define LINEVAL_WALK_EN BIT(16) +#define WAKE_VAL(x) (((x) & 0xf) << 17) +#define WAKE_VAL_NONE WAKE_VAL(12) +#define WAKE_VAL_ANY WAKE_VAL(15) +#define WAKE_VAL_DS10 WAKE_VAL(2) +#define LINE_WAKEUP_EN BIT(21) +#define MASTER_CFG_SEL BIT(22) + +#define XUSB_AO_UTMIP_SLEEPWALK(x) (0x100 + (x) * 4) +/* phase A */ +#define USBOP_RPD_A BIT(0) +#define USBON_RPD_A BIT(1) +#define AP_A BIT(4) +#define AN_A BIT(5) +#define HIGHZ_A BIT(6) +/* phase B */ +#define USBOP_RPD_B BIT(8) +#define USBON_RPD_B BIT(9) +#define AP_B BIT(12) +#define AN_B BIT(13) +#define HIGHZ_B BIT(14) +/* phase C */ +#define USBOP_RPD_C BIT(16) +#define USBON_RPD_C BIT(17) +#define AP_C BIT(20) +#define AN_C BIT(21) +#define HIGHZ_C BIT(22) +/* phase D */ +#define USBOP_RPD_D BIT(24) +#define USBON_RPD_D BIT(25) +#define AP_D BIT(28) +#define AN_D BIT(29) +#define HIGHZ_D BIT(30) + +#define XUSB_AO_UHSIC_SLEEPWALK(x) (0x120 + (x) * 4) +/* phase A */ +#define RPD_STROBE_A BIT(0) +#define RPD_DATA0_A BIT(1) +#define RPU_STROBE_A BIT(2) +#define RPU_DATA0_A BIT(3) +/* phase B */ +#define RPD_STROBE_B BIT(8) +#define RPD_DATA0_B BIT(9) +#define RPU_STROBE_B BIT(10) +#define RPU_DATA0_B BIT(11) +/* phase C */ +#define RPD_STROBE_C BIT(16) +#define RPD_DATA0_C BIT(17) +#define RPU_STROBE_C BIT(18) +#define RPU_DATA0_C BIT(19) +/* phase D */ +#define RPD_STROBE_D BIT(24) +#define RPD_DATA0_D BIT(25) +#define RPU_STROBE_D BIT(26) +#define RPU_DATA0_D BIT(27) + +#define XUSB_AO_UTMIP_PAD_CFG(x) (0x130 + (x) * 4) +#define FSLS_USE_XUSB_AO BIT(3) +#define TRK_CTRL_USE_XUSB_AO BIT(4) +#define RPD_CTRL_USE_XUSB_AO BIT(5) +#define RPU_USE_XUSB_AO BIT(6) +#define VREG_USE_XUSB_AO BIT(7) +#define USBOP_VAL_PD BIT(8) +#define USBON_VAL_PD BIT(9) +#define E_DPD_OVRD_EN BIT(10) +#define E_DPD_OVRD_VAL BIT(11) + +#define XUSB_AO_UHSIC_PAD_CFG(x) (0x150 + (x) * 4) +#define STROBE_VAL_PD BIT(0) +#define DATA0_VAL_PD BIT(1) +#define USE_XUSB_AO BIT(4) + #define TEGRA186_LANE(_name, _offset, _shift, _mask, _type) \ { \ .name = _name, \ @@ -130,16 +241,37 @@ struct tegra_xusb_fuse_calibration { u32 rpd_ctrl; }; +struct tegra186_xusb_padctl_context { + u32 vbus_id; + u32 usb2_pad_mux; + u32 usb2_port_cap; + u32 ss_port_cap; +}; + struct tegra186_xusb_padctl { struct tegra_xusb_padctl base; + void __iomem *ao_regs; struct tegra_xusb_fuse_calibration calib; /* UTMI bias and tracking */ struct clk *usb2_trk_clk; unsigned int bias_pad_enable; + + /* padctl context */ + struct tegra186_xusb_padctl_context context; }; +static inline void ao_writel(struct tegra186_xusb_padctl *priv, u32 value, unsigned int offset) +{ + writel(value, priv->ao_regs + offset); +} + +static inline u32 ao_readl(struct tegra186_xusb_padctl *priv, unsigned int offset) +{ + return readl(priv->ao_regs + offset); +} + static inline struct tegra186_xusb_padctl * to_tegra186_xusb_padctl(struct tegra_xusb_padctl *padctl) { @@ -180,9 +312,264 @@ static void tegra186_usb2_lane_remove(struct tegra_xusb_lane *lane) kfree(usb2); } +static int tegra186_utmi_enable_phy_sleepwalk(struct tegra_xusb_lane *lane, + enum usb_device_speed speed) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + struct tegra186_xusb_padctl *priv = to_tegra186_xusb_padctl(padctl); + unsigned int index = lane->index; + u32 value; + + mutex_lock(&padctl->lock); + + /* ensure sleepwalk logic is disabled */ + value = ao_readl(priv, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + value &= ~MASTER_ENABLE; + ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + + /* ensure sleepwalk logics are in low power mode */ + value = ao_readl(priv, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + value |= MASTER_CFG_SEL; + ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + + /* set debounce time */ + value = ao_readl(priv, XUSB_AO_USB_DEBOUNCE_DEL); + value &= ~UTMIP_LINE_DEB_CNT(~0); + value |= UTMIP_LINE_DEB_CNT(1); + ao_writel(priv, value, XUSB_AO_USB_DEBOUNCE_DEL); + + /* ensure fake events of sleepwalk logic are desiabled */ + value = ao_readl(priv, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + value &= ~(FAKE_USBOP_VAL | FAKE_USBON_VAL | + FAKE_USBOP_EN | FAKE_USBON_EN); + ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + + /* ensure wake events of sleepwalk logic are not latched */ + value = ao_readl(priv, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + value &= ~LINE_WAKEUP_EN; + ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + + /* disable wake event triggers of sleepwalk logic */ + value = ao_readl(priv, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + value &= ~WAKE_VAL(~0); + value |= WAKE_VAL_NONE; + ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + + /* power down the line state detectors of the pad */ + value = ao_readl(priv, XUSB_AO_UTMIP_PAD_CFG(index)); + value |= (USBOP_VAL_PD | USBON_VAL_PD); + ao_writel(priv, value, XUSB_AO_UTMIP_PAD_CFG(index)); + + /* save state per speed */ + value = ao_readl(priv, XUSB_AO_UTMIP_SAVED_STATE(index)); + value &= ~SPEED(~0); + + switch (speed) { + case USB_SPEED_HIGH: + value |= UTMI_HS; + break; + + case USB_SPEED_FULL: + value |= UTMI_FS; + break; + + case USB_SPEED_LOW: + value |= UTMI_LS; + break; + + default: + value |= UTMI_RST; + break; + } + + ao_writel(priv, value, XUSB_AO_UTMIP_SAVED_STATE(index)); + + /* enable the trigger of the sleepwalk logic */ + value = ao_readl(priv, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + value |= LINEVAL_WALK_EN; + value &= ~WAKE_WALK_EN; + ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + + /* reset the walk pointer and clear the alarm of the sleepwalk logic, + * as well as capture the configuration of the USB2.0 pad + */ + value = ao_readl(priv, XUSB_AO_UTMIP_TRIGGERS(index)); + value |= (CLR_WALK_PTR | CLR_WAKE_ALARM | CAP_CFG); + ao_writel(priv, value, XUSB_AO_UTMIP_TRIGGERS(index)); + + /* setup the pull-ups and pull-downs of the signals during the four + * stages of sleepwalk. + * if device is connected, program sleepwalk logic to maintain a J and + * keep driving K upon seeing remote wake. + */ + value = USBOP_RPD_A | USBOP_RPD_B | USBOP_RPD_C | USBOP_RPD_D; + value |= USBON_RPD_A | USBON_RPD_B | USBON_RPD_C | USBON_RPD_D; + + switch (speed) { + case USB_SPEED_HIGH: + case USB_SPEED_FULL: + /* J state: D+/D- = high/low, K state: D+/D- = low/high */ + value |= HIGHZ_A; + value |= AP_A; + value |= AN_B | AN_C | AN_D; + break; + + case USB_SPEED_LOW: + /* J state: D+/D- = low/high, K state: D+/D- = high/low */ + value |= HIGHZ_A; + value |= AN_A; + value |= AP_B | AP_C | AP_D; + break; + + default: + value |= HIGHZ_A | HIGHZ_B | HIGHZ_C | HIGHZ_D; + break; + } + + ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK(index)); + + /* power up the line state detectors of the pad */ + value = ao_readl(priv, XUSB_AO_UTMIP_PAD_CFG(index)); + value &= ~(USBOP_VAL_PD | USBON_VAL_PD); + ao_writel(priv, value, XUSB_AO_UTMIP_PAD_CFG(index)); + + usleep_range(150, 200); + + /* switch the electric control of the USB2.0 pad to XUSB_AO */ + value = ao_readl(priv, XUSB_AO_UTMIP_PAD_CFG(index)); + value |= FSLS_USE_XUSB_AO | TRK_CTRL_USE_XUSB_AO | RPD_CTRL_USE_XUSB_AO | + RPU_USE_XUSB_AO | VREG_USE_XUSB_AO; + ao_writel(priv, value, XUSB_AO_UTMIP_PAD_CFG(index)); + + /* set the wake signaling trigger events */ + value = ao_readl(priv, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + value &= ~WAKE_VAL(~0); + value |= WAKE_VAL_ANY; + ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + + /* enable the wake detection */ + value = ao_readl(priv, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + value |= MASTER_ENABLE | LINE_WAKEUP_EN; + ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + + mutex_unlock(&padctl->lock); + + return 0; +} + +static int tegra186_utmi_disable_phy_sleepwalk(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + struct tegra186_xusb_padctl *priv = to_tegra186_xusb_padctl(padctl); + unsigned int index = lane->index; + u32 value; + + mutex_lock(&padctl->lock); + + /* disable the wake detection */ + value = ao_readl(priv, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + value &= ~(MASTER_ENABLE | LINE_WAKEUP_EN); + ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + + /* switch the electric control of the USB2.0 pad to XUSB vcore logic */ + value = ao_readl(priv, XUSB_AO_UTMIP_PAD_CFG(index)); + value &= ~(FSLS_USE_XUSB_AO | TRK_CTRL_USE_XUSB_AO | RPD_CTRL_USE_XUSB_AO | + RPU_USE_XUSB_AO | VREG_USE_XUSB_AO); + ao_writel(priv, value, XUSB_AO_UTMIP_PAD_CFG(index)); + + /* disable wake event triggers of sleepwalk logic */ + value = ao_readl(priv, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + value &= ~WAKE_VAL(~0); + value |= WAKE_VAL_NONE; + ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK_CFG(index)); + + /* power down the line state detectors of the port */ + value = ao_readl(priv, XUSB_AO_UTMIP_PAD_CFG(index)); + value |= USBOP_VAL_PD | USBON_VAL_PD; + ao_writel(priv, value, XUSB_AO_UTMIP_PAD_CFG(index)); + + /* clear alarm of the sleepwalk logic */ + value = ao_readl(priv, XUSB_AO_UTMIP_TRIGGERS(index)); + value |= CLR_WAKE_ALARM; + ao_writel(priv, value, XUSB_AO_UTMIP_TRIGGERS(index)); + + mutex_unlock(&padctl->lock); + + return 0; +} + +static int tegra186_utmi_enable_phy_wake(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + unsigned int index = lane->index; + u32 value; + + mutex_lock(&padctl->lock); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value &= ~ALL_WAKE_EVENTS; + value |= USB2_PORT_WAKEUP_EVENT(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + + usleep_range(10, 20); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value &= ~ALL_WAKE_EVENTS; + value |= USB2_PORT_WAKE_INTERRUPT_ENABLE(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + + mutex_unlock(&padctl->lock); + + return 0; +} + +static int tegra186_utmi_disable_phy_wake(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + unsigned int index = lane->index; + u32 value; + + mutex_lock(&padctl->lock); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value &= ~ALL_WAKE_EVENTS; + value &= ~USB2_PORT_WAKE_INTERRUPT_ENABLE(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + + usleep_range(10, 20); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value &= ~ALL_WAKE_EVENTS; + value |= USB2_PORT_WAKEUP_EVENT(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + + mutex_unlock(&padctl->lock); + + return 0; +} + +static bool tegra186_utmi_phy_remote_wake_detected(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + unsigned int index = lane->index; + u32 value; + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + if ((value & USB2_PORT_WAKE_INTERRUPT_ENABLE(index)) && + (value & USB2_PORT_WAKEUP_EVENT(index))) + return true; + + return false; +} + static const struct tegra_xusb_lane_ops tegra186_usb2_lane_ops = { .probe = tegra186_usb2_lane_probe, .remove = tegra186_usb2_lane_remove, + .enable_phy_sleepwalk = tegra186_utmi_enable_phy_sleepwalk, + .disable_phy_sleepwalk = tegra186_utmi_disable_phy_sleepwalk, + .enable_phy_wake = tegra186_utmi_enable_phy_wake, + .disable_phy_wake = tegra186_utmi_disable_phy_wake, + .remote_wake_detected = tegra186_utmi_phy_remote_wake_detected, }; static void tegra186_utmi_bias_pad_power_on(struct tegra_xusb_padctl *padctl) @@ -656,10 +1043,128 @@ static void tegra186_usb3_lane_remove(struct tegra_xusb_lane *lane) kfree(usb3); } +static int tegra186_usb3_enable_phy_sleepwalk(struct tegra_xusb_lane *lane, + enum usb_device_speed speed) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + unsigned int index = lane->index; + u32 value; + + mutex_lock(&padctl->lock); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_1); + value |= SSPX_ELPG_CLAMP_EN_EARLY(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_1); + + usleep_range(100, 200); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_1); + value |= SSPX_ELPG_CLAMP_EN(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_1); + + usleep_range(250, 350); + + mutex_unlock(&padctl->lock); + + return 0; +} + +static int tegra186_usb3_disable_phy_sleepwalk(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + unsigned int index = lane->index; + u32 value; + + mutex_lock(&padctl->lock); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_1); + value &= ~SSPX_ELPG_CLAMP_EN_EARLY(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_1); + + usleep_range(100, 200); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_1); + value &= ~SSPX_ELPG_CLAMP_EN(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_1); + + mutex_unlock(&padctl->lock); + + return 0; +} + +static int tegra186_usb3_enable_phy_wake(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + unsigned int index = lane->index; + u32 value; + + mutex_lock(&padctl->lock); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value &= ~ALL_WAKE_EVENTS; + value |= SS_PORT_WAKEUP_EVENT(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + + usleep_range(10, 20); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value &= ~ALL_WAKE_EVENTS; + value |= SS_PORT_WAKE_INTERRUPT_ENABLE(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + + mutex_unlock(&padctl->lock); + + return 0; +} + +static int tegra186_usb3_disable_phy_wake(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + unsigned int index = lane->index; + u32 value; + + mutex_lock(&padctl->lock); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value &= ~ALL_WAKE_EVENTS; + value &= ~SS_PORT_WAKE_INTERRUPT_ENABLE(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + + usleep_range(10, 20); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value &= ~ALL_WAKE_EVENTS; + value |= SS_PORT_WAKEUP_EVENT(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + + mutex_unlock(&padctl->lock); + + return 0; +} + +static bool tegra186_usb3_phy_remote_wake_detected(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + unsigned int index = lane->index; + u32 value; + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + if ((value & SS_PORT_WAKE_INTERRUPT_ENABLE(index)) && (value & SS_PORT_WAKEUP_EVENT(index))) + return true; + + return false; +} + static const struct tegra_xusb_lane_ops tegra186_usb3_lane_ops = { .probe = tegra186_usb3_lane_probe, .remove = tegra186_usb3_lane_remove, + .enable_phy_sleepwalk = tegra186_usb3_enable_phy_sleepwalk, + .disable_phy_sleepwalk = tegra186_usb3_disable_phy_sleepwalk, + .enable_phy_wake = tegra186_usb3_enable_phy_wake, + .disable_phy_wake = tegra186_usb3_disable_phy_wake, + .remote_wake_detected = tegra186_usb3_phy_remote_wake_detected, }; + static int tegra186_usb3_port_enable(struct tegra_xusb_port *port) { return 0; @@ -913,7 +1418,9 @@ static struct tegra_xusb_padctl * tegra186_xusb_padctl_probe(struct device *dev, const struct tegra_xusb_padctl_soc *soc) { + struct platform_device *pdev = to_platform_device(dev); struct tegra186_xusb_padctl *priv; + struct resource *res; int err; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -923,6 +1430,11 @@ tegra186_xusb_padctl_probe(struct device *dev, priv->base.dev = dev; priv->base.soc = soc; + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ao"); + priv->ao_regs = devm_ioremap_resource(dev, res); + if (IS_ERR(priv->ao_regs)) + return ERR_CAST(priv->ao_regs); + err = tegra186_xusb_read_fuse_calibration(priv); if (err < 0) return ERR_PTR(err); @@ -930,6 +1442,40 @@ tegra186_xusb_padctl_probe(struct device *dev, return &priv->base; } +static void tegra186_xusb_padctl_save(struct tegra_xusb_padctl *padctl) +{ + struct tegra186_xusb_padctl *priv = to_tegra186_xusb_padctl(padctl); + + priv->context.vbus_id = padctl_readl(padctl, USB2_VBUS_ID); + priv->context.usb2_pad_mux = padctl_readl(padctl, XUSB_PADCTL_USB2_PAD_MUX); + priv->context.usb2_port_cap = padctl_readl(padctl, XUSB_PADCTL_USB2_PORT_CAP); + priv->context.ss_port_cap = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_CAP); +} + +static void tegra186_xusb_padctl_restore(struct tegra_xusb_padctl *padctl) +{ + struct tegra186_xusb_padctl *priv = to_tegra186_xusb_padctl(padctl); + + padctl_writel(padctl, priv->context.usb2_pad_mux, XUSB_PADCTL_USB2_PAD_MUX); + padctl_writel(padctl, priv->context.usb2_port_cap, XUSB_PADCTL_USB2_PORT_CAP); + padctl_writel(padctl, priv->context.ss_port_cap, XUSB_PADCTL_SS_PORT_CAP); + padctl_writel(padctl, priv->context.vbus_id, USB2_VBUS_ID); +} + +static int tegra186_xusb_padctl_suspend_noirq(struct tegra_xusb_padctl *padctl) +{ + tegra186_xusb_padctl_save(padctl); + + return 0; +} + +static int tegra186_xusb_padctl_resume_noirq(struct tegra_xusb_padctl *padctl) +{ + tegra186_xusb_padctl_restore(padctl); + + return 0; +} + static void tegra186_xusb_padctl_remove(struct tegra_xusb_padctl *padctl) { } @@ -937,6 +1483,8 @@ static void tegra186_xusb_padctl_remove(struct tegra_xusb_padctl *padctl) static const struct tegra_xusb_padctl_ops tegra186_xusb_padctl_ops = { .probe = tegra186_xusb_padctl_probe, .remove = tegra186_xusb_padctl_remove, + .suspend_noirq = tegra186_xusb_padctl_suspend_noirq, + .resume_noirq = tegra186_xusb_padctl_resume_noirq, .vbus_override = tegra186_xusb_padctl_vbus_override, }; diff --git a/drivers/phy/tegra/xusb-tegra210.c b/drivers/phy/tegra/xusb-tegra210.c index 66bd4613835b..eedfc7c2cc05 100644 --- a/drivers/phy/tegra/xusb-tegra210.c +++ b/drivers/phy/tegra/xusb-tegra210.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2020, NVIDIA CORPORATION. All rights reserved. * Copyright (C) 2015 Google, Inc. */ @@ -11,8 +11,10 @@ #include <linux/mailbox_client.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/of_platform.h> #include <linux/phy/phy.h> #include <linux/platform_device.h> +#include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/reset.h> #include <linux/slab.h> @@ -52,6 +54,20 @@ #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(x, v) (((v) & 0x7) << ((x) * 5)) #define XUSB_PADCTL_SS_PORT_MAP_PORT_DISABLED 0x7 +#define XUSB_PADCTL_ELPG_PROGRAM_0 0x20 +#define USB2_PORT_WAKE_INTERRUPT_ENABLE(x) BIT((x)) +#define USB2_PORT_WAKEUP_EVENT(x) BIT((x) + 7) +#define SS_PORT_WAKE_INTERRUPT_ENABLE(x) BIT((x) + 14) +#define SS_PORT_WAKEUP_EVENT(x) BIT((x) + 21) +#define USB2_HSIC_PORT_WAKE_INTERRUPT_ENABLE(x) BIT((x) + 28) +#define USB2_HSIC_PORT_WAKEUP_EVENT(x) BIT((x) + 30) +#define ALL_WAKE_EVENTS ( \ + USB2_PORT_WAKEUP_EVENT(0) | USB2_PORT_WAKEUP_EVENT(1) | \ + USB2_PORT_WAKEUP_EVENT(2) | USB2_PORT_WAKEUP_EVENT(3) | \ + SS_PORT_WAKEUP_EVENT(0) | SS_PORT_WAKEUP_EVENT(1) | \ + SS_PORT_WAKEUP_EVENT(2) | SS_PORT_WAKEUP_EVENT(3) | \ + USB2_HSIC_PORT_WAKEUP_EVENT(0)) + #define XUSB_PADCTL_ELPG_PROGRAM1 0x024 #define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN (1 << 31) #define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 30) @@ -90,6 +106,8 @@ #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR (1 << 2) #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_OVRD (1 << 1) #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_OVRD (1 << 0) +#define RPD_CTRL(x) (((x) & 0x1f) << 26) +#define RPD_CTRL_VALUE(x) (((x) >> 26) & 0x1f) #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0 0x284 #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD (1 << 11) @@ -108,6 +126,8 @@ #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT 12 #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_MASK 0x7f #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_VAL 0x1e +#define TCTRL_VALUE(x) (((x) & 0x3f) >> 0) +#define PCTRL_VALUE(x) (((x) >> 6) & 0x3f) #define XUSB_PADCTL_HSIC_PADX_CTL0(x) (0x300 + (x) * 0x20) #define XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE (1 << 18) @@ -198,6 +218,18 @@ #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_TERM_EN BIT(18) #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_MODE_OVRD BIT(13) +#define XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(x) (0x464 + (x) * 0x40) +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ BIT(0) +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ_OVRD BIT(1) +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_MASK GENMASK(5, 4) +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_VAL GENMASK(5, 4) +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_PWR_OVRD BIT(24) +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ BIT(8) +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ_OVRD BIT(9) +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_MASK GENMASK(13, 12) +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL GENMASK(13, 12) +#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD BIT(25) + #define XUSB_PADCTL_UPHY_PLL_S0_CTL1 0x860 #define XUSB_PADCTL_UPHY_PLL_S0_CTL2 0x864 @@ -209,6 +241,7 @@ #define XUSB_PADCTL_UPHY_PLL_S0_CTL8 0x87c #define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL1 0x960 +#define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL2 0x964 #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(x) (0xa60 + (x) * 0x40) #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT 16 @@ -238,16 +271,161 @@ #define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING 8 #define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_GROUNDED 0 +/* USB2 SLEEPWALK registers */ +#define UTMIP(_port, _offset1, _offset2) \ + (((_port) <= 2) ? (_offset1) : (_offset2)) + +#define PMC_UTMIP_UHSIC_SLEEP_CFG(x) UTMIP(x, 0x1fc, 0x4d0) +#define UTMIP_MASTER_ENABLE(x) UTMIP(x, BIT(8 * (x)), BIT(0)) +#define UTMIP_FSLS_USE_PMC(x) UTMIP(x, BIT(8 * (x) + 1), \ + BIT(1)) +#define UTMIP_PCTRL_USE_PMC(x) UTMIP(x, BIT(8 * (x) + 2), \ + BIT(2)) +#define UTMIP_TCTRL_USE_PMC(x) UTMIP(x, BIT(8 * (x) + 3), \ + BIT(3)) +#define UTMIP_WAKE_VAL(_port, _value) (((_value) & 0xf) << \ + (UTMIP(_port, 8 * (_port) + 4, 4))) +#define UTMIP_WAKE_VAL_NONE(_port) UTMIP_WAKE_VAL(_port, 12) +#define UTMIP_WAKE_VAL_ANY(_port) UTMIP_WAKE_VAL(_port, 15) + +#define PMC_UTMIP_UHSIC_SLEEP_CFG1 (0x4d0) +#define UTMIP_RPU_SWITC_LOW_USE_PMC_PX(x) BIT((x) + 8) +#define UTMIP_RPD_CTRL_USE_PMC_PX(x) BIT((x) + 16) + +#define PMC_UTMIP_MASTER_CONFIG (0x274) +#define UTMIP_PWR(x) UTMIP(x, BIT(x), BIT(4)) +#define UHSIC_PWR BIT(3) + +#define PMC_USB_DEBOUNCE_DEL (0xec) +#define DEBOUNCE_VAL(x) (((x) & 0xffff) << 0) +#define UTMIP_LINE_DEB_CNT(x) (((x) & 0xf) << 16) +#define UHSIC_LINE_DEB_CNT(x) (((x) & 0xf) << 20) + +#define PMC_UTMIP_UHSIC_FAKE(x) UTMIP(x, 0x218, 0x294) +#define UTMIP_FAKE_USBOP_VAL(x) UTMIP(x, BIT(4 * (x)), BIT(8)) +#define UTMIP_FAKE_USBON_VAL(x) UTMIP(x, BIT(4 * (x) + 1), \ + BIT(9)) +#define UTMIP_FAKE_USBOP_EN(x) UTMIP(x, BIT(4 * (x) + 2), \ + BIT(10)) +#define UTMIP_FAKE_USBON_EN(x) UTMIP(x, BIT(4 * (x) + 3), \ + BIT(11)) + +#define PMC_UTMIP_UHSIC_SLEEPWALK_CFG(x) UTMIP(x, 0x200, 0x288) +#define UTMIP_LINEVAL_WALK_EN(x) UTMIP(x, BIT(8 * (x) + 7), \ + BIT(15)) + +#define PMC_USB_AO (0xf0) +#define USBOP_VAL_PD(x) UTMIP(x, BIT(4 * (x)), BIT(20)) +#define USBON_VAL_PD(x) UTMIP(x, BIT(4 * (x) + 1), \ + BIT(21)) +#define STROBE_VAL_PD BIT(12) +#define DATA0_VAL_PD BIT(13) +#define DATA1_VAL_PD BIT(24) + +#define PMC_UTMIP_UHSIC_SAVED_STATE(x) UTMIP(x, 0x1f0, 0x280) +#define SPEED(_port, _value) (((_value) & 0x3) << \ + (UTMIP(_port, 8 * (_port), 8))) +#define UTMI_HS(_port) SPEED(_port, 0) +#define UTMI_FS(_port) SPEED(_port, 1) +#define UTMI_LS(_port) SPEED(_port, 2) +#define UTMI_RST(_port) SPEED(_port, 3) + +#define PMC_UTMIP_UHSIC_TRIGGERS (0x1ec) +#define UTMIP_CLR_WALK_PTR(x) UTMIP(x, BIT(x), BIT(16)) +#define UTMIP_CAP_CFG(x) UTMIP(x, BIT((x) + 4), BIT(17)) +#define UTMIP_CLR_WAKE_ALARM(x) UTMIP(x, BIT((x) + 12), \ + BIT(19)) +#define UHSIC_CLR_WALK_PTR BIT(3) +#define UHSIC_CLR_WAKE_ALARM BIT(15) + +#define PMC_UTMIP_SLEEPWALK_PX(x) UTMIP(x, 0x204 + (4 * (x)), \ + 0x4e0) +/* phase A */ +#define UTMIP_USBOP_RPD_A BIT(0) +#define UTMIP_USBON_RPD_A BIT(1) +#define UTMIP_AP_A BIT(4) +#define UTMIP_AN_A BIT(5) +#define UTMIP_HIGHZ_A BIT(6) +/* phase B */ +#define UTMIP_USBOP_RPD_B BIT(8) +#define UTMIP_USBON_RPD_B BIT(9) +#define UTMIP_AP_B BIT(12) +#define UTMIP_AN_B BIT(13) +#define UTMIP_HIGHZ_B BIT(14) +/* phase C */ +#define UTMIP_USBOP_RPD_C BIT(16) +#define UTMIP_USBON_RPD_C BIT(17) +#define UTMIP_AP_C BIT(20) +#define UTMIP_AN_C BIT(21) +#define UTMIP_HIGHZ_C BIT(22) +/* phase D */ +#define UTMIP_USBOP_RPD_D BIT(24) +#define UTMIP_USBON_RPD_D BIT(25) +#define UTMIP_AP_D BIT(28) +#define UTMIP_AN_D BIT(29) +#define UTMIP_HIGHZ_D BIT(30) + +#define PMC_UTMIP_UHSIC_LINE_WAKEUP (0x26c) +#define UTMIP_LINE_WAKEUP_EN(x) UTMIP(x, BIT(x), BIT(4)) +#define UHSIC_LINE_WAKEUP_EN BIT(3) + +#define PMC_UTMIP_TERM_PAD_CFG (0x1f8) +#define PCTRL_VAL(x) (((x) & 0x3f) << 1) +#define TCTRL_VAL(x) (((x) & 0x3f) << 7) + +#define PMC_UTMIP_PAD_CFGX(x) (0x4c0 + (4 * (x))) +#define RPD_CTRL_PX(x) (((x) & 0x1f) << 22) + +#define PMC_UHSIC_SLEEP_CFG PMC_UTMIP_UHSIC_SLEEP_CFG(0) +#define UHSIC_MASTER_ENABLE BIT(24) +#define UHSIC_WAKE_VAL(_value) (((_value) & 0xf) << 28) +#define UHSIC_WAKE_VAL_SD10 UHSIC_WAKE_VAL(2) +#define UHSIC_WAKE_VAL_NONE UHSIC_WAKE_VAL(12) + +#define PMC_UHSIC_FAKE PMC_UTMIP_UHSIC_FAKE(0) +#define UHSIC_FAKE_STROBE_VAL BIT(12) +#define UHSIC_FAKE_DATA_VAL BIT(13) +#define UHSIC_FAKE_STROBE_EN BIT(14) +#define UHSIC_FAKE_DATA_EN BIT(15) + +#define PMC_UHSIC_SAVED_STATE PMC_UTMIP_UHSIC_SAVED_STATE(0) +#define UHSIC_MODE(_value) (((_value) & 0x1) << 24) +#define UHSIC_HS UHSIC_MODE(0) +#define UHSIC_RST UHSIC_MODE(1) + +#define PMC_UHSIC_SLEEPWALK_CFG PMC_UTMIP_UHSIC_SLEEPWALK_CFG(0) +#define UHSIC_WAKE_WALK_EN BIT(30) +#define UHSIC_LINEVAL_WALK_EN BIT(31) + +#define PMC_UHSIC_SLEEPWALK_P0 (0x210) +#define UHSIC_DATA0_RPD_A BIT(1) +#define UHSIC_DATA0_RPU_B BIT(11) +#define UHSIC_DATA0_RPU_C BIT(19) +#define UHSIC_DATA0_RPU_D BIT(27) +#define UHSIC_STROBE_RPU_A BIT(2) +#define UHSIC_STROBE_RPD_B BIT(8) +#define UHSIC_STROBE_RPD_C BIT(16) +#define UHSIC_STROBE_RPD_D BIT(24) + struct tegra210_xusb_fuse_calibration { u32 hs_curr_level[4]; u32 hs_term_range_adj; u32 rpd_ctrl; }; +struct tegra210_xusb_padctl_context { + u32 usb2_pad_mux; + u32 usb2_port_cap; + u32 ss_port_map; + u32 usb3_pad_mux; +}; + struct tegra210_xusb_padctl { struct tegra_xusb_padctl base; + struct regmap *regmap; struct tegra210_xusb_fuse_calibration fuse; + struct tegra210_xusb_padctl_context context; }; static inline struct tegra210_xusb_padctl * @@ -256,23 +434,51 @@ to_tegra210_xusb_padctl(struct tegra_xusb_padctl *padctl) return container_of(padctl, struct tegra210_xusb_padctl, base); } +static const struct tegra_xusb_lane_map tegra210_usb3_map[] = { + { 0, "pcie", 6 }, + { 1, "pcie", 5 }, + { 2, "pcie", 0 }, + { 2, "pcie", 3 }, + { 3, "pcie", 4 }, + { 3, "sata", 0 }, + { 0, NULL, 0 } +}; + +static int tegra210_usb3_lane_map(struct tegra_xusb_lane *lane) +{ + const struct tegra_xusb_lane_map *map; + + for (map = tegra210_usb3_map; map->type; map++) { + if (map->index == lane->index && + strcmp(map->type, lane->pad->soc->name) == 0) { + dev_dbg(lane->pad->padctl->dev, "lane = %s map to port = usb3-%d\n", + lane->pad->soc->lanes[lane->index].name, map->port); + return map->port; + } + } + + return -EINVAL; +} + /* must be called under padctl->lock */ static int tegra210_pex_uphy_enable(struct tegra_xusb_padctl *padctl) { struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(padctl->pcie); unsigned long timeout; u32 value; + unsigned int i; int err; - if (pcie->enable > 0) { - pcie->enable++; + if (pcie->enable) return 0; - } err = clk_prepare_enable(pcie->pll); if (err < 0) return err; + if (tegra210_plle_hw_sequence_is_enabled()) + goto skip_pll_init; + err = reset_control_deassert(pcie->rst); if (err < 0) goto disable; @@ -455,7 +661,14 @@ static int tegra210_pex_uphy_enable(struct tegra_xusb_padctl *padctl) tegra210_xusb_pll_hw_sequence_start(); - pcie->enable++; +skip_pll_init: + pcie->enable = true; + + for (i = 0; i < padctl->pcie->soc->num_lanes; i++) { + value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); + value |= XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(i); + padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); + } return 0; @@ -469,34 +682,44 @@ disable: static void tegra210_pex_uphy_disable(struct tegra_xusb_padctl *padctl) { struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(padctl->pcie); + u32 value; + unsigned int i; - mutex_lock(&padctl->lock); + if (WARN_ON(!pcie->enable)) + return; - if (WARN_ON(pcie->enable == 0)) - goto unlock; + pcie->enable = false; - if (--pcie->enable > 0) - goto unlock; + for (i = 0; i < padctl->pcie->soc->num_lanes; i++) { + value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); + value &= ~XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(i); + padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); + } - reset_control_assert(pcie->rst); clk_disable_unprepare(pcie->pll); - -unlock: - mutex_unlock(&padctl->lock); } /* must be called under padctl->lock */ -static int tegra210_sata_uphy_enable(struct tegra_xusb_padctl *padctl, bool usb) +static int tegra210_sata_uphy_enable(struct tegra_xusb_padctl *padctl) { struct tegra_xusb_sata_pad *sata = to_sata_pad(padctl->sata); + struct tegra_xusb_lane *lane = tegra_xusb_find_lane(padctl, "sata", 0); unsigned long timeout; u32 value; + unsigned int i; int err; + bool usb; - if (sata->enable > 0) { - sata->enable++; + if (sata->enable) return 0; - } + + if (IS_ERR(lane)) + return 0; + + if (tegra210_plle_hw_sequence_is_enabled()) + goto skip_pll_init; + + usb = tegra_xusb_lane_check(lane, "usb3-ss"); err = clk_prepare_enable(sata->pll); if (err < 0) @@ -697,7 +920,14 @@ static int tegra210_sata_uphy_enable(struct tegra_xusb_padctl *padctl, bool usb) tegra210_sata_pll_hw_sequence_start(); - sata->enable++; +skip_pll_init: + sata->enable = true; + + for (i = 0; i < padctl->sata->soc->num_lanes; i++) { + value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); + value |= XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(i); + padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); + } return 0; @@ -711,31 +941,27 @@ disable: static void tegra210_sata_uphy_disable(struct tegra_xusb_padctl *padctl) { struct tegra_xusb_sata_pad *sata = to_sata_pad(padctl->sata); + u32 value; + unsigned int i; - mutex_lock(&padctl->lock); + if (WARN_ON(!sata->enable)) + return; - if (WARN_ON(sata->enable == 0)) - goto unlock; + sata->enable = false; - if (--sata->enable > 0) - goto unlock; + for (i = 0; i < padctl->sata->soc->num_lanes; i++) { + value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); + value &= ~XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(i); + padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); + } - reset_control_assert(sata->rst); clk_disable_unprepare(sata->pll); - -unlock: - mutex_unlock(&padctl->lock); } -static int tegra210_xusb_padctl_enable(struct tegra_xusb_padctl *padctl) +static void tegra210_aux_mux_lp0_clamp_disable(struct tegra_xusb_padctl *padctl) { u32 value; - mutex_lock(&padctl->lock); - - if (padctl->enable++ > 0) - goto out; - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN; padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); @@ -751,24 +977,12 @@ static int tegra210_xusb_padctl_enable(struct tegra_xusb_padctl *padctl) value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN; padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); - -out: - mutex_unlock(&padctl->lock); - return 0; } -static int tegra210_xusb_padctl_disable(struct tegra_xusb_padctl *padctl) +static void tegra210_aux_mux_lp0_clamp_enable(struct tegra_xusb_padctl *padctl) { u32 value; - mutex_lock(&padctl->lock); - - if (WARN_ON(padctl->enable == 0)) - goto out; - - if (--padctl->enable > 0) - goto out; - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); value |= XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN; padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); @@ -784,12 +998,38 @@ static int tegra210_xusb_padctl_disable(struct tegra_xusb_padctl *padctl) value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); value |= XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN; padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); +} + +static int tegra210_uphy_init(struct tegra_xusb_padctl *padctl) +{ + if (padctl->pcie) + tegra210_pex_uphy_enable(padctl); + + if (padctl->sata) + tegra210_sata_uphy_enable(padctl); + + if (!tegra210_plle_hw_sequence_is_enabled()) + tegra210_plle_hw_sequence_start(); + else + dev_dbg(padctl->dev, "PLLE is already in HW control\n"); + + tegra210_aux_mux_lp0_clamp_disable(padctl); -out: - mutex_unlock(&padctl->lock); return 0; } +static void __maybe_unused +tegra210_uphy_deinit(struct tegra_xusb_padctl *padctl) +{ + tegra210_aux_mux_lp0_clamp_enable(padctl); + + if (padctl->sata) + tegra210_sata_uphy_disable(padctl); + + if (padctl->pcie) + tegra210_pex_uphy_disable(padctl); +} + static int tegra210_hsic_set_idle(struct tegra_xusb_padctl *padctl, unsigned int index, bool idle) { @@ -815,6 +1055,643 @@ static int tegra210_hsic_set_idle(struct tegra_xusb_padctl *padctl, return 0; } +static int tegra210_usb3_enable_phy_sleepwalk(struct tegra_xusb_lane *lane, + enum usb_device_speed speed) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + int port = tegra210_usb3_lane_map(lane); + struct device *dev = padctl->dev; + u32 value; + + if (port < 0) { + dev_err(dev, "invalid usb3 port number\n"); + return -EINVAL; + } + + mutex_lock(&padctl->lock); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); + value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(port); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); + + usleep_range(100, 200); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); + value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(port); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); + + usleep_range(250, 350); + + mutex_unlock(&padctl->lock); + + return 0; +} + +static int tegra210_usb3_disable_phy_sleepwalk(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + int port = tegra210_usb3_lane_map(lane); + struct device *dev = padctl->dev; + u32 value; + + if (port < 0) { + dev_err(dev, "invalid usb3 port number\n"); + return -EINVAL; + } + + mutex_lock(&padctl->lock); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); + value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(port); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); + + usleep_range(100, 200); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); + value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(port); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); + + mutex_unlock(&padctl->lock); + + return 0; +} + +static int tegra210_usb3_enable_phy_wake(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + int port = tegra210_usb3_lane_map(lane); + struct device *dev = padctl->dev; + u32 value; + + if (port < 0) { + dev_err(dev, "invalid usb3 port number\n"); + return -EINVAL; + } + + mutex_lock(&padctl->lock); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); + value &= ~ALL_WAKE_EVENTS; + value |= SS_PORT_WAKEUP_EVENT(port); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); + + usleep_range(10, 20); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); + value &= ~ALL_WAKE_EVENTS; + value |= SS_PORT_WAKE_INTERRUPT_ENABLE(port); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); + + mutex_unlock(&padctl->lock); + + return 0; +} + +static int tegra210_usb3_disable_phy_wake(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + int port = tegra210_usb3_lane_map(lane); + struct device *dev = padctl->dev; + u32 value; + + if (port < 0) { + dev_err(dev, "invalid usb3 port number\n"); + return -EINVAL; + } + + mutex_lock(&padctl->lock); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); + value &= ~ALL_WAKE_EVENTS; + value &= ~SS_PORT_WAKE_INTERRUPT_ENABLE(port); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); + + usleep_range(10, 20); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); + value &= ~ALL_WAKE_EVENTS; + value |= SS_PORT_WAKEUP_EVENT(port); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); + + mutex_unlock(&padctl->lock); + + return 0; +} + +static bool tegra210_usb3_phy_remote_wake_detected(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + int index = tegra210_usb3_lane_map(lane); + u32 value; + + if (index < 0) + return false; + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); + if ((value & SS_PORT_WAKE_INTERRUPT_ENABLE(index)) && (value & SS_PORT_WAKEUP_EVENT(index))) + return true; + + return false; +} + +static int tegra210_utmi_enable_phy_wake(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + unsigned int index = lane->index; + u32 value; + + mutex_lock(&padctl->lock); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); + value &= ~ALL_WAKE_EVENTS; + value |= USB2_PORT_WAKEUP_EVENT(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); + + usleep_range(10, 20); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); + value &= ~ALL_WAKE_EVENTS; + value |= USB2_PORT_WAKE_INTERRUPT_ENABLE(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); + + mutex_unlock(&padctl->lock); + + return 0; +} + +static int tegra210_utmi_disable_phy_wake(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + unsigned int index = lane->index; + u32 value; + + mutex_lock(&padctl->lock); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); + value &= ~ALL_WAKE_EVENTS; + value &= ~USB2_PORT_WAKE_INTERRUPT_ENABLE(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); + + usleep_range(10, 20); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); + value &= ~ALL_WAKE_EVENTS; + value |= USB2_PORT_WAKEUP_EVENT(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); + + mutex_unlock(&padctl->lock); + + return 0; +} + +static bool tegra210_utmi_phy_remote_wake_detected(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + unsigned int index = lane->index; + u32 value; + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); + if ((value & USB2_PORT_WAKE_INTERRUPT_ENABLE(index)) && + (value & USB2_PORT_WAKEUP_EVENT(index))) + return true; + + return false; +} + +static int tegra210_hsic_enable_phy_wake(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + unsigned int index = lane->index; + u32 value; + + mutex_lock(&padctl->lock); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); + value &= ~ALL_WAKE_EVENTS; + value |= USB2_HSIC_PORT_WAKEUP_EVENT(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); + + usleep_range(10, 20); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); + value &= ~ALL_WAKE_EVENTS; + value |= USB2_HSIC_PORT_WAKE_INTERRUPT_ENABLE(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); + + mutex_unlock(&padctl->lock); + + return 0; +} + +static int tegra210_hsic_disable_phy_wake(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + unsigned int index = lane->index; + u32 value; + + mutex_lock(&padctl->lock); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); + value &= ~ALL_WAKE_EVENTS; + value &= ~USB2_HSIC_PORT_WAKE_INTERRUPT_ENABLE(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); + + usleep_range(10, 20); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); + value &= ~ALL_WAKE_EVENTS; + value |= USB2_HSIC_PORT_WAKEUP_EVENT(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); + + mutex_unlock(&padctl->lock); + + return 0; +} + +static bool tegra210_hsic_phy_remote_wake_detected(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + unsigned int index = lane->index; + u32 value; + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); + if ((value & USB2_HSIC_PORT_WAKE_INTERRUPT_ENABLE(index)) && + (value & USB2_HSIC_PORT_WAKEUP_EVENT(index))) + return true; + + return false; +} + +#define padctl_pmc_readl(_priv, _offset) \ +({ \ + u32 value; \ + WARN(regmap_read(_priv->regmap, _offset, &value), "read %s failed\n", #_offset);\ + value; \ +}) + +#define padctl_pmc_writel(_priv, _value, _offset) \ + WARN(regmap_write(_priv->regmap, _offset, _value), "write %s failed\n", #_offset) + +static int tegra210_pmc_utmi_enable_phy_sleepwalk(struct tegra_xusb_lane *lane, + enum usb_device_speed speed) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl); + unsigned int port = lane->index; + u32 value, tctrl, pctrl, rpd_ctrl; + + if (!priv->regmap) + return -EOPNOTSUPP; + + if (speed > USB_SPEED_HIGH) + return -EINVAL; + + value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); + tctrl = TCTRL_VALUE(value); + pctrl = PCTRL_VALUE(value); + + value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(port)); + rpd_ctrl = RPD_CTRL_VALUE(value); + + /* ensure sleepwalk logic is disabled */ + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); + value &= ~UTMIP_MASTER_ENABLE(port); + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); + + /* ensure sleepwalk logics are in low power mode */ + value = padctl_pmc_readl(priv, PMC_UTMIP_MASTER_CONFIG); + value |= UTMIP_PWR(port); + padctl_pmc_writel(priv, value, PMC_UTMIP_MASTER_CONFIG); + + /* set debounce time */ + value = padctl_pmc_readl(priv, PMC_USB_DEBOUNCE_DEL); + value &= ~UTMIP_LINE_DEB_CNT(~0); + value |= UTMIP_LINE_DEB_CNT(0x1); + padctl_pmc_writel(priv, value, PMC_USB_DEBOUNCE_DEL); + + /* ensure fake events of sleepwalk logic are desiabled */ + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_FAKE(port)); + value &= ~(UTMIP_FAKE_USBOP_VAL(port) | UTMIP_FAKE_USBON_VAL(port) | + UTMIP_FAKE_USBOP_EN(port) | UTMIP_FAKE_USBON_EN(port)); + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_FAKE(port)); + + /* ensure wake events of sleepwalk logic are not latched */ + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_LINE_WAKEUP); + value &= ~UTMIP_LINE_WAKEUP_EN(port); + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_LINE_WAKEUP); + + /* disable wake event triggers of sleepwalk logic */ + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); + value &= ~UTMIP_WAKE_VAL(port, ~0); + value |= UTMIP_WAKE_VAL_NONE(port); + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); + + /* power down the line state detectors of the pad */ + value = padctl_pmc_readl(priv, PMC_USB_AO); + value |= (USBOP_VAL_PD(port) | USBON_VAL_PD(port)); + padctl_pmc_writel(priv, value, PMC_USB_AO); + + /* save state per speed */ + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SAVED_STATE(port)); + value &= ~SPEED(port, ~0); + + switch (speed) { + case USB_SPEED_HIGH: + value |= UTMI_HS(port); + break; + + case USB_SPEED_FULL: + value |= UTMI_FS(port); + break; + + case USB_SPEED_LOW: + value |= UTMI_LS(port); + break; + + default: + value |= UTMI_RST(port); + break; + } + + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SAVED_STATE(port)); + + /* enable the trigger of the sleepwalk logic */ + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEPWALK_CFG(port)); + value |= UTMIP_LINEVAL_WALK_EN(port); + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEPWALK_CFG(port)); + + /* + * Reset the walk pointer and clear the alarm of the sleepwalk logic, + * as well as capture the configuration of the USB2.0 pad. + */ + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_TRIGGERS); + value |= UTMIP_CLR_WALK_PTR(port) | UTMIP_CLR_WAKE_ALARM(port) | UTMIP_CAP_CFG(port); + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_TRIGGERS); + + /* program electrical parameters read from XUSB PADCTL */ + value = padctl_pmc_readl(priv, PMC_UTMIP_TERM_PAD_CFG); + value &= ~(TCTRL_VAL(~0) | PCTRL_VAL(~0)); + value |= (TCTRL_VAL(tctrl) | PCTRL_VAL(pctrl)); + padctl_pmc_writel(priv, value, PMC_UTMIP_TERM_PAD_CFG); + + value = padctl_pmc_readl(priv, PMC_UTMIP_PAD_CFGX(port)); + value &= ~RPD_CTRL_PX(~0); + value |= RPD_CTRL_PX(rpd_ctrl); + padctl_pmc_writel(priv, value, PMC_UTMIP_PAD_CFGX(port)); + + /* + * Set up the pull-ups and pull-downs of the signals during the four + * stages of sleepwalk. If a device is connected, program sleepwalk + * logic to maintain a J and keep driving K upon seeing remote wake. + */ + value = padctl_pmc_readl(priv, PMC_UTMIP_SLEEPWALK_PX(port)); + value = UTMIP_USBOP_RPD_A | UTMIP_USBOP_RPD_B | UTMIP_USBOP_RPD_C | UTMIP_USBOP_RPD_D; + value |= UTMIP_USBON_RPD_A | UTMIP_USBON_RPD_B | UTMIP_USBON_RPD_C | UTMIP_USBON_RPD_D; + + switch (speed) { + case USB_SPEED_HIGH: + case USB_SPEED_FULL: + /* J state: D+/D- = high/low, K state: D+/D- = low/high */ + value |= UTMIP_HIGHZ_A; + value |= UTMIP_AP_A; + value |= UTMIP_AN_B | UTMIP_AN_C | UTMIP_AN_D; + break; + + case USB_SPEED_LOW: + /* J state: D+/D- = low/high, K state: D+/D- = high/low */ + value |= UTMIP_HIGHZ_A; + value |= UTMIP_AN_A; + value |= UTMIP_AP_B | UTMIP_AP_C | UTMIP_AP_D; + break; + + default: + value |= UTMIP_HIGHZ_A | UTMIP_HIGHZ_B | UTMIP_HIGHZ_C | UTMIP_HIGHZ_D; + break; + } + + padctl_pmc_writel(priv, value, PMC_UTMIP_SLEEPWALK_PX(port)); + + /* power up the line state detectors of the pad */ + value = padctl_pmc_readl(priv, PMC_USB_AO); + value &= ~(USBOP_VAL_PD(port) | USBON_VAL_PD(port)); + padctl_pmc_writel(priv, value, PMC_USB_AO); + + usleep_range(50, 100); + + /* switch the electric control of the USB2.0 pad to PMC */ + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); + value |= UTMIP_FSLS_USE_PMC(port) | UTMIP_PCTRL_USE_PMC(port) | UTMIP_TCTRL_USE_PMC(port); + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); + + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG1); + value |= UTMIP_RPD_CTRL_USE_PMC_PX(port) | UTMIP_RPU_SWITC_LOW_USE_PMC_PX(port); + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG1); + + /* set the wake signaling trigger events */ + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); + value &= ~UTMIP_WAKE_VAL(port, ~0); + value |= UTMIP_WAKE_VAL_ANY(port); + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); + + /* enable the wake detection */ + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); + value |= UTMIP_MASTER_ENABLE(port); + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); + + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_LINE_WAKEUP); + value |= UTMIP_LINE_WAKEUP_EN(port); + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_LINE_WAKEUP); + + return 0; +} + +static int tegra210_pmc_utmi_disable_phy_sleepwalk(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl); + unsigned int port = lane->index; + u32 value; + + if (!priv->regmap) + return -EOPNOTSUPP; + + /* disable the wake detection */ + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); + value &= ~UTMIP_MASTER_ENABLE(port); + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); + + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_LINE_WAKEUP); + value &= ~UTMIP_LINE_WAKEUP_EN(port); + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_LINE_WAKEUP); + + /* switch the electric control of the USB2.0 pad to XUSB or USB2 */ + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); + value &= ~(UTMIP_FSLS_USE_PMC(port) | UTMIP_PCTRL_USE_PMC(port) | + UTMIP_TCTRL_USE_PMC(port)); + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); + + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG1); + value &= ~(UTMIP_RPD_CTRL_USE_PMC_PX(port) | UTMIP_RPU_SWITC_LOW_USE_PMC_PX(port)); + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG1); + + /* disable wake event triggers of sleepwalk logic */ + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); + value &= ~UTMIP_WAKE_VAL(port, ~0); + value |= UTMIP_WAKE_VAL_NONE(port); + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); + + /* power down the line state detectors of the port */ + value = padctl_pmc_readl(priv, PMC_USB_AO); + value |= (USBOP_VAL_PD(port) | USBON_VAL_PD(port)); + padctl_pmc_writel(priv, value, PMC_USB_AO); + + /* clear alarm of the sleepwalk logic */ + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_TRIGGERS); + value |= UTMIP_CLR_WAKE_ALARM(port); + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_TRIGGERS); + + return 0; +} + +static int tegra210_pmc_hsic_enable_phy_sleepwalk(struct tegra_xusb_lane *lane, + enum usb_device_speed speed) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl); + u32 value; + + if (!priv->regmap) + return -EOPNOTSUPP; + + /* ensure sleepwalk logic is disabled */ + value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEP_CFG); + value &= ~UHSIC_MASTER_ENABLE; + padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEP_CFG); + + /* ensure sleepwalk logics are in low power mode */ + value = padctl_pmc_readl(priv, PMC_UTMIP_MASTER_CONFIG); + value |= UHSIC_PWR; + padctl_pmc_writel(priv, value, PMC_UTMIP_MASTER_CONFIG); + + /* set debounce time */ + value = padctl_pmc_readl(priv, PMC_USB_DEBOUNCE_DEL); + value &= ~UHSIC_LINE_DEB_CNT(~0); + value |= UHSIC_LINE_DEB_CNT(0x1); + padctl_pmc_writel(priv, value, PMC_USB_DEBOUNCE_DEL); + + /* ensure fake events of sleepwalk logic are desiabled */ + value = padctl_pmc_readl(priv, PMC_UHSIC_FAKE); + value &= ~(UHSIC_FAKE_STROBE_VAL | UHSIC_FAKE_DATA_VAL | + UHSIC_FAKE_STROBE_EN | UHSIC_FAKE_DATA_EN); + padctl_pmc_writel(priv, value, PMC_UHSIC_FAKE); + + /* ensure wake events of sleepwalk logic are not latched */ + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_LINE_WAKEUP); + value &= ~UHSIC_LINE_WAKEUP_EN; + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_LINE_WAKEUP); + + /* disable wake event triggers of sleepwalk logic */ + value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEP_CFG); + value &= ~UHSIC_WAKE_VAL(~0); + value |= UHSIC_WAKE_VAL_NONE; + padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEP_CFG); + + /* power down the line state detectors of the port */ + value = padctl_pmc_readl(priv, PMC_USB_AO); + value |= STROBE_VAL_PD | DATA0_VAL_PD | DATA1_VAL_PD; + padctl_pmc_writel(priv, value, PMC_USB_AO); + + /* save state, HSIC always comes up as HS */ + value = padctl_pmc_readl(priv, PMC_UHSIC_SAVED_STATE); + value &= ~UHSIC_MODE(~0); + value |= UHSIC_HS; + padctl_pmc_writel(priv, value, PMC_UHSIC_SAVED_STATE); + + /* enable the trigger of the sleepwalk logic */ + value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEPWALK_CFG); + value |= UHSIC_WAKE_WALK_EN | UHSIC_LINEVAL_WALK_EN; + padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEPWALK_CFG); + + /* + * Reset the walk pointer and clear the alarm of the sleepwalk logic, + * as well as capture the configuration of the USB2.0 port. + */ + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_TRIGGERS); + value |= UHSIC_CLR_WALK_PTR | UHSIC_CLR_WAKE_ALARM; + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_TRIGGERS); + + /* + * Set up the pull-ups and pull-downs of the signals during the four + * stages of sleepwalk. Maintain a HSIC IDLE and keep driving HSIC + * RESUME upon remote wake. + */ + value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEPWALK_P0); + value = UHSIC_DATA0_RPD_A | UHSIC_DATA0_RPU_B | UHSIC_DATA0_RPU_C | UHSIC_DATA0_RPU_D | + UHSIC_STROBE_RPU_A | UHSIC_STROBE_RPD_B | UHSIC_STROBE_RPD_C | UHSIC_STROBE_RPD_D; + padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEPWALK_P0); + + /* power up the line state detectors of the port */ + value = padctl_pmc_readl(priv, PMC_USB_AO); + value &= ~(STROBE_VAL_PD | DATA0_VAL_PD | DATA1_VAL_PD); + padctl_pmc_writel(priv, value, PMC_USB_AO); + + usleep_range(50, 100); + + /* set the wake signaling trigger events */ + value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEP_CFG); + value &= ~UHSIC_WAKE_VAL(~0); + value |= UHSIC_WAKE_VAL_SD10; + padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEP_CFG); + + /* enable the wake detection */ + value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEP_CFG); + value |= UHSIC_MASTER_ENABLE; + padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEP_CFG); + + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_LINE_WAKEUP); + value |= UHSIC_LINE_WAKEUP_EN; + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_LINE_WAKEUP); + + return 0; +} + +static int tegra210_pmc_hsic_disable_phy_sleepwalk(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl); + u32 value; + + if (!priv->regmap) + return -EOPNOTSUPP; + + /* disable the wake detection */ + value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEP_CFG); + value &= ~UHSIC_MASTER_ENABLE; + padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEP_CFG); + + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_LINE_WAKEUP); + value &= ~UHSIC_LINE_WAKEUP_EN; + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_LINE_WAKEUP); + + /* disable wake event triggers of sleepwalk logic */ + value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEP_CFG); + value &= ~UHSIC_WAKE_VAL(~0); + value |= UHSIC_WAKE_VAL_NONE; + padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEP_CFG); + + /* power down the line state detectors of the port */ + value = padctl_pmc_readl(priv, PMC_USB_AO); + value |= STROBE_VAL_PD | DATA0_VAL_PD | DATA1_VAL_PD; + padctl_pmc_writel(priv, value, PMC_USB_AO); + + /* clear alarm of the sleepwalk logic */ + value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_TRIGGERS); + value |= UHSIC_CLR_WAKE_ALARM; + padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_TRIGGERS); + + return 0; +} + static int tegra210_usb3_set_lfps_detect(struct tegra_xusb_padctl *padctl, unsigned int index, bool enable) { @@ -911,14 +1788,36 @@ static void tegra210_usb2_lane_remove(struct tegra_xusb_lane *lane) static const struct tegra_xusb_lane_ops tegra210_usb2_lane_ops = { .probe = tegra210_usb2_lane_probe, .remove = tegra210_usb2_lane_remove, + .enable_phy_sleepwalk = tegra210_pmc_utmi_enable_phy_sleepwalk, + .disable_phy_sleepwalk = tegra210_pmc_utmi_disable_phy_sleepwalk, + .enable_phy_wake = tegra210_utmi_enable_phy_wake, + .disable_phy_wake = tegra210_utmi_disable_phy_wake, + .remote_wake_detected = tegra210_utmi_phy_remote_wake_detected, }; static int tegra210_usb2_phy_init(struct phy *phy) { struct tegra_xusb_lane *lane = phy_get_drvdata(phy); struct tegra_xusb_padctl *padctl = lane->pad->padctl; + unsigned int index = lane->index; + struct tegra_xusb_usb2_port *port; + int err; u32 value; + port = tegra_xusb_find_usb2_port(padctl, index); + if (!port) { + dev_err(&phy->dev, "no port found for USB2 lane %u\n", index); + return -ENODEV; + } + + if (port->supply && port->mode == USB_DR_MODE_HOST) { + err = regulator_enable(port->supply); + if (err) + return err; + } + + mutex_lock(&padctl->lock); + value = padctl_readl(padctl, XUSB_PADCTL_USB2_PAD_MUX); value &= ~(XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_MASK << XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_SHIFT); @@ -926,14 +1825,31 @@ static int tegra210_usb2_phy_init(struct phy *phy) XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_SHIFT; padctl_writel(padctl, value, XUSB_PADCTL_USB2_PAD_MUX); - return tegra210_xusb_padctl_enable(padctl); + mutex_unlock(&padctl->lock); + + return 0; } static int tegra210_usb2_phy_exit(struct phy *phy) { struct tegra_xusb_lane *lane = phy_get_drvdata(phy); + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + struct tegra_xusb_usb2_port *port; + int err; - return tegra210_xusb_padctl_disable(lane->pad->padctl); + port = tegra_xusb_find_usb2_port(padctl, lane->index); + if (!port) { + dev_err(&phy->dev, "no port found for USB2 lane %u\n", lane->index); + return -ENODEV; + } + + if (port->supply && port->mode == USB_DR_MODE_HOST) { + err = regulator_disable(port->supply); + if (err) + return err; + } + + return 0; } static int tegra210_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl, @@ -1053,6 +1969,8 @@ static int tegra210_usb2_phy_power_on(struct phy *phy) priv = to_tegra210_xusb_padctl(padctl); + mutex_lock(&padctl->lock); + if (port->usb3_port_fake != -1) { value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK( @@ -1146,14 +2064,6 @@ static int tegra210_usb2_phy_power_on(struct phy *phy) padctl_writel(padctl, value, XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(index)); - if (port->supply && port->mode == USB_DR_MODE_HOST) { - err = regulator_enable(port->supply); - if (err) - return err; - } - - mutex_lock(&padctl->lock); - if (pad->enable > 0) { pad->enable++; mutex_unlock(&padctl->lock); @@ -1162,7 +2072,7 @@ static int tegra210_usb2_phy_power_on(struct phy *phy) err = clk_prepare_enable(pad->clk); if (err) - goto disable_regulator; + goto out; value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_MASK << @@ -1194,8 +2104,7 @@ static int tegra210_usb2_phy_power_on(struct phy *phy) return 0; -disable_regulator: - regulator_disable(port->supply); +out: mutex_unlock(&padctl->lock); return err; } @@ -1254,7 +2163,6 @@ static int tegra210_usb2_phy_power_off(struct phy *phy) padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); out: - regulator_disable(port->supply); mutex_unlock(&padctl->lock); return 0; } @@ -1376,6 +2284,11 @@ static void tegra210_hsic_lane_remove(struct tegra_xusb_lane *lane) static const struct tegra_xusb_lane_ops tegra210_hsic_lane_ops = { .probe = tegra210_hsic_lane_probe, .remove = tegra210_hsic_lane_remove, + .enable_phy_sleepwalk = tegra210_pmc_hsic_enable_phy_sleepwalk, + .disable_phy_sleepwalk = tegra210_pmc_hsic_disable_phy_sleepwalk, + .enable_phy_wake = tegra210_hsic_enable_phy_wake, + .disable_phy_wake = tegra210_hsic_disable_phy_wake, + .remote_wake_detected = tegra210_hsic_phy_remote_wake_detected, }; static int tegra210_hsic_phy_init(struct phy *phy) @@ -1391,14 +2304,12 @@ static int tegra210_hsic_phy_init(struct phy *phy) XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_SHIFT; padctl_writel(padctl, value, XUSB_PADCTL_USB2_PAD_MUX); - return tegra210_xusb_padctl_enable(padctl); + return 0; } static int tegra210_hsic_phy_exit(struct phy *phy) { - struct tegra_xusb_lane *lane = phy_get_drvdata(phy); - - return tegra210_xusb_padctl_disable(lane->pad->padctl); + return 0; } static int tegra210_hsic_phy_power_on(struct phy *phy) @@ -1582,6 +2493,55 @@ static const struct tegra_xusb_pad_soc tegra210_hsic_pad = { .ops = &tegra210_hsic_ops, }; +static void tegra210_uphy_lane_iddq_enable(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + u32 value; + + value = padctl_readl(padctl, lane->soc->regs.misc_ctl2); + value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ_OVRD; + value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ_OVRD; + value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_PWR_OVRD; + value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD; + value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ; + value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_MASK; + value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_VAL; + value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ; + value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_MASK; + value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL; + padctl_writel(padctl, value, lane->soc->regs.misc_ctl2); +} + +static void tegra210_uphy_lane_iddq_disable(struct tegra_xusb_lane *lane) +{ + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + u32 value; + + value = padctl_readl(padctl, lane->soc->regs.misc_ctl2); + value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ_OVRD; + value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ_OVRD; + value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_PWR_OVRD; + value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD; + value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ; + value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_MASK; + value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_VAL; + value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ; + value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_MASK; + value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL; + padctl_writel(padctl, value, lane->soc->regs.misc_ctl2); +} + +#define TEGRA210_UPHY_LANE(_name, _offset, _shift, _mask, _type, _misc) \ + { \ + .name = _name, \ + .offset = _offset, \ + .shift = _shift, \ + .mask = _mask, \ + .num_funcs = ARRAY_SIZE(tegra210_##_type##_functions), \ + .funcs = tegra210_##_type##_functions, \ + .regs.misc_ctl2 = _misc, \ + } + static const char *tegra210_pcie_functions[] = { "pcie-x1", "usb3-ss", @@ -1590,15 +2550,137 @@ static const char *tegra210_pcie_functions[] = { }; static const struct tegra_xusb_lane_soc tegra210_pcie_lanes[] = { - TEGRA210_LANE("pcie-0", 0x028, 12, 0x3, pcie), - TEGRA210_LANE("pcie-1", 0x028, 14, 0x3, pcie), - TEGRA210_LANE("pcie-2", 0x028, 16, 0x3, pcie), - TEGRA210_LANE("pcie-3", 0x028, 18, 0x3, pcie), - TEGRA210_LANE("pcie-4", 0x028, 20, 0x3, pcie), - TEGRA210_LANE("pcie-5", 0x028, 22, 0x3, pcie), - TEGRA210_LANE("pcie-6", 0x028, 24, 0x3, pcie), + TEGRA210_UPHY_LANE("pcie-0", 0x028, 12, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(0)), + TEGRA210_UPHY_LANE("pcie-1", 0x028, 14, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(1)), + TEGRA210_UPHY_LANE("pcie-2", 0x028, 16, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(2)), + TEGRA210_UPHY_LANE("pcie-3", 0x028, 18, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(3)), + TEGRA210_UPHY_LANE("pcie-4", 0x028, 20, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(4)), + TEGRA210_UPHY_LANE("pcie-5", 0x028, 22, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(5)), + TEGRA210_UPHY_LANE("pcie-6", 0x028, 24, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(6)), }; +static struct tegra_xusb_usb3_port * +tegra210_lane_to_usb3_port(struct tegra_xusb_lane *lane) +{ + int port; + + if (!lane || !lane->pad || !lane->pad->padctl) + return NULL; + + port = tegra210_usb3_lane_map(lane); + if (port < 0) + return NULL; + + return tegra_xusb_find_usb3_port(lane->pad->padctl, port); +} + +static int tegra210_usb3_phy_power_on(struct phy *phy) +{ + struct device *dev = &phy->dev; + struct tegra_xusb_lane *lane = phy_get_drvdata(phy); + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + struct tegra_xusb_usb3_port *usb3 = tegra210_lane_to_usb3_port(lane); + unsigned int index; + u32 value; + + if (!usb3) { + dev_err(dev, "no USB3 port found for lane %u\n", lane->index); + return -ENODEV; + } + + index = usb3->base.index; + + value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); + + if (!usb3->internal) + value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index); + else + value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index); + + value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(index); + value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(index, usb3->port); + padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); + + value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(index)); + value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_MASK << + XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT); + value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_VAL << + XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT; + padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(index)); + + value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL2(index)); + value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_MASK << + XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_SHIFT); + value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_VAL << + XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_SHIFT; + padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL2(index)); + + padctl_writel(padctl, XUSB_PADCTL_UPHY_USB3_PAD_ECTL3_RX_DFE_VAL, + XUSB_PADCTL_UPHY_USB3_PADX_ECTL3(index)); + + value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL4(index)); + value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_MASK << + XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_SHIFT); + value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_VAL << + XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_SHIFT; + padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL4(index)); + + padctl_writel(padctl, XUSB_PADCTL_UPHY_USB3_PAD_ECTL6_RX_EQ_CTRL_H_VAL, + XUSB_PADCTL_UPHY_USB3_PADX_ECTL6(index)); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); + value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); + + usleep_range(100, 200); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); + value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); + + usleep_range(100, 200); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); + value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); + + return 0; +} + +static int tegra210_usb3_phy_power_off(struct phy *phy) +{ + struct device *dev = &phy->dev; + struct tegra_xusb_lane *lane = phy_get_drvdata(phy); + struct tegra_xusb_padctl *padctl = lane->pad->padctl; + struct tegra_xusb_usb3_port *usb3 = tegra210_lane_to_usb3_port(lane); + unsigned int index; + u32 value; + + if (!usb3) { + dev_err(dev, "no USB3 port found for lane %u\n", lane->index); + return -ENODEV; + } + + index = usb3->base.index; + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); + value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); + + usleep_range(100, 200); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); + value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); + + usleep_range(250, 350); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); + value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(index); + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); + + return 0; +} static struct tegra_xusb_lane * tegra210_pcie_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, unsigned int index) @@ -1635,40 +2717,40 @@ static void tegra210_pcie_lane_remove(struct tegra_xusb_lane *lane) static const struct tegra_xusb_lane_ops tegra210_pcie_lane_ops = { .probe = tegra210_pcie_lane_probe, .remove = tegra210_pcie_lane_remove, + .iddq_enable = tegra210_uphy_lane_iddq_enable, + .iddq_disable = tegra210_uphy_lane_iddq_disable, + .enable_phy_sleepwalk = tegra210_usb3_enable_phy_sleepwalk, + .disable_phy_sleepwalk = tegra210_usb3_disable_phy_sleepwalk, + .enable_phy_wake = tegra210_usb3_enable_phy_wake, + .disable_phy_wake = tegra210_usb3_disable_phy_wake, + .remote_wake_detected = tegra210_usb3_phy_remote_wake_detected, }; static int tegra210_pcie_phy_init(struct phy *phy) { struct tegra_xusb_lane *lane = phy_get_drvdata(phy); + struct tegra_xusb_padctl *padctl = lane->pad->padctl; - return tegra210_xusb_padctl_enable(lane->pad->padctl); -} + mutex_lock(&padctl->lock); -static int tegra210_pcie_phy_exit(struct phy *phy) -{ - struct tegra_xusb_lane *lane = phy_get_drvdata(phy); + tegra210_uphy_init(padctl); + + mutex_unlock(&padctl->lock); - return tegra210_xusb_padctl_disable(lane->pad->padctl); + return 0; } static int tegra210_pcie_phy_power_on(struct phy *phy) { struct tegra_xusb_lane *lane = phy_get_drvdata(phy); struct tegra_xusb_padctl *padctl = lane->pad->padctl; - u32 value; - int err; + int err = 0; mutex_lock(&padctl->lock); - err = tegra210_pex_uphy_enable(padctl); - if (err < 0) - goto unlock; - - value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); - value |= XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index); - padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); + if (tegra_xusb_lane_check(lane, "usb3-ss")) + err = tegra210_usb3_phy_power_on(phy); -unlock: mutex_unlock(&padctl->lock); return err; } @@ -1677,20 +2759,19 @@ static int tegra210_pcie_phy_power_off(struct phy *phy) { struct tegra_xusb_lane *lane = phy_get_drvdata(phy); struct tegra_xusb_padctl *padctl = lane->pad->padctl; - u32 value; + int err = 0; - value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); - value &= ~XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index); - padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); + mutex_lock(&padctl->lock); - tegra210_pex_uphy_disable(padctl); + if (tegra_xusb_lane_check(lane, "usb3-ss")) + err = tegra210_usb3_phy_power_off(phy); - return 0; + mutex_unlock(&padctl->lock); + return err; } static const struct phy_ops tegra210_pcie_phy_ops = { .init = tegra210_pcie_phy_init, - .exit = tegra210_pcie_phy_exit, .power_on = tegra210_pcie_phy_power_on, .power_off = tegra210_pcie_phy_power_off, .owner = THIS_MODULE, @@ -1767,7 +2848,7 @@ static const struct tegra_xusb_pad_soc tegra210_pcie_pad = { }; static const struct tegra_xusb_lane_soc tegra210_sata_lanes[] = { - TEGRA210_LANE("sata-0", 0x028, 30, 0x3, pcie), + TEGRA210_UPHY_LANE("sata-0", 0x028, 30, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL2), }; static struct tegra_xusb_lane * @@ -1806,40 +2887,39 @@ static void tegra210_sata_lane_remove(struct tegra_xusb_lane *lane) static const struct tegra_xusb_lane_ops tegra210_sata_lane_ops = { .probe = tegra210_sata_lane_probe, .remove = tegra210_sata_lane_remove, + .iddq_enable = tegra210_uphy_lane_iddq_enable, + .iddq_disable = tegra210_uphy_lane_iddq_disable, + .enable_phy_sleepwalk = tegra210_usb3_enable_phy_sleepwalk, + .disable_phy_sleepwalk = tegra210_usb3_disable_phy_sleepwalk, + .enable_phy_wake = tegra210_usb3_enable_phy_wake, + .disable_phy_wake = tegra210_usb3_disable_phy_wake, + .remote_wake_detected = tegra210_usb3_phy_remote_wake_detected, }; static int tegra210_sata_phy_init(struct phy *phy) { struct tegra_xusb_lane *lane = phy_get_drvdata(phy); + struct tegra_xusb_padctl *padctl = lane->pad->padctl; - return tegra210_xusb_padctl_enable(lane->pad->padctl); -} + mutex_lock(&padctl->lock); -static int tegra210_sata_phy_exit(struct phy *phy) -{ - struct tegra_xusb_lane *lane = phy_get_drvdata(phy); + tegra210_uphy_init(padctl); - return tegra210_xusb_padctl_disable(lane->pad->padctl); + mutex_unlock(&padctl->lock); + return 0; } static int tegra210_sata_phy_power_on(struct phy *phy) { struct tegra_xusb_lane *lane = phy_get_drvdata(phy); struct tegra_xusb_padctl *padctl = lane->pad->padctl; - u32 value; - int err; + int err = 0; mutex_lock(&padctl->lock); - err = tegra210_sata_uphy_enable(padctl, false); - if (err < 0) - goto unlock; - - value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); - value |= XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index); - padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); + if (tegra_xusb_lane_check(lane, "usb3-ss")) + err = tegra210_usb3_phy_power_on(phy); -unlock: mutex_unlock(&padctl->lock); return err; } @@ -1848,20 +2928,19 @@ static int tegra210_sata_phy_power_off(struct phy *phy) { struct tegra_xusb_lane *lane = phy_get_drvdata(phy); struct tegra_xusb_padctl *padctl = lane->pad->padctl; - u32 value; + int err = 0; - value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); - value &= ~XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index); - padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); + mutex_lock(&padctl->lock); - tegra210_sata_uphy_disable(lane->pad->padctl); + if (tegra_xusb_lane_check(lane, "usb3-ss")) + err = tegra210_usb3_phy_power_off(phy); - return 0; + mutex_unlock(&padctl->lock); + return err; } static const struct phy_ops tegra210_sata_phy_ops = { .init = tegra210_sata_phy_init, - .exit = tegra210_sata_phy_exit, .power_on = tegra210_sata_phy_power_on, .power_off = tegra210_sata_phy_power_off, .owner = THIS_MODULE, @@ -1984,137 +3063,13 @@ static const struct tegra_xusb_port_ops tegra210_hsic_port_ops = { static int tegra210_usb3_port_enable(struct tegra_xusb_port *port) { - struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port); - struct tegra_xusb_padctl *padctl = port->padctl; - struct tegra_xusb_lane *lane = usb3->base.lane; - unsigned int index = port->index; - u32 value; - int err; - - value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); - - if (!usb3->internal) - value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index); - else - value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index); - - value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(index); - value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(index, usb3->port); - padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); - - /* - * TODO: move this code into the PCIe/SATA PHY ->power_on() callbacks - * and conditionalize based on mux function? This seems to work, but - * might not be the exact proper sequence. - */ - err = regulator_enable(usb3->supply); - if (err < 0) - return err; - - value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(index)); - value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_MASK << - XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT); - value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_VAL << - XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT; - padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(index)); - - value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL2(index)); - value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_MASK << - XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_SHIFT); - value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_VAL << - XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_SHIFT; - padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL2(index)); - - padctl_writel(padctl, XUSB_PADCTL_UPHY_USB3_PAD_ECTL3_RX_DFE_VAL, - XUSB_PADCTL_UPHY_USB3_PADX_ECTL3(index)); - - value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL4(index)); - value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_MASK << - XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_SHIFT); - value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_VAL << - XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_SHIFT; - padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL4(index)); - - padctl_writel(padctl, XUSB_PADCTL_UPHY_USB3_PAD_ECTL6_RX_EQ_CTRL_H_VAL, - XUSB_PADCTL_UPHY_USB3_PADX_ECTL6(index)); - - if (lane->pad == padctl->sata) - err = tegra210_sata_uphy_enable(padctl, true); - else - err = tegra210_pex_uphy_enable(padctl); - - if (err) { - dev_err(&port->dev, "%s: failed to enable UPHY: %d\n", - __func__, err); - return err; - } - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); - value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(index); - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); - - usleep_range(100, 200); - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); - value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(index); - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); - - usleep_range(100, 200); - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); - value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(index); - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); - return 0; } static void tegra210_usb3_port_disable(struct tegra_xusb_port *port) { - struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port); - struct tegra_xusb_padctl *padctl = port->padctl; - struct tegra_xusb_lane *lane = port->lane; - unsigned int index = port->index; - u32 value; - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); - value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(index); - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); - - usleep_range(100, 200); - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); - value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(index); - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); - - usleep_range(250, 350); - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); - value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(index); - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); - - if (lane->pad == padctl->sata) - tegra210_sata_uphy_disable(padctl); - else - tegra210_pex_uphy_disable(padctl); - - regulator_disable(usb3->supply); - - value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); - value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(index); - value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(index, 0x7); - padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); } -static const struct tegra_xusb_lane_map tegra210_usb3_map[] = { - { 0, "pcie", 6 }, - { 1, "pcie", 5 }, - { 2, "pcie", 0 }, - { 2, "pcie", 3 }, - { 3, "pcie", 4 }, - { 3, "pcie", 4 }, - { 0, NULL, 0 } -}; - static struct tegra_xusb_lane * tegra210_usb3_port_map(struct tegra_xusb_port *port) { @@ -2188,6 +3143,8 @@ tegra210_xusb_padctl_probe(struct device *dev, const struct tegra_xusb_padctl_soc *soc) { struct tegra210_xusb_padctl *padctl; + struct platform_device *pdev; + struct device_node *np; int err; padctl = devm_kzalloc(dev, sizeof(*padctl), GFP_KERNEL); @@ -2201,6 +3158,26 @@ tegra210_xusb_padctl_probe(struct device *dev, if (err < 0) return ERR_PTR(err); + np = of_parse_phandle(dev->of_node, "nvidia,pmc", 0); + if (!np) { + dev_warn(dev, "nvidia,pmc property is missing\n"); + goto out; + } + + pdev = of_find_device_by_node(np); + if (!pdev) { + dev_warn(dev, "PMC device is not available\n"); + goto out; + } + + if (!platform_get_drvdata(pdev)) + return ERR_PTR(-EPROBE_DEFER); + + padctl->regmap = dev_get_regmap(&pdev->dev, "usb_sleepwalk"); + if (!padctl->regmap) + dev_info(dev, "failed to find PMC regmap\n"); + +out: return &padctl->base; } @@ -2208,9 +3185,75 @@ static void tegra210_xusb_padctl_remove(struct tegra_xusb_padctl *padctl) { } +static void tegra210_xusb_padctl_save(struct tegra_xusb_padctl *padctl) +{ + struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl); + + priv->context.usb2_pad_mux = + padctl_readl(padctl, XUSB_PADCTL_USB2_PAD_MUX); + priv->context.usb2_port_cap = + padctl_readl(padctl, XUSB_PADCTL_USB2_PORT_CAP); + priv->context.ss_port_map = + padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); + priv->context.usb3_pad_mux = + padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); +} + +static void tegra210_xusb_padctl_restore(struct tegra_xusb_padctl *padctl) +{ + struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl); + struct tegra_xusb_lane *lane; + + padctl_writel(padctl, priv->context.usb2_pad_mux, + XUSB_PADCTL_USB2_PAD_MUX); + padctl_writel(padctl, priv->context.usb2_port_cap, + XUSB_PADCTL_USB2_PORT_CAP); + padctl_writel(padctl, priv->context.ss_port_map, + XUSB_PADCTL_SS_PORT_MAP); + + list_for_each_entry(lane, &padctl->lanes, list) { + if (lane->pad->ops->iddq_enable) + tegra210_uphy_lane_iddq_enable(lane); + } + + padctl_writel(padctl, priv->context.usb3_pad_mux, + XUSB_PADCTL_USB3_PAD_MUX); + + list_for_each_entry(lane, &padctl->lanes, list) { + if (lane->pad->ops->iddq_disable) + tegra210_uphy_lane_iddq_disable(lane); + } +} + +static int tegra210_xusb_padctl_suspend_noirq(struct tegra_xusb_padctl *padctl) +{ + mutex_lock(&padctl->lock); + + tegra210_uphy_deinit(padctl); + + tegra210_xusb_padctl_save(padctl); + + mutex_unlock(&padctl->lock); + return 0; +} + +static int tegra210_xusb_padctl_resume_noirq(struct tegra_xusb_padctl *padctl) +{ + mutex_lock(&padctl->lock); + + tegra210_xusb_padctl_restore(padctl); + + tegra210_uphy_init(padctl); + + mutex_unlock(&padctl->lock); + return 0; +} + static const struct tegra_xusb_padctl_ops tegra210_xusb_padctl_ops = { .probe = tegra210_xusb_padctl_probe, .remove = tegra210_xusb_padctl_remove, + .suspend_noirq = tegra210_xusb_padctl_suspend_noirq, + .resume_noirq = tegra210_xusb_padctl_resume_noirq, .usb3_set_lfps_detect = tegra210_usb3_set_lfps_detect, .hsic_set_idle = tegra210_hsic_set_idle, .vbus_override = tegra210_xusb_padctl_vbus_override, diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c index 941006f503e4..0aadac678191 100644 --- a/drivers/phy/tegra/xusb.c +++ b/drivers/phy/tegra/xusb.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2020, NVIDIA CORPORATION. All rights reserved. */ #include <linux/delay.h> @@ -321,11 +321,17 @@ static void tegra_xusb_lane_program(struct tegra_xusb_lane *lane) if (soc->num_funcs < 2) return; + if (lane->pad->ops->iddq_enable) + lane->pad->ops->iddq_enable(lane); + /* choose function */ value = padctl_readl(padctl, soc->offset); value &= ~(soc->mask << soc->shift); value |= lane->function << soc->shift; padctl_writel(padctl, value, soc->offset); + + if (lane->pad->ops->iddq_disable) + lane->pad->ops->iddq_disable(lane); } static void tegra_xusb_pad_program(struct tegra_xusb_pad *pad) @@ -376,7 +382,7 @@ static int tegra_xusb_setup_pads(struct tegra_xusb_padctl *padctl) return 0; } -static bool tegra_xusb_lane_check(struct tegra_xusb_lane *lane, +bool tegra_xusb_lane_check(struct tegra_xusb_lane *lane, const char *function) { const char *func = lane->soc->funcs[lane->function]; @@ -1267,10 +1273,36 @@ static int tegra_xusb_padctl_remove(struct platform_device *pdev) return err; } +static int tegra_xusb_padctl_suspend_noirq(struct device *dev) +{ + struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev); + + if (padctl->soc && padctl->soc->ops && padctl->soc->ops->suspend_noirq) + return padctl->soc->ops->suspend_noirq(padctl); + + return 0; +} + +static int tegra_xusb_padctl_resume_noirq(struct device *dev) +{ + struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev); + + if (padctl->soc && padctl->soc->ops && padctl->soc->ops->resume_noirq) + return padctl->soc->ops->resume_noirq(padctl); + + return 0; +} + +static const struct dev_pm_ops tegra_xusb_padctl_pm_ops = { + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(tegra_xusb_padctl_suspend_noirq, + tegra_xusb_padctl_resume_noirq) +}; + static struct platform_driver tegra_xusb_padctl_driver = { .driver = { .name = "tegra-xusb-padctl", .of_match_table = tegra_xusb_padctl_of_match, + .pm = &tegra_xusb_padctl_pm_ops, }, .probe = tegra_xusb_padctl_probe, .remove = tegra_xusb_padctl_remove, @@ -1337,6 +1369,62 @@ int tegra_xusb_padctl_hsic_set_idle(struct tegra_xusb_padctl *padctl, } EXPORT_SYMBOL_GPL(tegra_xusb_padctl_hsic_set_idle); +int tegra_xusb_padctl_enable_phy_sleepwalk(struct tegra_xusb_padctl *padctl, struct phy *phy, + enum usb_device_speed speed) +{ + struct tegra_xusb_lane *lane = phy_get_drvdata(phy); + + if (lane->pad->ops->enable_phy_sleepwalk) + return lane->pad->ops->enable_phy_sleepwalk(lane, speed); + + return -EOPNOTSUPP; +} +EXPORT_SYMBOL_GPL(tegra_xusb_padctl_enable_phy_sleepwalk); + +int tegra_xusb_padctl_disable_phy_sleepwalk(struct tegra_xusb_padctl *padctl, struct phy *phy) +{ + struct tegra_xusb_lane *lane = phy_get_drvdata(phy); + + if (lane->pad->ops->disable_phy_sleepwalk) + return lane->pad->ops->disable_phy_sleepwalk(lane); + + return -EOPNOTSUPP; +} +EXPORT_SYMBOL_GPL(tegra_xusb_padctl_disable_phy_sleepwalk); + +int tegra_xusb_padctl_enable_phy_wake(struct tegra_xusb_padctl *padctl, struct phy *phy) +{ + struct tegra_xusb_lane *lane = phy_get_drvdata(phy); + + if (lane->pad->ops->enable_phy_wake) + return lane->pad->ops->enable_phy_wake(lane); + + return -EOPNOTSUPP; +} +EXPORT_SYMBOL_GPL(tegra_xusb_padctl_enable_phy_wake); + +int tegra_xusb_padctl_disable_phy_wake(struct tegra_xusb_padctl *padctl, struct phy *phy) +{ + struct tegra_xusb_lane *lane = phy_get_drvdata(phy); + + if (lane->pad->ops->disable_phy_wake) + return lane->pad->ops->disable_phy_wake(lane); + + return -EOPNOTSUPP; +} +EXPORT_SYMBOL_GPL(tegra_xusb_padctl_disable_phy_wake); + +bool tegra_xusb_padctl_remote_wake_detected(struct tegra_xusb_padctl *padctl, struct phy *phy) +{ + struct tegra_xusb_lane *lane = phy_get_drvdata(phy); + + if (lane->pad->ops->remote_wake_detected) + return lane->pad->ops->remote_wake_detected(lane); + + return false; +} +EXPORT_SYMBOL_GPL(tegra_xusb_padctl_remote_wake_detected); + int tegra_xusb_padctl_usb3_set_lfps_detect(struct tegra_xusb_padctl *padctl, unsigned int port, bool enable) { diff --git a/drivers/phy/tegra/xusb.h b/drivers/phy/tegra/xusb.h index ea35af747066..034f7a2c28d6 100644 --- a/drivers/phy/tegra/xusb.h +++ b/drivers/phy/tegra/xusb.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2020, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2015, Google Inc. */ @@ -11,6 +11,7 @@ #include <linux/mutex.h> #include <linux/workqueue.h> +#include <linux/usb/ch9.h> #include <linux/usb/otg.h> #include <linux/usb/role.h> @@ -35,6 +36,10 @@ struct tegra_xusb_lane_soc { const char * const *funcs; unsigned int num_funcs; + + struct { + unsigned int misc_ctl2; + } regs; }; struct tegra_xusb_lane { @@ -126,8 +131,17 @@ struct tegra_xusb_lane_ops { struct device_node *np, unsigned int index); void (*remove)(struct tegra_xusb_lane *lane); + void (*iddq_enable)(struct tegra_xusb_lane *lane); + void (*iddq_disable)(struct tegra_xusb_lane *lane); + int (*enable_phy_sleepwalk)(struct tegra_xusb_lane *lane, enum usb_device_speed speed); + int (*disable_phy_sleepwalk)(struct tegra_xusb_lane *lane); + int (*enable_phy_wake)(struct tegra_xusb_lane *lane); + int (*disable_phy_wake)(struct tegra_xusb_lane *lane); + bool (*remote_wake_detected)(struct tegra_xusb_lane *lane); }; +bool tegra_xusb_lane_check(struct tegra_xusb_lane *lane, const char *function); + /* * pads */ @@ -230,7 +244,7 @@ struct tegra_xusb_pcie_pad { struct reset_control *rst; struct clk *pll; - unsigned int enable; + bool enable; }; static inline struct tegra_xusb_pcie_pad * @@ -245,7 +259,7 @@ struct tegra_xusb_sata_pad { struct reset_control *rst; struct clk *pll; - unsigned int enable; + bool enable; }; static inline struct tegra_xusb_sata_pad * @@ -388,6 +402,8 @@ struct tegra_xusb_padctl_ops { const struct tegra_xusb_padctl_soc *soc); void (*remove)(struct tegra_xusb_padctl *padctl); + int (*suspend_noirq)(struct tegra_xusb_padctl *padctl); + int (*resume_noirq)(struct tegra_xusb_padctl *padctl); int (*usb3_save_context)(struct tegra_xusb_padctl *padctl, unsigned int index); int (*hsic_set_idle)(struct tegra_xusb_padctl *padctl, diff --git a/drivers/phy/ti/phy-dm816x-usb.c b/drivers/phy/ti/phy-dm816x-usb.c index 57adc08a89b2..9fe6ea6fdae5 100644 --- a/drivers/phy/ti/phy-dm816x-usb.c +++ b/drivers/phy/ti/phy-dm816x-usb.c @@ -242,19 +242,28 @@ static int dm816x_usb_phy_probe(struct platform_device *pdev) pm_runtime_enable(phy->dev); generic_phy = devm_phy_create(phy->dev, NULL, &ops); - if (IS_ERR(generic_phy)) - return PTR_ERR(generic_phy); + if (IS_ERR(generic_phy)) { + error = PTR_ERR(generic_phy); + goto clk_unprepare; + } phy_set_drvdata(generic_phy, phy); phy_provider = devm_of_phy_provider_register(phy->dev, of_phy_simple_xlate); - if (IS_ERR(phy_provider)) - return PTR_ERR(phy_provider); + if (IS_ERR(phy_provider)) { + error = PTR_ERR(phy_provider); + goto clk_unprepare; + } usb_add_phy_dev(&phy->phy); return 0; + +clk_unprepare: + pm_runtime_disable(phy->dev); + clk_unprepare(phy->refclk); + return error; } static int dm816x_usb_phy_remove(struct platform_device *pdev) diff --git a/drivers/phy/ti/phy-twl4030-usb.c b/drivers/phy/ti/phy-twl4030-usb.c index 812e5409d359..5771e2486a3b 100644 --- a/drivers/phy/ti/phy-twl4030-usb.c +++ b/drivers/phy/ti/phy-twl4030-usb.c @@ -544,8 +544,8 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl) return 0; } -static ssize_t twl4030_usb_vbus_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t vbus_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct twl4030_usb *twl = dev_get_drvdata(dev); int ret = -EINVAL; @@ -557,7 +557,7 @@ static ssize_t twl4030_usb_vbus_show(struct device *dev, return ret; } -static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL); +static DEVICE_ATTR_RO(vbus); static irqreturn_t twl4030_usb_irq(int irq, void *_twl) { diff --git a/drivers/platform/x86/dell/dell_rbu.c b/drivers/platform/x86/dell/dell_rbu.c index 085ad0a0d22e..e9f4b30dcafa 100644 --- a/drivers/platform/x86/dell/dell_rbu.c +++ b/drivers/platform/x86/dell/dell_rbu.c @@ -573,7 +573,7 @@ static ssize_t image_type_write(struct file *filp, struct kobject *kobj, if (!rbu_data.entry_created) { spin_unlock(&rbu_data.lock); req_firm_rc = request_firmware_nowait(THIS_MODULE, - FW_ACTION_NOHOTPLUG, "dell_rbu", + FW_ACTION_NOUEVENT, "dell_rbu", &rbu_device->dev, GFP_KERNEL, &context, callbackfn_rbu); if (req_firm_rc) { diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index d40ed8621571..9610a9f08ff4 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c @@ -369,6 +369,7 @@ err_out: dev->card_link = NULL; return NULL; } +EXPORT_SYMBOL(pnp_request_card_device); /** * pnp_release_card_device - call this when the driver no longer needs the device @@ -382,6 +383,7 @@ void pnp_release_card_device(struct pnp_dev *dev) device_release_driver(&dev->dev); drv->link.remove = &card_remove_first; } +EXPORT_SYMBOL(pnp_release_card_device); /* * suspend/resume callbacks @@ -439,6 +441,7 @@ int pnp_register_card_driver(struct pnp_card_driver *drv) } return 0; } +EXPORT_SYMBOL(pnp_register_card_driver); /** * pnp_unregister_card_driver - unregisters a PnP card driver from the PnP Layer @@ -451,8 +454,4 @@ void pnp_unregister_card_driver(struct pnp_card_driver *drv) mutex_unlock(&pnp_lock); pnp_unregister_driver(&drv->link); } - -EXPORT_SYMBOL(pnp_request_card_device); -EXPORT_SYMBOL(pnp_release_card_device); -EXPORT_SYMBOL(pnp_register_card_driver); EXPORT_SYMBOL(pnp_unregister_card_driver); diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index 93a30a8f88d1..c29d590c5e4f 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c @@ -68,6 +68,7 @@ int pnp_device_attach(struct pnp_dev *pnp_dev) mutex_unlock(&pnp_lock); return 0; } +EXPORT_SYMBOL(pnp_device_attach); void pnp_device_detach(struct pnp_dev *pnp_dev) { @@ -76,6 +77,7 @@ void pnp_device_detach(struct pnp_dev *pnp_dev) pnp_dev->status = PNP_READY; mutex_unlock(&pnp_lock); } +EXPORT_SYMBOL(pnp_device_detach); static int pnp_device_probe(struct device *dev) { @@ -271,11 +273,13 @@ int pnp_register_driver(struct pnp_driver *drv) return driver_register(&drv->driver); } +EXPORT_SYMBOL(pnp_register_driver); void pnp_unregister_driver(struct pnp_driver *drv) { driver_unregister(&drv->driver); } +EXPORT_SYMBOL(pnp_unregister_driver); /** * pnp_add_id - adds an EISA id to the specified device @@ -310,8 +314,3 @@ struct pnp_id *pnp_add_id(struct pnp_dev *dev, const char *id) return dev_id; } - -EXPORT_SYMBOL(pnp_register_driver); -EXPORT_SYMBOL(pnp_unregister_driver); -EXPORT_SYMBOL(pnp_device_attach); -EXPORT_SYMBOL(pnp_device_detach); diff --git a/drivers/pnp/isapnp/compat.c b/drivers/pnp/isapnp/compat.c index 035e95092489..d60d9e377da5 100644 --- a/drivers/pnp/isapnp/compat.c +++ b/drivers/pnp/isapnp/compat.c @@ -63,5 +63,4 @@ struct pnp_dev *pnp_find_dev(struct pnp_card *card, unsigned short vendor, } return NULL; } - EXPORT_SYMBOL(pnp_find_dev); diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index 144055593ec8..1765d6e60a8a 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -350,6 +350,7 @@ int pnp_start_dev(struct pnp_dev *dev) dev_info(&dev->dev, "activated\n"); return 0; } +EXPORT_SYMBOL(pnp_start_dev); /** * pnp_stop_dev - low-level disable of the PnP device @@ -371,6 +372,7 @@ int pnp_stop_dev(struct pnp_dev *dev) dev_info(&dev->dev, "disabled\n"); return 0; } +EXPORT_SYMBOL(pnp_stop_dev); /** * pnp_activate_dev - activates a PnP device for use @@ -396,6 +398,7 @@ int pnp_activate_dev(struct pnp_dev *dev) dev->active = 1; return 0; } +EXPORT_SYMBOL(pnp_activate_dev); /** * pnp_disable_dev - disables device @@ -423,8 +426,4 @@ int pnp_disable_dev(struct pnp_dev *dev) return 0; } - -EXPORT_SYMBOL(pnp_start_dev); -EXPORT_SYMBOL(pnp_stop_dev); -EXPORT_SYMBOL(pnp_activate_dev); EXPORT_SYMBOL(pnp_disable_dev); diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c index e4f53d31191d..a6073db10ec6 100644 --- a/drivers/pnp/support.c +++ b/drivers/pnp/support.c @@ -30,7 +30,6 @@ int pnp_is_active(struct pnp_dev *dev) else return 1; } - EXPORT_SYMBOL(pnp_is_active); /* diff --git a/drivers/power/reset/at91-sama5d2_shdwc.c b/drivers/power/reset/at91-sama5d2_shdwc.c index 125e592af445..d8ecffe72f16 100644 --- a/drivers/power/reset/at91-sama5d2_shdwc.c +++ b/drivers/power/reset/at91-sama5d2_shdwc.c @@ -351,10 +351,8 @@ static int __init at91_shdwc_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); at91_shdwc->shdwc_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(at91_shdwc->shdwc_base)) { - dev_err(&pdev->dev, "Could not map reset controller address\n"); + if (IS_ERR(at91_shdwc->shdwc_base)) return PTR_ERR(at91_shdwc->shdwc_base); - } match = of_match_node(at91_shdwc_of_match, pdev->dev.of_node); at91_shdwc->rcfg = match->data; diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c index c5067eb75370..1c5af2fef142 100644 --- a/drivers/power/reset/gpio-poweroff.c +++ b/drivers/power/reset/gpio-poweroff.c @@ -90,6 +90,7 @@ static const struct of_device_id of_gpio_poweroff_match[] = { { .compatible = "gpio-poweroff", }, {}, }; +MODULE_DEVICE_TABLE(of, of_gpio_poweroff_match); static struct platform_driver gpio_poweroff_driver = { .probe = gpio_poweroff_probe, diff --git a/drivers/power/reset/keystone-reset.c b/drivers/power/reset/keystone-reset.c index 211eeef0c81a..c720112db704 100644 --- a/drivers/power/reset/keystone-reset.c +++ b/drivers/power/reset/keystone-reset.c @@ -71,6 +71,7 @@ static const struct of_device_id rsctrl_of_match[] = { {.compatible = "ti,keystone-reset", }, {}, }; +MODULE_DEVICE_TABLE(of, rsctrl_of_match); static int rsctrl_probe(struct platform_device *pdev) { diff --git a/drivers/power/reset/regulator-poweroff.c b/drivers/power/reset/regulator-poweroff.c index f697088e0ad1..20701203935f 100644 --- a/drivers/power/reset/regulator-poweroff.c +++ b/drivers/power/reset/regulator-poweroff.c @@ -64,6 +64,7 @@ static const struct of_device_id of_regulator_poweroff_match[] = { { .compatible = "regulator-poweroff", }, {}, }; +MODULE_DEVICE_TABLE(of, of_regulator_poweroff_match); static struct platform_driver regulator_poweroff_driver = { .probe = regulator_poweroff_probe, diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index e696364126f1..11f5368e810e 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -712,7 +712,8 @@ config BATTERY_GOLDFISH config BATTERY_RT5033 tristate "RT5033 fuel gauge support" - depends on MFD_RT5033 + depends on I2C + select REGMAP_I2C help This adds support for battery fuel gauge in Richtek RT5033 PMIC. The fuelgauge calculates and determines the battery state of charge @@ -760,15 +761,6 @@ config CHARGER_UCS1002 Say Y to enable support for Microchip UCS1002 Programmable USB Port Power Controller with Charger Emulation. -config CHARGER_BD70528 - tristate "ROHM bd70528 charger driver" - depends on MFD_ROHM_BD70528 - select LINEAR_RANGES - help - Say Y here to enable support for getting battery status - information and altering charger configurations from charger - block of the ROHM BD70528 Power Management IC. - config CHARGER_BD99954 tristate "ROHM bd99954 charger driver" depends on I2C diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index a7309a3d1a47..33059a91f60c 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile @@ -60,7 +60,7 @@ obj-$(CONFIG_BATTERY_TWL4030_MADC) += twl4030_madc_battery.o obj-$(CONFIG_CHARGER_88PM860X) += 88pm860x_charger.o obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o obj-$(CONFIG_BATTERY_RX51) += rx51_battery.o -obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o abx500_chargalg.o pm2301_charger.o +obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o abx500_chargalg.o obj-$(CONFIG_CHARGER_CPCAP) += cpcap-charger.o obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o @@ -96,7 +96,6 @@ obj-$(CONFIG_CHARGER_CROS_USBPD) += cros_usbpd-charger.o obj-$(CONFIG_CHARGER_SC2731) += sc2731_charger.o obj-$(CONFIG_FUEL_GAUGE_SC27XX) += sc27xx_fuel_gauge.o obj-$(CONFIG_CHARGER_UCS1002) += ucs1002_power.o -obj-$(CONFIG_CHARGER_BD70528) += bd70528-charger.o obj-$(CONFIG_CHARGER_BD99954) += bd99954-charger.o obj-$(CONFIG_CHARGER_WILCO) += wilco-charger.o obj-$(CONFIG_RN5T618_POWER) += rn5t618_power.o diff --git a/drivers/power/supply/ab8500-bm.h b/drivers/power/supply/ab8500-bm.h index 41c69a4f2a1f..0c940571e5b0 100644 --- a/drivers/power/supply/ab8500-bm.h +++ b/drivers/power/supply/ab8500-bm.h @@ -506,9 +506,6 @@ struct abx500_bm_data { int usb_safety_tmr_h; int bkup_bat_v; int bkup_bat_i; - bool autopower_cfg; - bool ac_enabled; - bool usb_enabled; bool no_maintenance; bool capacity_scaling; bool chg_unknown_bat; @@ -730,4 +727,8 @@ int ab8500_bm_of_probe(struct device *dev, struct device_node *np, struct abx500_bm_data *bm); +extern struct platform_driver ab8500_fg_driver; +extern struct platform_driver ab8500_btemp_driver; +extern struct platform_driver abx500_chargalg_driver; + #endif /* _AB8500_CHARGER_H_ */ diff --git a/drivers/power/supply/ab8500-chargalg.h b/drivers/power/supply/ab8500-chargalg.h index 94a6f9068bc5..07e6ff50084f 100644 --- a/drivers/power/supply/ab8500-chargalg.h +++ b/drivers/power/supply/ab8500-chargalg.h @@ -15,7 +15,7 @@ * - POWER_SUPPLY_TYPE_USB, * because only them store as drv_data pointer to struct ux500_charger. */ -#define psy_to_ux500_charger(x) power_supply_get_drvdata(psy) +#define psy_to_ux500_charger(x) power_supply_get_drvdata(x) /* Forward declaration */ struct ux500_charger; diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c index fdfcd59fc43e..dbdcff32f353 100644 --- a/drivers/power/supply/ab8500_btemp.c +++ b/drivers/power/supply/ab8500_btemp.c @@ -13,6 +13,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/device.h> +#include <linux/component.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/slab.h> @@ -932,26 +933,6 @@ static int __maybe_unused ab8500_btemp_suspend(struct device *dev) return 0; } -static int ab8500_btemp_remove(struct platform_device *pdev) -{ - struct ab8500_btemp *di = platform_get_drvdata(pdev); - int i, irq; - - /* Disable interrupts */ - for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) { - irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name); - free_irq(irq, di); - } - - /* Delete the work queue */ - destroy_workqueue(di->btemp_wq); - - flush_scheduled_work(); - power_supply_unregister(di->btemp_psy); - - return 0; -} - static char *supply_interface[] = { "ab8500_chargalg", "ab8500_fg", @@ -966,9 +947,42 @@ static const struct power_supply_desc ab8500_btemp_desc = { .external_power_changed = ab8500_btemp_external_power_changed, }; +static int ab8500_btemp_bind(struct device *dev, struct device *master, + void *data) +{ + struct ab8500_btemp *di = dev_get_drvdata(dev); + + /* Create a work queue for the btemp */ + di->btemp_wq = + alloc_workqueue("ab8500_btemp_wq", WQ_MEM_RECLAIM, 0); + if (di->btemp_wq == NULL) { + dev_err(dev, "failed to create work queue\n"); + return -ENOMEM; + } + + /* Kick off periodic temperature measurements */ + ab8500_btemp_periodic(di, true); + + return 0; +} + +static void ab8500_btemp_unbind(struct device *dev, struct device *master, + void *data) +{ + struct ab8500_btemp *di = dev_get_drvdata(dev); + + /* Delete the work queue */ + destroy_workqueue(di->btemp_wq); + flush_scheduled_work(); +} + +static const struct component_ops ab8500_btemp_component_ops = { + .bind = ab8500_btemp_bind, + .unbind = ab8500_btemp_unbind, +}; + static int ab8500_btemp_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; struct power_supply_config psy_cfg = {}; struct device *dev = &pdev->dev; struct ab8500_btemp *di; @@ -981,12 +995,6 @@ static int ab8500_btemp_probe(struct platform_device *pdev) di->bm = &ab8500_bm_data; - ret = ab8500_bm_of_probe(dev, np, di->bm); - if (ret) { - dev_err(dev, "failed to get battery information\n"); - return ret; - } - /* get parent data */ di->dev = dev; di->parent = dev_get_drvdata(pdev->dev.parent); @@ -1011,14 +1019,6 @@ static int ab8500_btemp_probe(struct platform_device *pdev) psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface); psy_cfg.drv_data = di; - /* Create a work queue for the btemp */ - di->btemp_wq = - alloc_workqueue("ab8500_btemp_wq", WQ_MEM_RECLAIM, 0); - if (di->btemp_wq == NULL) { - dev_err(dev, "failed to create work queue\n"); - return -ENOMEM; - } - /* Init work for measuring temperature periodically */ INIT_DEFERRABLE_WORK(&di->btemp_periodic_work, ab8500_btemp_periodic_work); @@ -1031,7 +1031,7 @@ static int ab8500_btemp_probe(struct platform_device *pdev) AB8500_BTEMP_HIGH_TH, &val); if (ret < 0) { dev_err(dev, "%s ab8500 read failed\n", __func__); - goto free_btemp_wq; + return ret; } switch (val) { case BTEMP_HIGH_TH_57_0: @@ -1050,30 +1050,28 @@ static int ab8500_btemp_probe(struct platform_device *pdev) } /* Register BTEMP power supply class */ - di->btemp_psy = power_supply_register(dev, &ab8500_btemp_desc, - &psy_cfg); + di->btemp_psy = devm_power_supply_register(dev, &ab8500_btemp_desc, + &psy_cfg); if (IS_ERR(di->btemp_psy)) { dev_err(dev, "failed to register BTEMP psy\n"); - ret = PTR_ERR(di->btemp_psy); - goto free_btemp_wq; + return PTR_ERR(di->btemp_psy); } /* Register interrupts */ for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) { irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name); - if (irq < 0) { - ret = irq; - goto free_irq; - } + if (irq < 0) + return irq; - ret = request_threaded_irq(irq, NULL, ab8500_btemp_irq[i].isr, + ret = devm_request_threaded_irq(dev, irq, NULL, + ab8500_btemp_irq[i].isr, IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, ab8500_btemp_irq[i].name, di); if (ret) { dev_err(dev, "failed to request %s IRQ %d: %d\n" , ab8500_btemp_irq[i].name, irq, ret); - goto free_irq; + return ret; } dev_dbg(dev, "Requested %s IRQ %d: %d\n", ab8500_btemp_irq[i].name, irq, ret); @@ -1081,23 +1079,16 @@ static int ab8500_btemp_probe(struct platform_device *pdev) platform_set_drvdata(pdev, di); - /* Kick off periodic temperature measurements */ - ab8500_btemp_periodic(di, true); list_add_tail(&di->node, &ab8500_btemp_list); - return ret; + return component_add(dev, &ab8500_btemp_component_ops); +} -free_irq: - /* We also have to free all successfully registered irqs */ - for (i = i - 1; i >= 0; i--) { - irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name); - free_irq(irq, di); - } +static int ab8500_btemp_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &ab8500_btemp_component_ops); - power_supply_unregister(di->btemp_psy); -free_btemp_wq: - destroy_workqueue(di->btemp_wq); - return ret; + return 0; } static SIMPLE_DEV_PM_OPS(ab8500_btemp_pm_ops, ab8500_btemp_suspend, ab8500_btemp_resume); @@ -1106,8 +1097,9 @@ static const struct of_device_id ab8500_btemp_match[] = { { .compatible = "stericsson,ab8500-btemp", }, { }, }; +MODULE_DEVICE_TABLE(of, ab8500_btemp_match); -static struct platform_driver ab8500_btemp_driver = { +struct platform_driver ab8500_btemp_driver = { .probe = ab8500_btemp_probe, .remove = ab8500_btemp_remove, .driver = { @@ -1116,20 +1108,6 @@ static struct platform_driver ab8500_btemp_driver = { .pm = &ab8500_btemp_pm_ops, }, }; - -static int __init ab8500_btemp_init(void) -{ - return platform_driver_register(&ab8500_btemp_driver); -} - -static void __exit ab8500_btemp_exit(void) -{ - platform_driver_unregister(&ab8500_btemp_driver); -} - -device_initcall(ab8500_btemp_init); -module_exit(ab8500_btemp_exit); - MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy"); MODULE_ALIAS("platform:ab8500-btemp"); diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c index a9be10eb2c22..fa49e12e5a60 100644 --- a/drivers/power/supply/ab8500_charger.c +++ b/drivers/power/supply/ab8500_charger.c @@ -13,6 +13,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/device.h> +#include <linux/component.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/notifier.h> @@ -414,6 +415,14 @@ disable_otp: static void ab8500_power_supply_changed(struct ab8500_charger *di, struct power_supply *psy) { + /* + * This happens if we get notifications or interrupts and + * the platform has been configured not to support one or + * other type of charging. + */ + if (!psy) + return; + if (di->autopower_cfg) { if (!di->usb.charger_connected && !di->ac.charger_connected && @@ -440,7 +449,15 @@ static void ab8500_charger_set_usb_connected(struct ab8500_charger *di, if (!connected) di->flags.vbus_drop_end = false; - sysfs_notify(&di->usb_chg.psy->dev.kobj, NULL, "present"); + /* + * Sometimes the platform is configured not to support + * USB charging and no psy has been created, but we still + * will get these notifications. + */ + if (di->usb_chg.psy) { + sysfs_notify(&di->usb_chg.psy->dev.kobj, NULL, + "present"); + } if (connected) { mutex_lock(&di->charger_attached_mutex); @@ -3171,9 +3188,6 @@ static int ab8500_charger_usb_notifier_call(struct notifier_block *nb, enum ab8500_usb_state bm_usb_state; unsigned mA = *((unsigned *)power); - if (!di) - return NOTIFY_DONE; - if (event != USB_EVENT_VBUS) { dev_dbg(di->dev, "not a standard host, returning\n"); return NOTIFY_DONE; @@ -3276,10 +3290,74 @@ static struct notifier_block charger_nb = { .notifier_call = ab8500_external_charger_prepare, }; -static int ab8500_charger_remove(struct platform_device *pdev) +static char *supply_interface[] = { + "ab8500_chargalg", + "ab8500_fg", + "ab8500_btemp", +}; + +static const struct power_supply_desc ab8500_ac_chg_desc = { + .name = "ab8500_ac", + .type = POWER_SUPPLY_TYPE_MAINS, + .properties = ab8500_charger_ac_props, + .num_properties = ARRAY_SIZE(ab8500_charger_ac_props), + .get_property = ab8500_charger_ac_get_property, +}; + +static const struct power_supply_desc ab8500_usb_chg_desc = { + .name = "ab8500_usb", + .type = POWER_SUPPLY_TYPE_USB, + .properties = ab8500_charger_usb_props, + .num_properties = ARRAY_SIZE(ab8500_charger_usb_props), + .get_property = ab8500_charger_usb_get_property, +}; + +static int ab8500_charger_bind(struct device *dev) { - struct ab8500_charger *di = platform_get_drvdata(pdev); - int i, irq, ret; + struct ab8500_charger *di = dev_get_drvdata(dev); + int ch_stat; + int ret; + + /* Create a work queue for the charger */ + di->charger_wq = alloc_ordered_workqueue("ab8500_charger_wq", + WQ_MEM_RECLAIM); + if (di->charger_wq == NULL) { + dev_err(dev, "failed to create work queue\n"); + return -ENOMEM; + } + + ch_stat = ab8500_charger_detect_chargers(di, false); + + if (ch_stat & AC_PW_CONN) { + if (is_ab8500(di->parent)) + queue_delayed_work(di->charger_wq, + &di->ac_charger_attached_work, + HZ); + } + if (ch_stat & USB_PW_CONN) { + if (is_ab8500(di->parent)) + queue_delayed_work(di->charger_wq, + &di->usb_charger_attached_work, + HZ); + di->vbus_detected = true; + di->vbus_detected_start = true; + queue_work(di->charger_wq, + &di->detect_usb_type_work); + } + + ret = component_bind_all(dev, di); + if (ret) { + dev_err(dev, "can't bind component devices\n"); + return ret; + } + + return 0; +} + +static void ab8500_charger_unbind(struct device *dev) +{ + struct ab8500_charger *di = dev_get_drvdata(dev); + int ret; /* Disable AC charging */ ab8500_charger_ac_en(&di->ac_chg, false, 0, 0); @@ -3287,68 +3365,47 @@ static int ab8500_charger_remove(struct platform_device *pdev) /* Disable USB charging */ ab8500_charger_usb_en(&di->usb_chg, false, 0, 0); - /* Disable interrupts */ - for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { - irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); - free_irq(irq, di); - } - /* Backup battery voltage and current disable */ ret = abx500_mask_and_set_register_interruptible(di->dev, AB8500_RTC, AB8500_RTC_CTRL_REG, RTC_BUP_CH_ENA, 0); if (ret < 0) dev_err(di->dev, "%s mask and set failed\n", __func__); - usb_unregister_notifier(di->usb_phy, &di->nb); - usb_put_phy(di->usb_phy); - /* Delete the work queue */ destroy_workqueue(di->charger_wq); - /* Unregister external charger enable notifier */ - if (!di->ac_chg.enabled) - blocking_notifier_chain_unregister( - &charger_notifier_list, &charger_nb); - flush_scheduled_work(); - if (di->usb_chg.enabled) - power_supply_unregister(di->usb_chg.psy); - if (di->ac_chg.enabled && !di->ac_chg.external) - power_supply_unregister(di->ac_chg.psy); - - return 0; + /* Unbind fg, btemp, algorithm */ + component_unbind_all(dev, di); } -static char *supply_interface[] = { - "ab8500_chargalg", - "ab8500_fg", - "ab8500_btemp", +static const struct component_master_ops ab8500_charger_comp_ops = { + .bind = ab8500_charger_bind, + .unbind = ab8500_charger_unbind, }; -static const struct power_supply_desc ab8500_ac_chg_desc = { - .name = "ab8500_ac", - .type = POWER_SUPPLY_TYPE_MAINS, - .properties = ab8500_charger_ac_props, - .num_properties = ARRAY_SIZE(ab8500_charger_ac_props), - .get_property = ab8500_charger_ac_get_property, +static struct platform_driver *const ab8500_charger_component_drivers[] = { + &ab8500_fg_driver, + &ab8500_btemp_driver, + &abx500_chargalg_driver, }; -static const struct power_supply_desc ab8500_usb_chg_desc = { - .name = "ab8500_usb", - .type = POWER_SUPPLY_TYPE_USB, - .properties = ab8500_charger_usb_props, - .num_properties = ARRAY_SIZE(ab8500_charger_usb_props), - .get_property = ab8500_charger_usb_get_property, -}; +static int ab8500_charger_compare_dev(struct device *dev, void *data) +{ + return dev == data; +} static int ab8500_charger_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct component_match *match = NULL; struct power_supply_config ac_psy_cfg = {}, usb_psy_cfg = {}; struct ab8500_charger *di; - int irq, i, charger_status, ret = 0, ch_stat; - struct device *dev = &pdev->dev; + int charger_status; + int i, irq; + int ret; di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL); if (!di) @@ -3393,6 +3450,38 @@ static int ab8500_charger_probe(struct platform_device *pdev) return ret; } + /* + * VDD ADC supply needs to be enabled from this driver when there + * is a charger connected to avoid erroneous BTEMP_HIGH/LOW + * interrupts during charging + */ + di->regu = devm_regulator_get(dev, "vddadc"); + if (IS_ERR(di->regu)) { + ret = PTR_ERR(di->regu); + dev_err(dev, "failed to get vddadc regulator\n"); + return ret; + } + + /* Request interrupts */ + for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { + irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); + if (irq < 0) + return irq; + + ret = devm_request_threaded_irq(dev, + irq, NULL, ab8500_charger_irq[i].isr, + IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, + ab8500_charger_irq[i].name, di); + + if (ret != 0) { + dev_err(dev, "failed to request %s IRQ %d: %d\n" + , ab8500_charger_irq[i].name, irq, ret); + return ret; + } + dev_dbg(dev, "Requested %s IRQ %d: %d\n", + ab8500_charger_irq[i].name, irq, ret); + } + /* initialize lock */ spin_lock_init(&di->usb_state.usb_lock); mutex_init(&di->usb_ipt_crnt_lock); @@ -3419,14 +3508,16 @@ static int ab8500_charger_probe(struct platform_device *pdev) di->ac_chg.max_out_curr = di->bm->chg_output_curr[di->bm->n_chg_out_curr - 1]; di->ac_chg.wdt_refresh = CHG_WD_INTERVAL; - di->ac_chg.enabled = di->bm->ac_enabled; + /* + * The AB8505 only supports USB charging. If we are not the + * AB8505, register an AC charger. + * + * TODO: if this should be opt-in, add DT properties for this. + */ + if (!is_ab8505(di->parent)) + di->ac_chg.enabled = true; di->ac_chg.external = false; - /*notifier for external charger enabling*/ - if (!di->ac_chg.enabled) - blocking_notifier_chain_register( - &charger_notifier_list, &charger_nb); - /* USB supply */ /* ux500_charger sub-class */ di->usb_chg.ops.enable = &ab8500_charger_usb_en; @@ -3438,18 +3529,9 @@ static int ab8500_charger_probe(struct platform_device *pdev) di->usb_chg.max_out_curr = di->bm->chg_output_curr[di->bm->n_chg_out_curr - 1]; di->usb_chg.wdt_refresh = CHG_WD_INTERVAL; - di->usb_chg.enabled = di->bm->usb_enabled; di->usb_chg.external = false; di->usb_state.usb_current = -1; - /* Create a work queue for the charger */ - di->charger_wq = alloc_ordered_workqueue("ab8500_charger_wq", - WQ_MEM_RECLAIM); - if (di->charger_wq == NULL) { - dev_err(dev, "failed to create work queue\n"); - return -ENOMEM; - } - mutex_init(&di->charger_attached_mutex); /* Init work for HW failure check */ @@ -3500,61 +3582,32 @@ static int ab8500_charger_probe(struct platform_device *pdev) INIT_WORK(&di->check_usb_thermal_prot_work, ab8500_charger_check_usb_thermal_prot_work); - /* - * VDD ADC supply needs to be enabled from this driver when there - * is a charger connected to avoid erroneous BTEMP_HIGH/LOW - * interrupts during charging - */ - di->regu = devm_regulator_get(dev, "vddadc"); - if (IS_ERR(di->regu)) { - ret = PTR_ERR(di->regu); - dev_err(dev, "failed to get vddadc regulator\n"); - goto free_charger_wq; - } - /* Initialize OVV, and other registers */ ret = ab8500_charger_init_hw_registers(di); if (ret) { dev_err(dev, "failed to initialize ABB registers\n"); - goto free_charger_wq; + return ret; } /* Register AC charger class */ if (di->ac_chg.enabled) { - di->ac_chg.psy = power_supply_register(dev, + di->ac_chg.psy = devm_power_supply_register(dev, &ab8500_ac_chg_desc, &ac_psy_cfg); if (IS_ERR(di->ac_chg.psy)) { dev_err(dev, "failed to register AC charger\n"); - ret = PTR_ERR(di->ac_chg.psy); - goto free_charger_wq; + return PTR_ERR(di->ac_chg.psy); } } /* Register USB charger class */ - if (di->usb_chg.enabled) { - di->usb_chg.psy = power_supply_register(dev, - &ab8500_usb_chg_desc, - &usb_psy_cfg); - if (IS_ERR(di->usb_chg.psy)) { - dev_err(dev, "failed to register USB charger\n"); - ret = PTR_ERR(di->usb_chg.psy); - goto free_ac; - } - } - - di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); - if (IS_ERR_OR_NULL(di->usb_phy)) { - dev_err(dev, "failed to get usb transceiver\n"); - ret = -EINVAL; - goto free_usb; - } - di->nb.notifier_call = ab8500_charger_usb_notifier_call; - ret = usb_register_notifier(di->usb_phy, &di->nb); - if (ret) { - dev_err(dev, "failed to register usb notifier\n"); - goto put_usb_phy; + di->usb_chg.psy = devm_power_supply_register(dev, + &ab8500_usb_chg_desc, + &usb_psy_cfg); + if (IS_ERR(di->usb_chg.psy)) { + dev_err(dev, "failed to register USB charger\n"); + return PTR_ERR(di->usb_chg.psy); } /* Identify the connected charger types during startup */ @@ -3566,84 +3619,93 @@ static int ab8500_charger_probe(struct platform_device *pdev) sysfs_notify(&di->ac_chg.psy->dev.kobj, NULL, "present"); } - if (charger_status & USB_PW_CONN) { - di->vbus_detected = true; - di->vbus_detected_start = true; - queue_work(di->charger_wq, - &di->detect_usb_type_work); - } - - /* Register interrupts */ - for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { - irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); - if (irq < 0) { - ret = irq; - goto free_irq; - } + platform_set_drvdata(pdev, di); - ret = request_threaded_irq(irq, NULL, ab8500_charger_irq[i].isr, - IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, - ab8500_charger_irq[i].name, di); + /* Create something that will match the subdrivers when we bind */ + for (i = 0; i < ARRAY_SIZE(ab8500_charger_component_drivers); i++) { + struct device_driver *drv = &ab8500_charger_component_drivers[i]->driver; + struct device *p = NULL, *d; - if (ret != 0) { - dev_err(dev, "failed to request %s IRQ %d: %d\n" - , ab8500_charger_irq[i].name, irq, ret); - goto free_irq; + while ((d = platform_find_device_by_driver(p, drv))) { + put_device(p); + component_match_add(dev, &match, + ab8500_charger_compare_dev, d); + p = d; } - dev_dbg(dev, "Requested %s IRQ %d: %d\n", - ab8500_charger_irq[i].name, irq, ret); + put_device(p); + } + if (!match) { + dev_err(dev, "no matching components\n"); + return -ENODEV; + } + if (IS_ERR(match)) { + dev_err(dev, "could not create component match\n"); + return PTR_ERR(match); } - platform_set_drvdata(pdev, di); - - mutex_lock(&di->charger_attached_mutex); + /* Notifier for external charger enabling */ + if (!di->ac_chg.enabled) + blocking_notifier_chain_register( + &charger_notifier_list, &charger_nb); - ch_stat = ab8500_charger_detect_chargers(di, false); - if ((ch_stat & AC_PW_CONN) == AC_PW_CONN) { - if (is_ab8500(di->parent)) - queue_delayed_work(di->charger_wq, - &di->ac_charger_attached_work, - HZ); + di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); + if (IS_ERR_OR_NULL(di->usb_phy)) { + dev_err(dev, "failed to get usb transceiver\n"); + ret = -EINVAL; + goto out_charger_notifier; } - if ((ch_stat & USB_PW_CONN) == USB_PW_CONN) { - if (is_ab8500(di->parent)) - queue_delayed_work(di->charger_wq, - &di->usb_charger_attached_work, - HZ); + di->nb.notifier_call = ab8500_charger_usb_notifier_call; + ret = usb_register_notifier(di->usb_phy, &di->nb); + if (ret) { + dev_err(dev, "failed to register usb notifier\n"); + goto put_usb_phy; } - mutex_unlock(&di->charger_attached_mutex); - return ret; + ret = component_master_add_with_match(&pdev->dev, + &ab8500_charger_comp_ops, + match); + if (ret) { + dev_err(dev, "failed to add component master\n"); + goto free_notifier; + } -free_irq: - usb_unregister_notifier(di->usb_phy, &di->nb); + return 0; - /* We also have to free all successfully registered irqs */ - for (i = i - 1; i >= 0; i--) { - irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); - free_irq(irq, di); - } +free_notifier: + usb_unregister_notifier(di->usb_phy, &di->nb); put_usb_phy: usb_put_phy(di->usb_phy); -free_usb: - if (di->usb_chg.enabled) - power_supply_unregister(di->usb_chg.psy); -free_ac: - if (di->ac_chg.enabled) - power_supply_unregister(di->ac_chg.psy); -free_charger_wq: - destroy_workqueue(di->charger_wq); +out_charger_notifier: + if (!di->ac_chg.enabled) + blocking_notifier_chain_unregister( + &charger_notifier_list, &charger_nb); return ret; } +static int ab8500_charger_remove(struct platform_device *pdev) +{ + struct ab8500_charger *di = platform_get_drvdata(pdev); + + component_master_del(&pdev->dev, &ab8500_charger_comp_ops); + + usb_unregister_notifier(di->usb_phy, &di->nb); + usb_put_phy(di->usb_phy); + if (!di->ac_chg.enabled) + blocking_notifier_chain_unregister( + &charger_notifier_list, &charger_nb); + + return 0; +} + static SIMPLE_DEV_PM_OPS(ab8500_charger_pm_ops, ab8500_charger_suspend, ab8500_charger_resume); static const struct of_device_id ab8500_charger_match[] = { { .compatible = "stericsson,ab8500-charger", }, { }, }; +MODULE_DEVICE_TABLE(of, ab8500_charger_match); static struct platform_driver ab8500_charger_driver = { .probe = ab8500_charger_probe, @@ -3657,15 +3719,24 @@ static struct platform_driver ab8500_charger_driver = { static int __init ab8500_charger_init(void) { + int ret; + + ret = platform_register_drivers(ab8500_charger_component_drivers, + ARRAY_SIZE(ab8500_charger_component_drivers)); + if (ret) + return ret; + return platform_driver_register(&ab8500_charger_driver); } static void __exit ab8500_charger_exit(void) { + platform_unregister_drivers(ab8500_charger_component_drivers, + ARRAY_SIZE(ab8500_charger_component_drivers)); platform_driver_unregister(&ab8500_charger_driver); } -subsys_initcall_sync(ab8500_charger_init); +module_init(ab8500_charger_init); module_exit(ab8500_charger_exit); MODULE_LICENSE("GPL v2"); diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c index 0c7c01a0d979..3d45ed0157c6 100644 --- a/drivers/power/supply/ab8500_fg.c +++ b/drivers/power/supply/ab8500_fg.c @@ -17,6 +17,7 @@ #include <linux/init.h> #include <linux/module.h> +#include <linux/component.h> #include <linux/device.h> #include <linux/interrupt.h> #include <linux/platform_device.h> @@ -59,7 +60,7 @@ ((y1) + ((((y2) - (y1)) * ((x) - (x1))) / ((x2) - (x1)))); /** - * struct ab8500_fg_interrupts - ab8500 fg interupts + * struct ab8500_fg_interrupts - ab8500 fg interrupts * @name: name of the interrupt * @isr function pointer to the isr */ @@ -2980,27 +2981,6 @@ static int __maybe_unused ab8500_fg_suspend(struct device *dev) return 0; } -static int ab8500_fg_remove(struct platform_device *pdev) -{ - int ret = 0; - struct ab8500_fg *di = platform_get_drvdata(pdev); - - list_del(&di->node); - - /* Disable coulomb counter */ - ret = ab8500_fg_coulomb_counter(di, false); - if (ret) - dev_err(di->dev, "failed to disable coulomb counter\n"); - - destroy_workqueue(di->fg_wq); - ab8500_fg_sysfs_exit(di); - - flush_scheduled_work(); - ab8500_fg_sysfs_psy_remove_attrs(di); - power_supply_unregister(di->fg_psy); - return ret; -} - /* ab8500 fg driver interrupts and their respective isr */ static struct ab8500_fg_interrupts ab8500_fg_irq[] = { {"NCONV_ACCU", ab8500_fg_cc_convend_handler}, @@ -3024,11 +3004,50 @@ static const struct power_supply_desc ab8500_fg_desc = { .external_power_changed = ab8500_fg_external_power_changed, }; +static int ab8500_fg_bind(struct device *dev, struct device *master, + void *data) +{ + struct ab8500_fg *di = dev_get_drvdata(dev); + + /* Create a work queue for running the FG algorithm */ + di->fg_wq = alloc_ordered_workqueue("ab8500_fg_wq", WQ_MEM_RECLAIM); + if (di->fg_wq == NULL) { + dev_err(dev, "failed to create work queue\n"); + return -ENOMEM; + } + + /* Start the coulomb counter */ + ab8500_fg_coulomb_counter(di, true); + /* Run the FG algorithm */ + queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); + + return 0; +} + +static void ab8500_fg_unbind(struct device *dev, struct device *master, + void *data) +{ + struct ab8500_fg *di = dev_get_drvdata(dev); + int ret; + + /* Disable coulomb counter */ + ret = ab8500_fg_coulomb_counter(di, false); + if (ret) + dev_err(dev, "failed to disable coulomb counter\n"); + + destroy_workqueue(di->fg_wq); + flush_scheduled_work(); +} + +static const struct component_ops ab8500_fg_component_ops = { + .bind = ab8500_fg_bind, + .unbind = ab8500_fg_unbind, +}; + static int ab8500_fg_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; - struct power_supply_config psy_cfg = {}; struct device *dev = &pdev->dev; + struct power_supply_config psy_cfg = {}; struct ab8500_fg *di; int i, irq; int ret = 0; @@ -3039,12 +3058,6 @@ static int ab8500_fg_probe(struct platform_device *pdev) di->bm = &ab8500_bm_data; - ret = ab8500_bm_of_probe(dev, np, di->bm); - if (ret) { - dev_err(dev, "failed to get battery information\n"); - return ret; - } - mutex_init(&di->cc_lock); /* get parent data */ @@ -3074,13 +3087,6 @@ static int ab8500_fg_probe(struct platform_device *pdev) ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_INIT); ab8500_fg_discharge_state_to(di, AB8500_FG_DISCHARGE_INIT); - /* Create a work queue for running the FG algorithm */ - di->fg_wq = alloc_ordered_workqueue("ab8500_fg_wq", WQ_MEM_RECLAIM); - if (di->fg_wq == NULL) { - dev_err(dev, "failed to create work queue\n"); - return -ENOMEM; - } - /* Init work for running the fg algorithm instantly */ INIT_WORK(&di->fg_work, ab8500_fg_instant_work); @@ -3113,7 +3119,7 @@ static int ab8500_fg_probe(struct platform_device *pdev) ret = ab8500_fg_init_hw_registers(di); if (ret) { dev_err(dev, "failed to initialize registers\n"); - goto free_inst_curr_wq; + return ret; } /* Consider battery unknown until we're informed otherwise */ @@ -3121,15 +3127,13 @@ static int ab8500_fg_probe(struct platform_device *pdev) di->flags.batt_id_received = false; /* Register FG power supply class */ - di->fg_psy = power_supply_register(dev, &ab8500_fg_desc, &psy_cfg); + di->fg_psy = devm_power_supply_register(dev, &ab8500_fg_desc, &psy_cfg); if (IS_ERR(di->fg_psy)) { dev_err(dev, "failed to register FG psy\n"); - ret = PTR_ERR(di->fg_psy); - goto free_inst_curr_wq; + return PTR_ERR(di->fg_psy); } di->fg_samples = SEC_TO_SAMPLE(di->bm->fg_params->init_timer); - ab8500_fg_coulomb_counter(di, true); /* * Initialize completion used to notify completion and start @@ -3141,19 +3145,18 @@ static int ab8500_fg_probe(struct platform_device *pdev) /* Register primary interrupt handlers */ for (i = 0; i < ARRAY_SIZE(ab8500_fg_irq); i++) { irq = platform_get_irq_byname(pdev, ab8500_fg_irq[i].name); - if (irq < 0) { - ret = irq; - goto free_irq; - } + if (irq < 0) + return irq; - ret = request_threaded_irq(irq, NULL, ab8500_fg_irq[i].isr, + ret = devm_request_threaded_irq(dev, irq, NULL, + ab8500_fg_irq[i].isr, IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, ab8500_fg_irq[i].name, di); if (ret != 0) { dev_err(dev, "failed to request %s IRQ %d: %d\n", ab8500_fg_irq[i].name, irq, ret); - goto free_irq; + return ret; } dev_dbg(dev, "Requested %s IRQ %d: %d\n", ab8500_fg_irq[i].name, irq, ret); @@ -3168,14 +3171,14 @@ static int ab8500_fg_probe(struct platform_device *pdev) ret = ab8500_fg_sysfs_init(di); if (ret) { dev_err(dev, "failed to create sysfs entry\n"); - goto free_irq; + return ret; } ret = ab8500_fg_sysfs_psy_create_attrs(di); if (ret) { dev_err(dev, "failed to create FG psy\n"); ab8500_fg_sysfs_exit(di); - goto free_irq; + return ret; } /* Calibrate the fg first time */ @@ -3185,24 +3188,21 @@ static int ab8500_fg_probe(struct platform_device *pdev) /* Use room temp as default value until we get an update from driver. */ di->bat_temp = 210; - /* Run the FG algorithm */ - queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); - list_add_tail(&di->node, &ab8500_fg_list); - return ret; + return component_add(dev, &ab8500_fg_component_ops); +} -free_irq: - /* We also have to free all registered irqs */ - while (--i >= 0) { - /* Last assignment of i from primary interrupt handlers */ - irq = platform_get_irq_byname(pdev, ab8500_fg_irq[i].name); - free_irq(irq, di); - } +static int ab8500_fg_remove(struct platform_device *pdev) +{ + int ret = 0; + struct ab8500_fg *di = platform_get_drvdata(pdev); + + component_del(&pdev->dev, &ab8500_fg_component_ops); + list_del(&di->node); + ab8500_fg_sysfs_exit(di); + ab8500_fg_sysfs_psy_remove_attrs(di); - power_supply_unregister(di->fg_psy); -free_inst_curr_wq: - destroy_workqueue(di->fg_wq); return ret; } @@ -3212,8 +3212,9 @@ static const struct of_device_id ab8500_fg_match[] = { { .compatible = "stericsson,ab8500-fg", }, { }, }; +MODULE_DEVICE_TABLE(of, ab8500_fg_match); -static struct platform_driver ab8500_fg_driver = { +struct platform_driver ab8500_fg_driver = { .probe = ab8500_fg_probe, .remove = ab8500_fg_remove, .driver = { @@ -3222,20 +3223,6 @@ static struct platform_driver ab8500_fg_driver = { .pm = &ab8500_fg_pm_ops, }, }; - -static int __init ab8500_fg_init(void) -{ - return platform_driver_register(&ab8500_fg_driver); -} - -static void __exit ab8500_fg_exit(void) -{ - platform_driver_unregister(&ab8500_fg_driver); -} - -subsys_initcall_sync(ab8500_fg_init); -module_exit(ab8500_fg_exit); - MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Johan Palsson, Karl Komierowski"); MODULE_ALIAS("platform:ab8500-fg"); diff --git a/drivers/power/supply/abx500_chargalg.c b/drivers/power/supply/abx500_chargalg.c index f5b792243727..a17849bfacbf 100644 --- a/drivers/power/supply/abx500_chargalg.c +++ b/drivers/power/supply/abx500_chargalg.c @@ -15,6 +15,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/device.h> +#include <linux/component.h> #include <linux/hrtimer.h> #include <linux/interrupt.h> #include <linux/delay.h> @@ -1943,13 +1944,44 @@ static int __maybe_unused abx500_chargalg_suspend(struct device *dev) return 0; } -static int abx500_chargalg_remove(struct platform_device *pdev) +static char *supply_interface[] = { + "ab8500_fg", +}; + +static const struct power_supply_desc abx500_chargalg_desc = { + .name = "abx500_chargalg", + .type = POWER_SUPPLY_TYPE_BATTERY, + .properties = abx500_chargalg_props, + .num_properties = ARRAY_SIZE(abx500_chargalg_props), + .get_property = abx500_chargalg_get_property, + .external_power_changed = abx500_chargalg_external_power_changed, +}; + +static int abx500_chargalg_bind(struct device *dev, struct device *master, + void *data) { - struct abx500_chargalg *di = platform_get_drvdata(pdev); + struct abx500_chargalg *di = dev_get_drvdata(dev); - /* sysfs interface to enable/disbale charging from user space */ - abx500_chargalg_sysfs_exit(di); + /* Create a work queue for the chargalg */ + di->chargalg_wq = alloc_ordered_workqueue("abx500_chargalg_wq", + WQ_MEM_RECLAIM); + if (di->chargalg_wq == NULL) { + dev_err(di->dev, "failed to create work queue\n"); + return -ENOMEM; + } + + /* Run the charging algorithm */ + queue_delayed_work(di->chargalg_wq, &di->chargalg_periodic_work, 0); + return 0; +} + +static void abx500_chargalg_unbind(struct device *dev, struct device *master, + void *data) +{ + struct abx500_chargalg *di = dev_get_drvdata(dev); + + /* Stop all timers and work */ hrtimer_cancel(&di->safety_timer); hrtimer_cancel(&di->maintenance_timer); @@ -1959,48 +1991,29 @@ static int abx500_chargalg_remove(struct platform_device *pdev) /* Delete the work queue */ destroy_workqueue(di->chargalg_wq); - - power_supply_unregister(di->chargalg_psy); - - return 0; + flush_scheduled_work(); } -static char *supply_interface[] = { - "ab8500_fg", -}; - -static const struct power_supply_desc abx500_chargalg_desc = { - .name = "abx500_chargalg", - .type = POWER_SUPPLY_TYPE_BATTERY, - .properties = abx500_chargalg_props, - .num_properties = ARRAY_SIZE(abx500_chargalg_props), - .get_property = abx500_chargalg_get_property, - .external_power_changed = abx500_chargalg_external_power_changed, +static const struct component_ops abx500_chargalg_component_ops = { + .bind = abx500_chargalg_bind, + .unbind = abx500_chargalg_unbind, }; static int abx500_chargalg_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; struct power_supply_config psy_cfg = {}; struct abx500_chargalg *di; int ret = 0; - di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); - if (!di) { - dev_err(&pdev->dev, "%s no mem for ab8500_chargalg\n", __func__); + di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL); + if (!di) return -ENOMEM; - } di->bm = &ab8500_bm_data; - ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm); - if (ret) { - dev_err(&pdev->dev, "failed to get battery information\n"); - return ret; - } - /* get device struct and parent */ - di->dev = &pdev->dev; + di->dev = dev; di->parent = dev_get_drvdata(pdev->dev.parent); psy_cfg.supplied_to = supply_interface; @@ -2016,14 +2029,6 @@ static int abx500_chargalg_probe(struct platform_device *pdev) di->maintenance_timer.function = abx500_chargalg_maintenance_timer_expired; - /* Create a work queue for the chargalg */ - di->chargalg_wq = alloc_ordered_workqueue("abx500_chargalg_wq", - WQ_MEM_RECLAIM); - if (di->chargalg_wq == NULL) { - dev_err(di->dev, "failed to create work queue\n"); - return -ENOMEM; - } - /* Init work for chargalg */ INIT_DEFERRABLE_WORK(&di->chargalg_periodic_work, abx500_chargalg_periodic_work); @@ -2037,12 +2042,12 @@ static int abx500_chargalg_probe(struct platform_device *pdev) di->chg_info.prev_conn_chg = -1; /* Register chargalg power supply class */ - di->chargalg_psy = power_supply_register(di->dev, &abx500_chargalg_desc, + di->chargalg_psy = devm_power_supply_register(di->dev, + &abx500_chargalg_desc, &psy_cfg); if (IS_ERR(di->chargalg_psy)) { dev_err(di->dev, "failed to register chargalg psy\n"); - ret = PTR_ERR(di->chargalg_psy); - goto free_chargalg_wq; + return PTR_ERR(di->chargalg_psy); } platform_set_drvdata(pdev, di); @@ -2051,21 +2056,24 @@ static int abx500_chargalg_probe(struct platform_device *pdev) ret = abx500_chargalg_sysfs_init(di); if (ret) { dev_err(di->dev, "failed to create sysfs entry\n"); - goto free_psy; + return ret; } di->curr_status.curr_step = CHARGALG_CURR_STEP_HIGH; - /* Run the charging algorithm */ - queue_delayed_work(di->chargalg_wq, &di->chargalg_periodic_work, 0); - dev_info(di->dev, "probe success\n"); - return ret; + return component_add(dev, &abx500_chargalg_component_ops); +} -free_psy: - power_supply_unregister(di->chargalg_psy); -free_chargalg_wq: - destroy_workqueue(di->chargalg_wq); - return ret; +static int abx500_chargalg_remove(struct platform_device *pdev) +{ + struct abx500_chargalg *di = platform_get_drvdata(pdev); + + component_del(&pdev->dev, &abx500_chargalg_component_ops); + + /* sysfs interface to enable/disable charging from user space */ + abx500_chargalg_sysfs_exit(di); + + return 0; } static SIMPLE_DEV_PM_OPS(abx500_chargalg_pm_ops, abx500_chargalg_suspend, abx500_chargalg_resume); @@ -2075,7 +2083,7 @@ static const struct of_device_id ab8500_chargalg_match[] = { { }, }; -static struct platform_driver abx500_chargalg_driver = { +struct platform_driver abx500_chargalg_driver = { .probe = abx500_chargalg_probe, .remove = abx500_chargalg_remove, .driver = { @@ -2084,9 +2092,6 @@ static struct platform_driver abx500_chargalg_driver = { .pm = &abx500_chargalg_pm_ops, }, }; - -module_platform_driver(abx500_chargalg_driver); - MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Johan Palsson, Karl Komierowski"); MODULE_ALIAS("platform:abx500-chargalg"); diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c index e84b6e4da14a..18a9db0df4b1 100644 --- a/drivers/power/supply/axp20x_battery.c +++ b/drivers/power/supply/axp20x_battery.c @@ -40,6 +40,7 @@ #define AXP209_FG_PERCENT GENMASK(6, 0) #define AXP22X_FG_VALID BIT(7) +#define AXP20X_CHRG_CTRL1_ENABLE BIT(7) #define AXP20X_CHRG_CTRL1_TGT_VOLT GENMASK(6, 5) #define AXP20X_CHRG_CTRL1_TGT_4_1V (0 << 5) #define AXP20X_CHRG_CTRL1_TGT_4_15V (1 << 5) @@ -468,7 +469,18 @@ static int axp20x_battery_set_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: return axp20x_set_max_constant_charge_current(axp20x_batt, val->intval); - + case POWER_SUPPLY_PROP_STATUS: + switch (val->intval) { + case POWER_SUPPLY_STATUS_CHARGING: + return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, + AXP20X_CHRG_CTRL1_ENABLE, AXP20X_CHRG_CTRL1_ENABLE); + + case POWER_SUPPLY_STATUS_DISCHARGING: + case POWER_SUPPLY_STATUS_NOT_CHARGING: + return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, + AXP20X_CHRG_CTRL1_ENABLE, 0); + } + fallthrough; default: return -EINVAL; } @@ -491,7 +503,8 @@ static enum power_supply_property axp20x_battery_props[] = { static int axp20x_battery_prop_writeable(struct power_supply *psy, enum power_supply_property psp) { - return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN || + return psp == POWER_SUPPLY_PROP_STATUS || + psp == POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN || psp == POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN || psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT || psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX; diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c index 39e16ecb7638..2ba2d8d6b8e6 100644 --- a/drivers/power/supply/axp288_fuel_gauge.c +++ b/drivers/power/supply/axp288_fuel_gauge.c @@ -142,9 +142,7 @@ static int fuel_gauge_reg_readb(struct axp288_fg_info *info, int reg) for (i = 0; i < NR_RETRY_CNT; i++) { ret = regmap_read(info->regmap, reg, &val); - if (ret == -EBUSY) - continue; - else + if (ret != -EBUSY) break; } @@ -676,7 +674,7 @@ intr_failed: * detection reports one despite it not being there. * Please keep this listed sorted alphabetically. */ -static const struct dmi_system_id axp288_fuel_gauge_blacklist[] = { +static const struct dmi_system_id axp288_no_battery_list[] = { { /* ACEPC T8 Cherry Trail Z8350 mini PC */ .matches = { @@ -723,15 +721,6 @@ static const struct dmi_system_id axp288_fuel_gauge_blacklist[] = { DMI_MATCH(DMI_PRODUCT_NAME, "MEEGOPAD T02"), }, }, - { - /* Meegopad T08 */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Default string"), - DMI_MATCH(DMI_BOARD_VENDOR, "To be filled by OEM."), - DMI_MATCH(DMI_BOARD_NAME, "T3 MRD"), - DMI_MATCH(DMI_BOARD_VERSION, "V1.1"), - }, - }, { /* Mele PCG03 Mini PC */ .matches = { DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Mini PC"), @@ -745,6 +734,15 @@ static const struct dmi_system_id axp288_fuel_gauge_blacklist[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"), } }, + { + /* Various Ace PC/Meegopad/MinisForum/Wintel Mini-PCs/HDMI-sticks */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "T3 MRD"), + DMI_MATCH(DMI_CHASSIS_TYPE, "3"), + DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."), + DMI_MATCH(DMI_BIOS_VERSION, "5.11"), + }, + }, {} }; @@ -764,7 +762,7 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev) }; unsigned int val; - if (dmi_check_system(axp288_fuel_gauge_blacklist)) + if (dmi_check_system(axp288_no_battery_list)) return -ENODEV; /* diff --git a/drivers/power/supply/bd70528-charger.c b/drivers/power/supply/bd70528-charger.c deleted file mode 100644 index 7c1f0b99c71b..000000000000 --- a/drivers/power/supply/bd70528-charger.c +++ /dev/null @@ -1,710 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -// -// Copyright (C) 2018 ROHM Semiconductors -// -// power-supply driver for ROHM BD70528 PMIC - -/* - * BD70528 charger HW state machine. - * - * The thermal shutdown state is not drawn. From any other state but - * battery error and suspend it is possible to go to TSD/TMP states - * if temperature is out of bounds. - * - * CHG_RST = H - * or CHG_EN=L - * or (DCIN2_UVLO=L && DCIN1_UVLO=L) - * or (DCIN2_OVLO=H & DCIN1_UVKLO=L) - * - * +--------------+ +--------------+ - * | | | | - * | Any state +-------> | Suspend | - * | | | | - * +--------------+ +------+-------+ - * | - * CHG_EN = H && BAT_DET = H && | - * No errors (temp, bat_ov, UVLO, | - * OVLO...) | - * | - * BAT_OV or +---------v----------+ - * (DBAT && TTRI) | | - * +-----------------+ Trickle Charge | <---------------+ - * | | | | - * | +-------+------------+ | - * | | | - * | | ^ | - * | V_BAT > VTRI_TH | | VBAT < VTRI_TH - 50mV | - * | | | | - * | v | | - * | | | - * | BAT_OV or +----------+----+ | - * | (DBAT && TFST) | | | - * | +----------------+ Fast Charge | | - * | | | | | - * v v +----+----------+ | - * | | - *+----------------+ ILIM_DET=L | ^ ILIM_DET | - *| | & CV_DET=H | | or CV_DET=L | - *| Battery Error | & VBAT > | | or VBAT < VRECHG_TH | - *| | VRECHG_TH | | or IBAT > IFST/x | - *+----------------+ & IBAT < | | | - * IFST/x v | | - * ^ | | - * | +---------+-+ | - * | | | | - * +-------------------+ Top OFF | | - * BAT_OV = H or | | | - * (DBAT && TFST) +-----+-----+ | - * | | - * Stay top-off for 15s | | - * v | - * | - * +--------+ | - * | | | - * | Done +-------------------------+ - * | | - * +--------+ VBAT < VRECHG_TH - */ - -#include <linux/kernel.h> -#include <linux/interrupt.h> -#include <linux/mfd/rohm-bd70528.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/power_supply.h> -#include <linux/linear_range.h> - -#define CHG_STAT_SUSPEND 0x0 -#define CHG_STAT_TRICKLE 0x1 -#define CHG_STAT_FAST 0x3 -#define CHG_STAT_TOPOFF 0xe -#define CHG_STAT_DONE 0xf -#define CHG_STAT_OTP_TRICKLE 0x10 -#define CHG_STAT_OTP_FAST 0x11 -#define CHG_STAT_OTP_DONE 0x12 -#define CHG_STAT_TSD_TRICKLE 0x20 -#define CHG_STAT_TSD_FAST 0x21 -#define CHG_STAT_TSD_TOPOFF 0x22 -#define CHG_STAT_BAT_ERR 0x7f - -static const char *bd70528_charger_model = "BD70528"; -static const char *bd70528_charger_manufacturer = "ROHM Semiconductors"; - -#define BD_ERR_IRQ_HND(_name_, _wrn_) \ -static irqreturn_t bd0528_##_name_##_interrupt(int irq, void *arg) \ -{ \ - struct power_supply *psy = (struct power_supply *)arg; \ - \ - power_supply_changed(psy); \ - dev_err(&psy->dev, (_wrn_)); \ - \ - return IRQ_HANDLED; \ -} - -#define BD_INFO_IRQ_HND(_name_, _wrn_) \ -static irqreturn_t bd0528_##_name_##_interrupt(int irq, void *arg) \ -{ \ - struct power_supply *psy = (struct power_supply *)arg; \ - \ - power_supply_changed(psy); \ - dev_dbg(&psy->dev, (_wrn_)); \ - \ - return IRQ_HANDLED; \ -} - -#define BD_IRQ_HND(_name_) bd0528_##_name_##_interrupt - -struct bd70528_psy { - struct regmap *regmap; - struct device *dev; - struct power_supply *psy; -}; - -BD_ERR_IRQ_HND(BAT_OV_DET, "Battery overvoltage detected\n"); -BD_ERR_IRQ_HND(DBAT_DET, "Dead battery detected\n"); -BD_ERR_IRQ_HND(COLD_DET, "Battery cold\n"); -BD_ERR_IRQ_HND(HOT_DET, "Battery hot\n"); -BD_ERR_IRQ_HND(CHG_TSD, "Charger thermal shutdown\n"); -BD_ERR_IRQ_HND(DCIN2_OV_DET, "DCIN2 overvoltage detected\n"); - -BD_INFO_IRQ_HND(BAT_OV_RES, "Battery voltage back to normal\n"); -BD_INFO_IRQ_HND(COLD_RES, "Battery temperature back to normal\n"); -BD_INFO_IRQ_HND(HOT_RES, "Battery temperature back to normal\n"); -BD_INFO_IRQ_HND(BAT_RMV, "Battery removed\n"); -BD_INFO_IRQ_HND(BAT_DET, "Battery detected\n"); -BD_INFO_IRQ_HND(DCIN2_OV_RES, "DCIN2 voltage back to normal\n"); -BD_INFO_IRQ_HND(DCIN2_RMV, "DCIN2 removed\n"); -BD_INFO_IRQ_HND(DCIN2_DET, "DCIN2 detected\n"); -BD_INFO_IRQ_HND(DCIN1_RMV, "DCIN1 removed\n"); -BD_INFO_IRQ_HND(DCIN1_DET, "DCIN1 detected\n"); - -struct irq_name_pair { - const char *n; - irqreturn_t (*h)(int irq, void *arg); -}; - -static int bd70528_get_irqs(struct platform_device *pdev, - struct bd70528_psy *bdpsy) -{ - int irq, i, ret; - unsigned int mask; - static const struct irq_name_pair bd70528_chg_irqs[] = { - { .n = "bd70528-bat-ov-res", .h = BD_IRQ_HND(BAT_OV_RES) }, - { .n = "bd70528-bat-ov-det", .h = BD_IRQ_HND(BAT_OV_DET) }, - { .n = "bd70528-bat-dead", .h = BD_IRQ_HND(DBAT_DET) }, - { .n = "bd70528-bat-warmed", .h = BD_IRQ_HND(COLD_RES) }, - { .n = "bd70528-bat-cold", .h = BD_IRQ_HND(COLD_DET) }, - { .n = "bd70528-bat-cooled", .h = BD_IRQ_HND(HOT_RES) }, - { .n = "bd70528-bat-hot", .h = BD_IRQ_HND(HOT_DET) }, - { .n = "bd70528-chg-tshd", .h = BD_IRQ_HND(CHG_TSD) }, - { .n = "bd70528-bat-removed", .h = BD_IRQ_HND(BAT_RMV) }, - { .n = "bd70528-bat-detected", .h = BD_IRQ_HND(BAT_DET) }, - { .n = "bd70528-dcin2-ov-res", .h = BD_IRQ_HND(DCIN2_OV_RES) }, - { .n = "bd70528-dcin2-ov-det", .h = BD_IRQ_HND(DCIN2_OV_DET) }, - { .n = "bd70528-dcin2-removed", .h = BD_IRQ_HND(DCIN2_RMV) }, - { .n = "bd70528-dcin2-detected", .h = BD_IRQ_HND(DCIN2_DET) }, - { .n = "bd70528-dcin1-removed", .h = BD_IRQ_HND(DCIN1_RMV) }, - { .n = "bd70528-dcin1-detected", .h = BD_IRQ_HND(DCIN1_DET) }, - }; - - for (i = 0; i < ARRAY_SIZE(bd70528_chg_irqs); i++) { - irq = platform_get_irq_byname(pdev, bd70528_chg_irqs[i].n); - if (irq < 0) { - dev_err(&pdev->dev, "Bad IRQ information for %s (%d)\n", - bd70528_chg_irqs[i].n, irq); - return irq; - } - ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, - bd70528_chg_irqs[i].h, - IRQF_ONESHOT, - bd70528_chg_irqs[i].n, - bdpsy->psy); - - if (ret) - return ret; - } - /* - * BD70528 irq controller is not touching the main mask register. - * So enable the charger block interrupts at main level. We can just - * leave them enabled as irq-controller should disable irqs - * from sub-registers when IRQ is disabled or freed. - */ - mask = BD70528_REG_INT_BAT1_MASK | BD70528_REG_INT_BAT2_MASK; - ret = regmap_update_bits(bdpsy->regmap, - BD70528_REG_INT_MAIN_MASK, mask, 0); - if (ret) - dev_err(&pdev->dev, "Failed to enable charger IRQs\n"); - - return ret; -} - -static int bd70528_get_charger_status(struct bd70528_psy *bdpsy, int *val) -{ - int ret; - unsigned int v; - - ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_CURR_STAT, &v); - if (ret) { - dev_err(bdpsy->dev, "Charger state read failure %d\n", - ret); - return ret; - } - - switch (v & BD70528_MASK_CHG_STAT) { - case CHG_STAT_SUSPEND: - /* Maybe we should check the CHG_TTRI_EN? */ - case CHG_STAT_OTP_TRICKLE: - case CHG_STAT_OTP_FAST: - case CHG_STAT_OTP_DONE: - case CHG_STAT_TSD_TRICKLE: - case CHG_STAT_TSD_FAST: - case CHG_STAT_TSD_TOPOFF: - case CHG_STAT_BAT_ERR: - *val = POWER_SUPPLY_STATUS_NOT_CHARGING; - break; - case CHG_STAT_DONE: - *val = POWER_SUPPLY_STATUS_FULL; - break; - case CHG_STAT_TRICKLE: - case CHG_STAT_FAST: - case CHG_STAT_TOPOFF: - *val = POWER_SUPPLY_STATUS_CHARGING; - break; - default: - *val = POWER_SUPPLY_STATUS_UNKNOWN; - break; - } - - return 0; -} - -static int bd70528_get_charge_type(struct bd70528_psy *bdpsy, int *val) -{ - int ret; - unsigned int v; - - ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_CURR_STAT, &v); - if (ret) { - dev_err(bdpsy->dev, "Charger state read failure %d\n", - ret); - return ret; - } - - switch (v & BD70528_MASK_CHG_STAT) { - case CHG_STAT_TRICKLE: - *val = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; - break; - case CHG_STAT_FAST: - case CHG_STAT_TOPOFF: - *val = POWER_SUPPLY_CHARGE_TYPE_FAST; - break; - case CHG_STAT_DONE: - case CHG_STAT_SUSPEND: - /* Maybe we should check the CHG_TTRI_EN? */ - case CHG_STAT_OTP_TRICKLE: - case CHG_STAT_OTP_FAST: - case CHG_STAT_OTP_DONE: - case CHG_STAT_TSD_TRICKLE: - case CHG_STAT_TSD_FAST: - case CHG_STAT_TSD_TOPOFF: - case CHG_STAT_BAT_ERR: - *val = POWER_SUPPLY_CHARGE_TYPE_NONE; - break; - default: - *val = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN; - break; - } - - return 0; -} - -static int bd70528_get_battery_health(struct bd70528_psy *bdpsy, int *val) -{ - int ret; - unsigned int v; - - ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_BAT_STAT, &v); - if (ret) { - dev_err(bdpsy->dev, "Battery state read failure %d\n", - ret); - return ret; - } - /* No battery? */ - if (!(v & BD70528_MASK_CHG_BAT_DETECT)) - *val = POWER_SUPPLY_HEALTH_DEAD; - else if (v & BD70528_MASK_CHG_BAT_OVERVOLT) - *val = POWER_SUPPLY_HEALTH_OVERVOLTAGE; - else if (v & BD70528_MASK_CHG_BAT_TIMER) - *val = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE; - else - *val = POWER_SUPPLY_HEALTH_GOOD; - - return 0; -} - -static int bd70528_get_online(struct bd70528_psy *bdpsy, int *val) -{ - int ret; - unsigned int v; - - ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_IN_STAT, &v); - if (ret) { - dev_err(bdpsy->dev, "DC1 IN state read failure %d\n", - ret); - return ret; - } - - *val = (v & BD70528_MASK_CHG_DCIN1_UVLO) ? 1 : 0; - - return 0; -} - -static int bd70528_get_present(struct bd70528_psy *bdpsy, int *val) -{ - int ret; - unsigned int v; - - ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_BAT_STAT, &v); - if (ret) { - dev_err(bdpsy->dev, "Battery state read failure %d\n", - ret); - return ret; - } - - *val = (v & BD70528_MASK_CHG_BAT_DETECT) ? 1 : 0; - - return 0; -} - -static const struct linear_range current_limit_ranges[] = { - { - .min = 5, - .step = 1, - .min_sel = 0, - .max_sel = 0x22, - }, - { - .min = 40, - .step = 5, - .min_sel = 0x23, - .max_sel = 0x26, - }, - { - .min = 60, - .step = 20, - .min_sel = 0x27, - .max_sel = 0x2d, - }, - { - .min = 200, - .step = 50, - .min_sel = 0x2e, - .max_sel = 0x34, - }, - { - .min = 500, - .step = 0, - .min_sel = 0x35, - .max_sel = 0x3f, - }, -}; - -/* - * BD70528 would support setting and getting own charge current/ - * voltage for low temperatures. The driver currently only reads - * the charge current at room temperature. We do set both though. - */ -static const struct linear_range warm_charge_curr[] = { - { - .min = 10, - .step = 10, - .min_sel = 0, - .max_sel = 0x12, - }, - { - .min = 200, - .step = 25, - .min_sel = 0x13, - .max_sel = 0x1f, - }, -}; - -/* - * Cold charge current selectors are identical to warm charge current - * selectors. The difference is that only smaller currents are available - * at cold charge range. - */ -#define MAX_COLD_CHG_CURR_SEL 0x15 -#define MAX_WARM_CHG_CURR_SEL 0x1f -#define MIN_CHG_CURR_SEL 0x0 - -static int get_charge_current(struct bd70528_psy *bdpsy, int *ma) -{ - unsigned int sel; - int ret; - - ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_CHG_CURR_WARM, - &sel); - if (ret) { - dev_err(bdpsy->dev, - "Charge current reading failed (%d)\n", ret); - return ret; - } - - sel &= BD70528_MASK_CHG_CHG_CURR; - - ret = linear_range_get_value_array(&warm_charge_curr[0], - ARRAY_SIZE(warm_charge_curr), - sel, ma); - if (ret) { - dev_err(bdpsy->dev, - "Unknown charge current value 0x%x\n", - sel); - } - - return ret; -} - -static int get_current_limit(struct bd70528_psy *bdpsy, int *ma) -{ - unsigned int sel; - int ret; - - ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_DCIN_ILIM, - &sel); - - if (ret) { - dev_err(bdpsy->dev, - "Input current limit reading failed (%d)\n", ret); - return ret; - } - - sel &= BD70528_MASK_CHG_DCIN_ILIM; - - ret = linear_range_get_value_array(¤t_limit_ranges[0], - ARRAY_SIZE(current_limit_ranges), - sel, ma); - if (ret) { - /* Unspecified values mean 500 mA */ - *ma = 500; - } - return 0; -} - -static enum power_supply_property bd70528_charger_props[] = { - POWER_SUPPLY_PROP_STATUS, - POWER_SUPPLY_PROP_CHARGE_TYPE, - POWER_SUPPLY_PROP_HEALTH, - POWER_SUPPLY_PROP_PRESENT, - POWER_SUPPLY_PROP_ONLINE, - POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, - POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, - POWER_SUPPLY_PROP_MODEL_NAME, - POWER_SUPPLY_PROP_MANUFACTURER, -}; - -static int bd70528_charger_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct bd70528_psy *bdpsy = power_supply_get_drvdata(psy); - int ret = 0; - - switch (psp) { - case POWER_SUPPLY_PROP_STATUS: - return bd70528_get_charger_status(bdpsy, &val->intval); - case POWER_SUPPLY_PROP_CHARGE_TYPE: - return bd70528_get_charge_type(bdpsy, &val->intval); - case POWER_SUPPLY_PROP_HEALTH: - return bd70528_get_battery_health(bdpsy, &val->intval); - case POWER_SUPPLY_PROP_PRESENT: - return bd70528_get_present(bdpsy, &val->intval); - case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: - ret = get_current_limit(bdpsy, &val->intval); - val->intval *= 1000; - return ret; - case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: - ret = get_charge_current(bdpsy, &val->intval); - val->intval *= 1000; - return ret; - case POWER_SUPPLY_PROP_ONLINE: - return bd70528_get_online(bdpsy, &val->intval); - case POWER_SUPPLY_PROP_MODEL_NAME: - val->strval = bd70528_charger_model; - return 0; - case POWER_SUPPLY_PROP_MANUFACTURER: - val->strval = bd70528_charger_manufacturer; - return 0; - default: - break; - } - - return -EINVAL; -} - -static int bd70528_prop_is_writable(struct power_supply *psy, - enum power_supply_property psp) -{ - switch (psp) { - case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: - case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: - return 1; - default: - break; - } - return 0; -} - -static int set_charge_current(struct bd70528_psy *bdpsy, int ma) -{ - unsigned int reg; - int ret = 0, tmpret; - bool found; - - if (ma > 500) { - dev_warn(bdpsy->dev, - "Requested charge current %u exceed maximum (500mA)\n", - ma); - reg = MAX_WARM_CHG_CURR_SEL; - goto set; - } - if (ma < 10) { - dev_err(bdpsy->dev, - "Requested charge current %u smaller than min (10mA)\n", - ma); - reg = MIN_CHG_CURR_SEL; - ret = -EINVAL; - goto set; - } - -/* - * For BD70528 voltage/current limits we happily accept any value which - * belongs the range. We could check if value matching the selector is - * desired by computing the range min + (sel - sel_low) * range step - but - * I guess it is enough if we use voltage/current which is closest (below) - * the requested? - */ - - ret = linear_range_get_selector_low_array(warm_charge_curr, - ARRAY_SIZE(warm_charge_curr), - ma, ®, &found); - if (ret) { - dev_err(bdpsy->dev, - "Unsupported charge current %u mA\n", ma); - reg = MIN_CHG_CURR_SEL; - goto set; - } - if (!found) { - /* - * There was a gap in supported values and we hit it. - * Yet a smaller value was found so we use it. - */ - dev_warn(bdpsy->dev, - "Unsupported charge current %u mA\n", ma); - } -set: - - tmpret = regmap_update_bits(bdpsy->regmap, - BD70528_REG_CHG_CHG_CURR_WARM, - BD70528_MASK_CHG_CHG_CURR, reg); - if (tmpret) - dev_err(bdpsy->dev, - "Charge current write failure (%d)\n", tmpret); - - if (reg > MAX_COLD_CHG_CURR_SEL) - reg = MAX_COLD_CHG_CURR_SEL; - - if (!tmpret) - tmpret = regmap_update_bits(bdpsy->regmap, - BD70528_REG_CHG_CHG_CURR_COLD, - BD70528_MASK_CHG_CHG_CURR, reg); - - if (!ret) - ret = tmpret; - - return ret; -} - -#define MAX_CURR_LIMIT_SEL 0x34 -#define MIN_CURR_LIMIT_SEL 0x0 - -static int set_current_limit(struct bd70528_psy *bdpsy, int ma) -{ - unsigned int reg; - int ret = 0, tmpret; - bool found; - - if (ma > 500) { - dev_warn(bdpsy->dev, - "Requested current limit %u exceed maximum (500mA)\n", - ma); - reg = MAX_CURR_LIMIT_SEL; - goto set; - } - if (ma < 5) { - dev_err(bdpsy->dev, - "Requested current limit %u smaller than min (5mA)\n", - ma); - reg = MIN_CURR_LIMIT_SEL; - ret = -EINVAL; - goto set; - } - - ret = linear_range_get_selector_low_array(current_limit_ranges, - ARRAY_SIZE(current_limit_ranges), - ma, ®, &found); - if (ret) { - dev_err(bdpsy->dev, "Unsupported current limit %umA\n", ma); - reg = MIN_CURR_LIMIT_SEL; - goto set; - } - if (!found) { - /* - * There was a gap in supported values and we hit it. - * We found a smaller value from ranges and use it. - * Warn user though. - */ - dev_warn(bdpsy->dev, "Unsupported current limit %umA\n", ma); - } - -set: - tmpret = regmap_update_bits(bdpsy->regmap, - BD70528_REG_CHG_DCIN_ILIM, - BD70528_MASK_CHG_DCIN_ILIM, reg); - - if (!ret) - ret = tmpret; - - return ret; -} - -static int bd70528_charger_set_property(struct power_supply *psy, - enum power_supply_property psp, - const union power_supply_propval *val) -{ - struct bd70528_psy *bdpsy = power_supply_get_drvdata(psy); - - switch (psp) { - case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: - return set_current_limit(bdpsy, val->intval / 1000); - case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: - return set_charge_current(bdpsy, val->intval / 1000); - default: - break; - } - return -EINVAL; -} - -static const struct power_supply_desc bd70528_charger_desc = { - .name = "bd70528-charger", - .type = POWER_SUPPLY_TYPE_MAINS, - .properties = bd70528_charger_props, - .num_properties = ARRAY_SIZE(bd70528_charger_props), - .get_property = bd70528_charger_get_property, - .set_property = bd70528_charger_set_property, - .property_is_writeable = bd70528_prop_is_writable, -}; - -static int bd70528_power_probe(struct platform_device *pdev) -{ - struct bd70528_psy *bdpsy; - struct power_supply_config cfg = {}; - - bdpsy = devm_kzalloc(&pdev->dev, sizeof(*bdpsy), GFP_KERNEL); - if (!bdpsy) - return -ENOMEM; - - bdpsy->regmap = dev_get_regmap(pdev->dev.parent, NULL); - if (!bdpsy->regmap) { - dev_err(&pdev->dev, "No regmap found for chip\n"); - return -EINVAL; - } - bdpsy->dev = &pdev->dev; - - platform_set_drvdata(pdev, bdpsy); - cfg.drv_data = bdpsy; - cfg.of_node = pdev->dev.parent->of_node; - - bdpsy->psy = devm_power_supply_register(&pdev->dev, - &bd70528_charger_desc, &cfg); - if (IS_ERR(bdpsy->psy)) { - dev_err(&pdev->dev, "failed: power supply register\n"); - return PTR_ERR(bdpsy->psy); - } - - return bd70528_get_irqs(pdev, bdpsy); -} - -static struct platform_driver bd70528_power = { - .driver = { - .name = "bd70528-power" - }, - .probe = bd70528_power_probe, -}; - -module_platform_driver(bd70528_power); - -MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); -MODULE_DESCRIPTION("BD70528 power-supply driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:bd70528-power"); diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index 852e86bfe2fb..35ff0c8fe96f 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -5,11 +5,10 @@ * Author: Mark A. Greer <mgreer@animalcreek.com> */ +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/interrupt.h> #include <linux/delay.h> -#include <linux/of_irq.h> -#include <linux/of_device.h> #include <linux/pm_runtime.h> #include <linux/power_supply.h> #include <linux/power/bq24190_charger.h> @@ -1959,7 +1958,6 @@ static const struct i2c_device_id bq24190_i2c_ids[] = { }; MODULE_DEVICE_TABLE(i2c, bq24190_i2c_ids); -#ifdef CONFIG_OF static const struct of_device_id bq24190_of_match[] = { { .compatible = "ti,bq24190", }, { .compatible = "ti,bq24192", }, @@ -1968,11 +1966,6 @@ static const struct of_device_id bq24190_of_match[] = { { }, }; MODULE_DEVICE_TABLE(of, bq24190_of_match); -#else -static const struct of_device_id bq24190_of_match[] = { - { }, -}; -#endif static struct i2c_driver bq24190_driver = { .probe = bq24190_probe, @@ -1981,7 +1974,7 @@ static struct i2c_driver bq24190_driver = { .driver = { .name = "bq24190-charger", .pm = &bq24190_pm_ops, - .of_match_table = of_match_ptr(bq24190_of_match), + .of_match_table = bq24190_of_match, }, }; module_i2c_driver(bq24190_driver); diff --git a/drivers/power/supply/charger-manager.c b/drivers/power/supply/charger-manager.c index 45da870aecca..d67edb760c94 100644 --- a/drivers/power/supply/charger-manager.c +++ b/drivers/power/supply/charger-manager.c @@ -1279,6 +1279,7 @@ static const struct of_device_id charger_manager_match[] = { }, {}, }; +MODULE_DEVICE_TABLE(of, charger_manager_match); static struct charger_desc *of_cm_parse_desc(struct device *dev) { diff --git a/drivers/power/supply/cpcap-battery.c b/drivers/power/supply/cpcap-battery.c index a3fc0084cda0..8d62d4241da3 100644 --- a/drivers/power/supply/cpcap-battery.c +++ b/drivers/power/supply/cpcap-battery.c @@ -667,10 +667,23 @@ static int cpcap_battery_get_property(struct power_supply *psy, if (!empty->voltage) return -ENODATA; val->intval = empty->counter_uah - latest->counter_uah; - if (val->intval < 0) + if (val->intval < 0) { + /* Assume invalid config if CHARGE_NOW is -20% */ + if (ddata->charge_full && abs(val->intval) > ddata->charge_full/5) { + empty->voltage = 0; + ddata->charge_full = 0; + return -ENODATA; + } val->intval = 0; - else if (ddata->charge_full && ddata->charge_full < val->intval) + } else if (ddata->charge_full && ddata->charge_full < val->intval) { + /* Assume invalid config if CHARGE_NOW exceeds CHARGE_FULL by 20% */ + if (val->intval > (6*ddata->charge_full)/5) { + empty->voltage = 0; + ddata->charge_full = 0; + return -ENODATA; + } val->intval = ddata->charge_full; + } break; case POWER_SUPPLY_PROP_CHARGE_FULL: if (!ddata->charge_full) @@ -747,7 +760,7 @@ static int cpcap_battery_set_property(struct power_supply *psy, case POWER_SUPPLY_PROP_CHARGE_FULL: if (val->intval < 0) return -EINVAL; - if (val->intval > ddata->config.info.charge_full_design) + if (val->intval > (6*ddata->config.info.charge_full_design)/5) return -EINVAL; ddata->charge_full = val->intval; diff --git a/drivers/power/supply/cpcap-charger.c b/drivers/power/supply/cpcap-charger.c index df01abc49ce8..60e0ce105a29 100644 --- a/drivers/power/supply/cpcap-charger.c +++ b/drivers/power/supply/cpcap-charger.c @@ -173,23 +173,6 @@ static enum power_supply_property cpcap_charger_props[] = { POWER_SUPPLY_PROP_CURRENT_NOW, }; -/* No battery always shows temperature of -40000 */ -static bool cpcap_charger_battery_found(struct cpcap_charger_ddata *ddata) -{ - struct iio_channel *channel; - int error, temperature; - - channel = ddata->channels[CPCAP_CHARGER_IIO_BATTDET]; - error = iio_read_channel_processed(channel, &temperature); - if (error < 0) { - dev_warn(ddata->dev, "%s failed: %i\n", __func__, error); - - return false; - } - - return temperature > -20000 && temperature < 60000; -} - static int cpcap_charger_get_charge_voltage(struct cpcap_charger_ddata *ddata) { struct iio_channel *channel; @@ -700,11 +683,29 @@ static void cpcap_usb_detect(struct work_struct *work) if (!ddata->feeding_vbus && cpcap_charger_vbus_valid(ddata) && s.chrgcurr1) { - int max_current = 532000; + int max_current; int vchrg, ichrg; + union power_supply_propval val; + struct power_supply *battery; - if (cpcap_charger_battery_found(ddata)) + battery = power_supply_get_by_name("battery"); + if (IS_ERR_OR_NULL(battery)) { + dev_err(ddata->dev, "battery power_supply not available %li\n", + PTR_ERR(battery)); + return; + } + + error = power_supply_get_property(battery, POWER_SUPPLY_PROP_PRESENT, &val); + power_supply_put(battery); + if (error) + goto out_err; + + if (val.intval) { max_current = 1596000; + } else { + dev_info(ddata->dev, "battery not inserted, charging disabled\n"); + max_current = 0; + } if (max_current > ddata->limit_current) max_current = ddata->limit_current; diff --git a/drivers/power/supply/max17040_battery.c b/drivers/power/supply/max17040_battery.c index 1aab868adabf..3cea92e28dc3 100644 --- a/drivers/power/supply/max17040_battery.c +++ b/drivers/power/supply/max17040_battery.c @@ -16,7 +16,6 @@ #include <linux/interrupt.h> #include <linux/power_supply.h> #include <linux/of_device.h> -#include <linux/max17040_battery.h> #include <linux/regmap.h> #include <linux/slab.h> @@ -142,13 +141,10 @@ struct max17040_chip { struct regmap *regmap; struct delayed_work work; struct power_supply *battery; - struct max17040_platform_data *pdata; struct chip_data data; /* battery capacity */ int soc; - /* State Of Charge */ - int status; /* Low alert threshold from 32% to 1% of the State of Charge */ u32 low_soc_alert; /* some devices return twice the capacity */ @@ -221,26 +217,7 @@ static int max17040_get_version(struct max17040_chip *chip) static int max17040_get_online(struct max17040_chip *chip) { - return chip->pdata && chip->pdata->battery_online ? - chip->pdata->battery_online() : 1; -} - -static int max17040_get_status(struct max17040_chip *chip) -{ - if (!chip->pdata || !chip->pdata->charger_online - || !chip->pdata->charger_enable) - return POWER_SUPPLY_STATUS_UNKNOWN; - - if (max17040_get_soc(chip) > MAX17040_BATTERY_FULL) - return POWER_SUPPLY_STATUS_FULL; - - if (chip->pdata->charger_online()) - if (chip->pdata->charger_enable()) - return POWER_SUPPLY_STATUS_CHARGING; - else - return POWER_SUPPLY_STATUS_NOT_CHARGING; - else - return POWER_SUPPLY_STATUS_DISCHARGING; + return 1; } static int max17040_get_of_data(struct max17040_chip *chip) @@ -283,7 +260,6 @@ static int max17040_get_of_data(struct max17040_chip *chip) static void max17040_check_changes(struct max17040_chip *chip) { chip->soc = max17040_get_soc(chip); - chip->status = max17040_get_status(chip); } static void max17040_queue_work(struct max17040_chip *chip) @@ -302,17 +278,16 @@ static void max17040_stop_work(void *data) static void max17040_work(struct work_struct *work) { struct max17040_chip *chip; - int last_soc, last_status; + int last_soc; chip = container_of(work, struct max17040_chip, work.work); - /* store SOC and status to check changes */ + /* store SOC to check changes */ last_soc = chip->soc; - last_status = chip->status; max17040_check_changes(chip); /* check changes and send uevent */ - if (last_soc != chip->soc || last_status != chip->status) + if (last_soc != chip->soc) power_supply_changed(chip->battery); max17040_queue_work(chip); @@ -361,12 +336,10 @@ static irqreturn_t max17040_thread_handler(int id, void *dev) static int max17040_enable_alert_irq(struct max17040_chip *chip) { struct i2c_client *client = chip->client; - unsigned int flags; int ret; - flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, - max17040_thread_handler, flags, + max17040_thread_handler, IRQF_ONESHOT, chip->battery->desc->name, chip); return ret; @@ -415,9 +388,6 @@ static int max17040_get_property(struct power_supply *psy, struct max17040_chip *chip = power_supply_get_drvdata(psy); switch (psp) { - case POWER_SUPPLY_PROP_STATUS: - val->intval = max17040_get_status(chip); - break; case POWER_SUPPLY_PROP_ONLINE: val->intval = max17040_get_online(chip); break; @@ -444,7 +414,6 @@ static const struct regmap_config max17040_regmap = { }; static enum power_supply_property max17040_battery_props[] = { - POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_ONLINE, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CAPACITY, @@ -480,7 +449,6 @@ static int max17040_probe(struct i2c_client *client, chip->client = client; chip->regmap = devm_regmap_init_i2c(client, &max17040_regmap); - chip->pdata = client->dev.platform_data; chip_id = (enum chip_id) id->driver_data; if (client->dev.of_node) { ret = max17040_get_of_data(chip); diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 1d7326cd8fc6..ce2041b30a06 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -1104,7 +1104,7 @@ static int max17042_probe(struct i2c_client *client, } if (client->irq) { - unsigned int flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; + unsigned int flags = IRQF_ONESHOT; /* * On ACPI systems the IRQ may be handled by ACPI-event code, diff --git a/drivers/power/supply/pm2301_charger.c b/drivers/power/supply/pm2301_charger.c deleted file mode 100644 index f86bbbeaff6c..000000000000 --- a/drivers/power/supply/pm2301_charger.c +++ /dev/null @@ -1,1249 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright 2012 ST Ericsson. - * - * Power supply driver for ST Ericsson pm2xxx_charger charger - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <linux/power_supply.h> -#include <linux/regulator/consumer.h> -#include <linux/err.h> -#include <linux/i2c.h> -#include <linux/workqueue.h> -#include <linux/mfd/abx500/ab8500.h> -#include <linux/pm2301_charger.h> -#include <linux/gpio.h> -#include <linux/pm_runtime.h> -#include <linux/pm.h> - -#include "ab8500-bm.h" -#include "ab8500-chargalg.h" -#include "pm2301_charger.h" - -#define to_pm2xxx_charger_ac_device_info(x) container_of((x), \ - struct pm2xxx_charger, ac_chg) -#define SLEEP_MIN 50 -#define SLEEP_MAX 100 -#define PM2XXX_AUTOSUSPEND_DELAY 500 - -static int pm2xxx_interrupt_registers[] = { - PM2XXX_REG_INT1, - PM2XXX_REG_INT2, - PM2XXX_REG_INT3, - PM2XXX_REG_INT4, - PM2XXX_REG_INT5, - PM2XXX_REG_INT6, -}; - -static enum power_supply_property pm2xxx_charger_ac_props[] = { - POWER_SUPPLY_PROP_HEALTH, - POWER_SUPPLY_PROP_PRESENT, - POWER_SUPPLY_PROP_ONLINE, - POWER_SUPPLY_PROP_VOLTAGE_AVG, -}; - -static int pm2xxx_charger_voltage_map[] = { - 3500, - 3525, - 3550, - 3575, - 3600, - 3625, - 3650, - 3675, - 3700, - 3725, - 3750, - 3775, - 3800, - 3825, - 3850, - 3875, - 3900, - 3925, - 3950, - 3975, - 4000, - 4025, - 4050, - 4075, - 4100, - 4125, - 4150, - 4175, - 4200, - 4225, - 4250, - 4275, - 4300, -}; - -static int pm2xxx_charger_current_map[] = { - 200, - 200, - 400, - 600, - 800, - 1000, - 1200, - 1400, - 1600, - 1800, - 2000, - 2200, - 2400, - 2600, - 2800, - 3000, -}; - -static void set_lpn_pin(struct pm2xxx_charger *pm2) -{ - if (!pm2->ac.charger_connected && gpio_is_valid(pm2->lpn_pin)) { - gpio_set_value(pm2->lpn_pin, 1); - usleep_range(SLEEP_MIN, SLEEP_MAX); - } -} - -static void clear_lpn_pin(struct pm2xxx_charger *pm2) -{ - if (!pm2->ac.charger_connected && gpio_is_valid(pm2->lpn_pin)) - gpio_set_value(pm2->lpn_pin, 0); -} - -static int pm2xxx_reg_read(struct pm2xxx_charger *pm2, int reg, u8 *val) -{ - int ret; - - /* wake up the device */ - pm_runtime_get_sync(pm2->dev); - - ret = i2c_smbus_read_i2c_block_data(pm2->config.pm2xxx_i2c, reg, - 1, val); - if (ret < 0) - dev_err(pm2->dev, "Error reading register at 0x%x\n", reg); - else - ret = 0; - - pm_runtime_put_sync(pm2->dev); - - return ret; -} - -static int pm2xxx_reg_write(struct pm2xxx_charger *pm2, int reg, u8 val) -{ - int ret; - - /* wake up the device */ - pm_runtime_get_sync(pm2->dev); - - ret = i2c_smbus_write_i2c_block_data(pm2->config.pm2xxx_i2c, reg, - 1, &val); - if (ret < 0) - dev_err(pm2->dev, "Error writing register at 0x%x\n", reg); - else - ret = 0; - - pm_runtime_put_sync(pm2->dev); - - return ret; -} - -static int pm2xxx_charging_enable_mngt(struct pm2xxx_charger *pm2) -{ - int ret; - - /* Enable charging */ - ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG2, - (PM2XXX_CH_AUTO_RESUME_EN | PM2XXX_CHARGER_ENA)); - - return ret; -} - -static int pm2xxx_charging_disable_mngt(struct pm2xxx_charger *pm2) -{ - int ret; - - /* Disable SW EOC ctrl */ - ret = pm2xxx_reg_write(pm2, PM2XXX_SW_CTRL_REG, PM2XXX_SWCTRL_HW); - if (ret < 0) { - dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__); - return ret; - } - - /* Disable charging */ - ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG2, - (PM2XXX_CH_AUTO_RESUME_DIS | PM2XXX_CHARGER_DIS)); - if (ret < 0) { - dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__); - return ret; - } - - return 0; -} - -static int pm2xxx_charger_batt_therm_mngt(struct pm2xxx_charger *pm2, int val) -{ - queue_work(pm2->charger_wq, &pm2->check_main_thermal_prot_work); - - return 0; -} - - -static int pm2xxx_charger_die_therm_mngt(struct pm2xxx_charger *pm2, int val) -{ - queue_work(pm2->charger_wq, &pm2->check_main_thermal_prot_work); - - return 0; -} - -static int pm2xxx_charger_ovv_mngt(struct pm2xxx_charger *pm2, int val) -{ - dev_err(pm2->dev, "Overvoltage detected\n"); - pm2->flags.ovv = true; - power_supply_changed(pm2->ac_chg.psy); - - /* Schedule a new HW failure check */ - queue_delayed_work(pm2->charger_wq, &pm2->check_hw_failure_work, 0); - - return 0; -} - -static int pm2xxx_charger_wd_exp_mngt(struct pm2xxx_charger *pm2, int val) -{ - dev_dbg(pm2->dev , "20 minutes watchdog expired\n"); - - pm2->ac.wd_expired = true; - power_supply_changed(pm2->ac_chg.psy); - - return 0; -} - -static int pm2xxx_charger_vbat_lsig_mngt(struct pm2xxx_charger *pm2, int val) -{ - int ret; - - switch (val) { - case PM2XXX_INT1_ITVBATLOWR: - dev_dbg(pm2->dev, "VBAT grows above VBAT_LOW level\n"); - /* Enable SW EOC ctrl */ - ret = pm2xxx_reg_write(pm2, PM2XXX_SW_CTRL_REG, - PM2XXX_SWCTRL_SW); - if (ret < 0) { - dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__); - return ret; - } - break; - - case PM2XXX_INT1_ITVBATLOWF: - dev_dbg(pm2->dev, "VBAT drops below VBAT_LOW level\n"); - /* Disable SW EOC ctrl */ - ret = pm2xxx_reg_write(pm2, PM2XXX_SW_CTRL_REG, - PM2XXX_SWCTRL_HW); - if (ret < 0) { - dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__); - return ret; - } - break; - - default: - dev_err(pm2->dev, "Unknown VBAT level\n"); - } - - return 0; -} - -static int pm2xxx_charger_bat_disc_mngt(struct pm2xxx_charger *pm2, int val) -{ - dev_dbg(pm2->dev, "battery disconnected\n"); - - return 0; -} - -static int pm2xxx_charger_detection(struct pm2xxx_charger *pm2, u8 *val) -{ - int ret; - - ret = pm2xxx_reg_read(pm2, PM2XXX_SRCE_REG_INT2, val); - - if (ret < 0) { - dev_err(pm2->dev, "Charger detection failed\n"); - goto out; - } - - *val &= (PM2XXX_INT2_S_ITVPWR1PLUG | PM2XXX_INT2_S_ITVPWR2PLUG); - -out: - return ret; -} - -static int pm2xxx_charger_itv_pwr_plug_mngt(struct pm2xxx_charger *pm2, int val) -{ - - int ret; - u8 read_val; - - /* - * Since we can't be sure that the events are received - * synchronously, we have the check if the main charger is - * connected by reading the interrupt source register. - */ - ret = pm2xxx_charger_detection(pm2, &read_val); - - if ((ret == 0) && read_val) { - pm2->ac.charger_connected = 1; - pm2->ac_conn = true; - queue_work(pm2->charger_wq, &pm2->ac_work); - } - - - return ret; -} - -static int pm2xxx_charger_itv_pwr_unplug_mngt(struct pm2xxx_charger *pm2, - int val) -{ - pm2->ac.charger_connected = 0; - queue_work(pm2->charger_wq, &pm2->ac_work); - - return 0; -} - -static int pm2_int_reg0(void *pm2_data, int val) -{ - struct pm2xxx_charger *pm2 = pm2_data; - int ret = 0; - - if (val & PM2XXX_INT1_ITVBATLOWR) { - ret = pm2xxx_charger_vbat_lsig_mngt(pm2, - PM2XXX_INT1_ITVBATLOWR); - if (ret < 0) - goto out; - } - - if (val & PM2XXX_INT1_ITVBATLOWF) { - ret = pm2xxx_charger_vbat_lsig_mngt(pm2, - PM2XXX_INT1_ITVBATLOWF); - if (ret < 0) - goto out; - } - - if (val & PM2XXX_INT1_ITVBATDISCONNECT) { - ret = pm2xxx_charger_bat_disc_mngt(pm2, - PM2XXX_INT1_ITVBATDISCONNECT); - if (ret < 0) - goto out; - } -out: - return ret; -} - -static int pm2_int_reg1(void *pm2_data, int val) -{ - struct pm2xxx_charger *pm2 = pm2_data; - int ret = 0; - - if (val & (PM2XXX_INT2_ITVPWR1PLUG | PM2XXX_INT2_ITVPWR2PLUG)) { - dev_dbg(pm2->dev , "Main charger plugged\n"); - ret = pm2xxx_charger_itv_pwr_plug_mngt(pm2, val & - (PM2XXX_INT2_ITVPWR1PLUG | PM2XXX_INT2_ITVPWR2PLUG)); - } - - if (val & - (PM2XXX_INT2_ITVPWR1UNPLUG | PM2XXX_INT2_ITVPWR2UNPLUG)) { - dev_dbg(pm2->dev , "Main charger unplugged\n"); - ret = pm2xxx_charger_itv_pwr_unplug_mngt(pm2, val & - (PM2XXX_INT2_ITVPWR1UNPLUG | - PM2XXX_INT2_ITVPWR2UNPLUG)); - } - - return ret; -} - -static int pm2_int_reg2(void *pm2_data, int val) -{ - struct pm2xxx_charger *pm2 = pm2_data; - int ret = 0; - - if (val & PM2XXX_INT3_ITAUTOTIMEOUTWD) - ret = pm2xxx_charger_wd_exp_mngt(pm2, val); - - if (val & (PM2XXX_INT3_ITCHPRECHARGEWD | - PM2XXX_INT3_ITCHCCWD | PM2XXX_INT3_ITCHCVWD)) { - dev_dbg(pm2->dev, - "Watchdog occurred for precharge, CC and CV charge\n"); - } - - return ret; -} - -static int pm2_int_reg3(void *pm2_data, int val) -{ - struct pm2xxx_charger *pm2 = pm2_data; - int ret = 0; - - if (val & (PM2XXX_INT4_ITCHARGINGON)) { - dev_dbg(pm2->dev , - "charging operation has started\n"); - } - - if (val & (PM2XXX_INT4_ITVRESUME)) { - dev_dbg(pm2->dev, - "battery discharged down to VResume threshold\n"); - } - - if (val & (PM2XXX_INT4_ITBATTFULL)) { - dev_dbg(pm2->dev , "battery fully detected\n"); - } - - if (val & (PM2XXX_INT4_ITCVPHASE)) { - dev_dbg(pm2->dev, "CV phase enter with 0.5C charging\n"); - } - - if (val & (PM2XXX_INT4_ITVPWR2OVV | PM2XXX_INT4_ITVPWR1OVV)) { - pm2->failure_case = VPWR_OVV; - ret = pm2xxx_charger_ovv_mngt(pm2, val & - (PM2XXX_INT4_ITVPWR2OVV | PM2XXX_INT4_ITVPWR1OVV)); - dev_dbg(pm2->dev, "VPWR/VSYSTEM overvoltage detected\n"); - } - - if (val & (PM2XXX_INT4_S_ITBATTEMPCOLD | - PM2XXX_INT4_S_ITBATTEMPHOT)) { - ret = pm2xxx_charger_batt_therm_mngt(pm2, val & - (PM2XXX_INT4_S_ITBATTEMPCOLD | - PM2XXX_INT4_S_ITBATTEMPHOT)); - dev_dbg(pm2->dev, "BTEMP is too Low/High\n"); - } - - return ret; -} - -static int pm2_int_reg4(void *pm2_data, int val) -{ - struct pm2xxx_charger *pm2 = pm2_data; - int ret = 0; - - if (val & PM2XXX_INT5_ITVSYSTEMOVV) { - pm2->failure_case = VSYSTEM_OVV; - ret = pm2xxx_charger_ovv_mngt(pm2, val & - PM2XXX_INT5_ITVSYSTEMOVV); - dev_dbg(pm2->dev, "VSYSTEM overvoltage detected\n"); - } - - if (val & (PM2XXX_INT5_ITTHERMALWARNINGFALL | - PM2XXX_INT5_ITTHERMALWARNINGRISE | - PM2XXX_INT5_ITTHERMALSHUTDOWNFALL | - PM2XXX_INT5_ITTHERMALSHUTDOWNRISE)) { - dev_dbg(pm2->dev, "BTEMP die temperature is too Low/High\n"); - ret = pm2xxx_charger_die_therm_mngt(pm2, val & - (PM2XXX_INT5_ITTHERMALWARNINGFALL | - PM2XXX_INT5_ITTHERMALWARNINGRISE | - PM2XXX_INT5_ITTHERMALSHUTDOWNFALL | - PM2XXX_INT5_ITTHERMALSHUTDOWNRISE)); - } - - return ret; -} - -static int pm2_int_reg5(void *pm2_data, int val) -{ - struct pm2xxx_charger *pm2 = pm2_data; - - if (val & (PM2XXX_INT6_ITVPWR2DROP | PM2XXX_INT6_ITVPWR1DROP)) { - dev_dbg(pm2->dev, "VMPWR drop to VBAT level\n"); - } - - if (val & (PM2XXX_INT6_ITVPWR2VALIDRISE | - PM2XXX_INT6_ITVPWR1VALIDRISE | - PM2XXX_INT6_ITVPWR2VALIDFALL | - PM2XXX_INT6_ITVPWR1VALIDFALL)) { - dev_dbg(pm2->dev, "Falling/Rising edge on WPWR1/2\n"); - } - - return 0; -} - -static irqreturn_t pm2xxx_irq_int(int irq, void *data) -{ - struct pm2xxx_charger *pm2 = data; - struct pm2xxx_interrupts *interrupt = pm2->pm2_int; - int i; - - /* wake up the device */ - pm_runtime_get_sync(pm2->dev); - - do { - for (i = 0; i < PM2XXX_NUM_INT_REG; i++) { - pm2xxx_reg_read(pm2, - pm2xxx_interrupt_registers[i], - &(interrupt->reg[i])); - - if (interrupt->reg[i] > 0) - interrupt->handler[i](pm2, interrupt->reg[i]); - } - } while (gpio_get_value(pm2->pdata->gpio_irq_number) == 0); - - pm_runtime_mark_last_busy(pm2->dev); - pm_runtime_put_autosuspend(pm2->dev); - - return IRQ_HANDLED; -} - -static int pm2xxx_charger_get_ac_cv(struct pm2xxx_charger *pm2) -{ - int ret = 0; - u8 val; - - if (pm2->ac.charger_connected && pm2->ac.charger_online) { - - ret = pm2xxx_reg_read(pm2, PM2XXX_SRCE_REG_INT4, &val); - if (ret < 0) { - dev_err(pm2->dev, "%s pm2xxx read failed\n", __func__); - goto out; - } - - if (val & PM2XXX_INT4_S_ITCVPHASE) - ret = PM2XXX_CONST_VOLT; - else - ret = PM2XXX_CONST_CURR; - } -out: - return ret; -} - -static int pm2xxx_current_to_regval(int curr) -{ - int i; - - if (curr < pm2xxx_charger_current_map[0]) - return 0; - - for (i = 1; i < ARRAY_SIZE(pm2xxx_charger_current_map); i++) { - if (curr < pm2xxx_charger_current_map[i]) - return (i - 1); - } - - i = ARRAY_SIZE(pm2xxx_charger_current_map) - 1; - if (curr == pm2xxx_charger_current_map[i]) - return i; - else - return -EINVAL; -} - -static int pm2xxx_voltage_to_regval(int curr) -{ - int i; - - if (curr < pm2xxx_charger_voltage_map[0]) - return 0; - - for (i = 1; i < ARRAY_SIZE(pm2xxx_charger_voltage_map); i++) { - if (curr < pm2xxx_charger_voltage_map[i]) - return i - 1; - } - - i = ARRAY_SIZE(pm2xxx_charger_voltage_map) - 1; - if (curr == pm2xxx_charger_voltage_map[i]) - return i; - else - return -EINVAL; -} - -static int pm2xxx_charger_update_charger_current(struct ux500_charger *charger, - int ich_out) -{ - int ret; - int curr_index; - struct pm2xxx_charger *pm2; - u8 val; - - if (charger->psy->desc->type == POWER_SUPPLY_TYPE_MAINS) - pm2 = to_pm2xxx_charger_ac_device_info(charger); - else - return -ENXIO; - - curr_index = pm2xxx_current_to_regval(ich_out); - if (curr_index < 0) { - dev_err(pm2->dev, - "Charger current too high, charging not started\n"); - return -ENXIO; - } - - ret = pm2xxx_reg_read(pm2, PM2XXX_BATT_CTRL_REG6, &val); - if (ret >= 0) { - val &= ~PM2XXX_DIR_CH_CC_CURRENT_MASK; - val |= curr_index; - ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG6, val); - if (ret < 0) { - dev_err(pm2->dev, - "%s write failed\n", __func__); - } - } - else - dev_err(pm2->dev, "%s read failed\n", __func__); - - return ret; -} - -static int pm2xxx_charger_ac_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct pm2xxx_charger *pm2; - - pm2 = to_pm2xxx_charger_ac_device_info(psy_to_ux500_charger(psy)); - - switch (psp) { - case POWER_SUPPLY_PROP_HEALTH: - if (pm2->flags.mainextchnotok) - val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; - else if (pm2->ac.wd_expired) - val->intval = POWER_SUPPLY_HEALTH_DEAD; - else if (pm2->flags.main_thermal_prot) - val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; - else if (pm2->flags.ovv) - val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; - else - val->intval = POWER_SUPPLY_HEALTH_GOOD; - break; - case POWER_SUPPLY_PROP_ONLINE: - val->intval = pm2->ac.charger_online; - break; - case POWER_SUPPLY_PROP_PRESENT: - val->intval = pm2->ac.charger_connected; - break; - case POWER_SUPPLY_PROP_VOLTAGE_AVG: - pm2->ac.cv_active = pm2xxx_charger_get_ac_cv(pm2); - val->intval = pm2->ac.cv_active; - break; - default: - return -EINVAL; - } - return 0; -} - -static int pm2xxx_charging_init(struct pm2xxx_charger *pm2) -{ - int ret = 0; - - /* enable CC and CV watchdog */ - ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG3, - (PM2XXX_CH_WD_CV_PHASE_60MIN | PM2XXX_CH_WD_CC_PHASE_60MIN)); - if( ret < 0) - return ret; - - /* enable precharge watchdog */ - ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG4, - PM2XXX_CH_WD_PRECH_PHASE_60MIN); - - /* Disable auto timeout */ - ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG5, - PM2XXX_CH_WD_AUTO_TIMEOUT_20MIN); - - /* - * EOC current level = 100mA - * Precharge current level = 100mA - * CC current level = 1000mA - */ - ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG6, - (PM2XXX_DIR_CH_CC_CURRENT_1000MA | - PM2XXX_CH_PRECH_CURRENT_100MA | - PM2XXX_CH_EOC_CURRENT_100MA)); - - /* - * recharge threshold = 3.8V - * Precharge to CC threshold = 2.9V - */ - ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG7, - (PM2XXX_CH_PRECH_VOL_2_9 | PM2XXX_CH_VRESUME_VOL_3_8)); - - /* float voltage charger level = 4.2V */ - ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG8, - PM2XXX_CH_VOLT_4_2); - - /* Voltage drop between VBAT and VSYS in HW charging = 300mV */ - ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG9, - (PM2XXX_CH_150MV_DROP_300MV | PM2XXX_CHARCHING_INFO_DIS | - PM2XXX_CH_CC_REDUCED_CURRENT_IDENT | - PM2XXX_CH_CC_MODEDROP_DIS)); - - /* Input charger level of over voltage = 10V */ - ret = pm2xxx_reg_write(pm2, PM2XXX_INP_VOLT_VPWR2, - PM2XXX_VPWR2_OVV_10); - ret = pm2xxx_reg_write(pm2, PM2XXX_INP_VOLT_VPWR1, - PM2XXX_VPWR1_OVV_10); - - /* Input charger drop */ - ret = pm2xxx_reg_write(pm2, PM2XXX_INP_DROP_VPWR2, - (PM2XXX_VPWR2_HW_OPT_DIS | PM2XXX_VPWR2_VALID_DIS | - PM2XXX_VPWR2_DROP_DIS)); - ret = pm2xxx_reg_write(pm2, PM2XXX_INP_DROP_VPWR1, - (PM2XXX_VPWR1_HW_OPT_DIS | PM2XXX_VPWR1_VALID_DIS | - PM2XXX_VPWR1_DROP_DIS)); - - /* Disable battery low monitoring */ - ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_LOW_LEV_COMP_REG, - PM2XXX_VBAT_LOW_MONITORING_ENA); - - return ret; -} - -static int pm2xxx_charger_ac_en(struct ux500_charger *charger, - int enable, int vset, int iset) -{ - int ret; - int volt_index; - int curr_index; - u8 val; - - struct pm2xxx_charger *pm2 = to_pm2xxx_charger_ac_device_info(charger); - - if (enable) { - if (!pm2->ac.charger_connected) { - dev_dbg(pm2->dev, "AC charger not connected\n"); - return -ENXIO; - } - - dev_dbg(pm2->dev, "Enable AC: %dmV %dmA\n", vset, iset); - if (!pm2->vddadc_en_ac) { - ret = regulator_enable(pm2->regu); - if (ret) - dev_warn(pm2->dev, - "Failed to enable vddadc regulator\n"); - else - pm2->vddadc_en_ac = true; - } - - ret = pm2xxx_charging_init(pm2); - if (ret < 0) { - dev_err(pm2->dev, "%s charging init failed\n", - __func__); - goto error_occured; - } - - volt_index = pm2xxx_voltage_to_regval(vset); - curr_index = pm2xxx_current_to_regval(iset); - - if (volt_index < 0 || curr_index < 0) { - dev_err(pm2->dev, - "Charger voltage or current too high, " - "charging not started\n"); - return -ENXIO; - } - - ret = pm2xxx_reg_read(pm2, PM2XXX_BATT_CTRL_REG8, &val); - if (ret < 0) { - dev_err(pm2->dev, "%s pm2xxx read failed\n", __func__); - goto error_occured; - } - val &= ~PM2XXX_CH_VOLT_MASK; - val |= volt_index; - ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG8, val); - if (ret < 0) { - dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__); - goto error_occured; - } - - ret = pm2xxx_reg_read(pm2, PM2XXX_BATT_CTRL_REG6, &val); - if (ret < 0) { - dev_err(pm2->dev, "%s pm2xxx read failed\n", __func__); - goto error_occured; - } - val &= ~PM2XXX_DIR_CH_CC_CURRENT_MASK; - val |= curr_index; - ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG6, val); - if (ret < 0) { - dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__); - goto error_occured; - } - - if (!pm2->bat->enable_overshoot) { - ret = pm2xxx_reg_read(pm2, PM2XXX_LED_CTRL_REG, &val); - if (ret < 0) { - dev_err(pm2->dev, "%s pm2xxx read failed\n", - __func__); - goto error_occured; - } - val |= PM2XXX_ANTI_OVERSHOOT_EN; - ret = pm2xxx_reg_write(pm2, PM2XXX_LED_CTRL_REG, val); - if (ret < 0) { - dev_err(pm2->dev, "%s pm2xxx write failed\n", - __func__); - goto error_occured; - } - } - - ret = pm2xxx_charging_enable_mngt(pm2); - if (ret < 0) { - dev_err(pm2->dev, "Failed to enable" - "pm2xxx ac charger\n"); - goto error_occured; - } - - pm2->ac.charger_online = 1; - } else { - pm2->ac.charger_online = 0; - pm2->ac.wd_expired = false; - - /* Disable regulator if enabled */ - if (pm2->vddadc_en_ac) { - regulator_disable(pm2->regu); - pm2->vddadc_en_ac = false; - } - - ret = pm2xxx_charging_disable_mngt(pm2); - if (ret < 0) { - dev_err(pm2->dev, "failed to disable" - "pm2xxx ac charger\n"); - goto error_occured; - } - - dev_dbg(pm2->dev, "PM2301: " "Disabled AC charging\n"); - } - power_supply_changed(pm2->ac_chg.psy); - -error_occured: - return ret; -} - -static int pm2xxx_charger_watchdog_kick(struct ux500_charger *charger) -{ - int ret; - struct pm2xxx_charger *pm2; - - if (charger->psy->desc->type == POWER_SUPPLY_TYPE_MAINS) - pm2 = to_pm2xxx_charger_ac_device_info(charger); - else - return -ENXIO; - - ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_WD_KICK, WD_TIMER); - if (ret) - dev_err(pm2->dev, "Failed to kick WD!\n"); - - return ret; -} - -static void pm2xxx_charger_ac_work(struct work_struct *work) -{ - struct pm2xxx_charger *pm2 = container_of(work, - struct pm2xxx_charger, ac_work); - - - power_supply_changed(pm2->ac_chg.psy); - sysfs_notify(&pm2->ac_chg.psy->dev.kobj, NULL, "present"); -}; - -static void pm2xxx_charger_check_hw_failure_work(struct work_struct *work) -{ - u8 reg_value; - - struct pm2xxx_charger *pm2 = container_of(work, - struct pm2xxx_charger, check_hw_failure_work.work); - - if (pm2->flags.ovv) { - pm2xxx_reg_read(pm2, PM2XXX_SRCE_REG_INT4, ®_value); - - if (!(reg_value & (PM2XXX_INT4_S_ITVPWR1OVV | - PM2XXX_INT4_S_ITVPWR2OVV))) { - pm2->flags.ovv = false; - power_supply_changed(pm2->ac_chg.psy); - } - } - - /* If we still have a failure, schedule a new check */ - if (pm2->flags.ovv) { - queue_delayed_work(pm2->charger_wq, - &pm2->check_hw_failure_work, round_jiffies(HZ)); - } -} - -static void pm2xxx_charger_check_main_thermal_prot_work( - struct work_struct *work) -{ - int ret; - u8 val; - - struct pm2xxx_charger *pm2 = container_of(work, struct pm2xxx_charger, - check_main_thermal_prot_work); - - /* Check if die temp warning is still active */ - ret = pm2xxx_reg_read(pm2, PM2XXX_SRCE_REG_INT5, &val); - if (ret < 0) { - dev_err(pm2->dev, "%s pm2xxx read failed\n", __func__); - return; - } - if (val & (PM2XXX_INT5_S_ITTHERMALWARNINGRISE - | PM2XXX_INT5_S_ITTHERMALSHUTDOWNRISE)) - pm2->flags.main_thermal_prot = true; - else if (val & (PM2XXX_INT5_S_ITTHERMALWARNINGFALL - | PM2XXX_INT5_S_ITTHERMALSHUTDOWNFALL)) - pm2->flags.main_thermal_prot = false; - - power_supply_changed(pm2->ac_chg.psy); -} - -static struct pm2xxx_interrupts pm2xxx_int = { - .handler[0] = pm2_int_reg0, - .handler[1] = pm2_int_reg1, - .handler[2] = pm2_int_reg2, - .handler[3] = pm2_int_reg3, - .handler[4] = pm2_int_reg4, - .handler[5] = pm2_int_reg5, -}; - -static struct pm2xxx_irq pm2xxx_charger_irq[] = { - {"PM2XXX_IRQ_INT", pm2xxx_irq_int}, -}; - -static int __maybe_unused pm2xxx_wall_charger_resume(struct device *dev) -{ - struct i2c_client *i2c_client = to_i2c_client(dev); - struct pm2xxx_charger *pm2; - - pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(i2c_client); - set_lpn_pin(pm2); - - /* If we still have a HW failure, schedule a new check */ - if (pm2->flags.ovv) - queue_delayed_work(pm2->charger_wq, - &pm2->check_hw_failure_work, 0); - - return 0; -} - -static int __maybe_unused pm2xxx_wall_charger_suspend(struct device *dev) -{ - struct i2c_client *i2c_client = to_i2c_client(dev); - struct pm2xxx_charger *pm2; - - pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(i2c_client); - clear_lpn_pin(pm2); - - /* Cancel any pending HW failure check */ - if (delayed_work_pending(&pm2->check_hw_failure_work)) - cancel_delayed_work(&pm2->check_hw_failure_work); - - flush_work(&pm2->ac_work); - flush_work(&pm2->check_main_thermal_prot_work); - - return 0; -} - -static int __maybe_unused pm2xxx_runtime_suspend(struct device *dev) -{ - struct i2c_client *pm2xxx_i2c_client = to_i2c_client(dev); - struct pm2xxx_charger *pm2; - - pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(pm2xxx_i2c_client); - clear_lpn_pin(pm2); - - return 0; -} - -static int __maybe_unused pm2xxx_runtime_resume(struct device *dev) -{ - struct i2c_client *pm2xxx_i2c_client = to_i2c_client(dev); - struct pm2xxx_charger *pm2; - - pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(pm2xxx_i2c_client); - - if (gpio_is_valid(pm2->lpn_pin) && gpio_get_value(pm2->lpn_pin) == 0) - set_lpn_pin(pm2); - - return 0; -} - -static const struct dev_pm_ops pm2xxx_pm_ops __maybe_unused = { - SET_SYSTEM_SLEEP_PM_OPS(pm2xxx_wall_charger_suspend, - pm2xxx_wall_charger_resume) - SET_RUNTIME_PM_OPS(pm2xxx_runtime_suspend, pm2xxx_runtime_resume, NULL) -}; - -static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, - const struct i2c_device_id *id) -{ - struct pm2xxx_platform_data *pl_data = i2c_client->dev.platform_data; - struct power_supply_config psy_cfg = {}; - struct pm2xxx_charger *pm2; - int ret = 0; - u8 val; - int i; - - if (!pl_data) { - dev_err(&i2c_client->dev, "No platform data supplied\n"); - return -EINVAL; - } - - pm2 = kzalloc(sizeof(struct pm2xxx_charger), GFP_KERNEL); - if (!pm2) { - dev_err(&i2c_client->dev, "pm2xxx_charger allocation failed\n"); - return -ENOMEM; - } - - /* get parent data */ - pm2->dev = &i2c_client->dev; - - pm2->pm2_int = &pm2xxx_int; - - /* get charger spcific platform data */ - if (!pl_data->wall_charger) { - dev_err(pm2->dev, "no charger platform data supplied\n"); - ret = -EINVAL; - goto free_device_info; - } - - pm2->pdata = pl_data->wall_charger; - - /* get battery specific platform data */ - if (!pl_data->battery) { - dev_err(pm2->dev, "no battery platform data supplied\n"); - ret = -EINVAL; - goto free_device_info; - } - - pm2->bat = pl_data->battery; - - if (!i2c_check_functionality(i2c_client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_READ_WORD_DATA)) { - ret = -ENODEV; - dev_info(pm2->dev, "pm2301 i2c_check_functionality failed\n"); - goto free_device_info; - } - - pm2->config.pm2xxx_i2c = i2c_client; - pm2->config.pm2xxx_id = (struct i2c_device_id *) id; - i2c_set_clientdata(i2c_client, pm2); - - /* AC supply */ - /* power_supply base class */ - pm2->ac_chg_desc.name = pm2->pdata->label; - pm2->ac_chg_desc.type = POWER_SUPPLY_TYPE_MAINS; - pm2->ac_chg_desc.properties = pm2xxx_charger_ac_props; - pm2->ac_chg_desc.num_properties = ARRAY_SIZE(pm2xxx_charger_ac_props); - pm2->ac_chg_desc.get_property = pm2xxx_charger_ac_get_property; - - psy_cfg.supplied_to = pm2->pdata->supplied_to; - psy_cfg.num_supplicants = pm2->pdata->num_supplicants; - /* pm2xxx_charger sub-class */ - pm2->ac_chg.ops.enable = &pm2xxx_charger_ac_en; - pm2->ac_chg.ops.kick_wd = &pm2xxx_charger_watchdog_kick; - pm2->ac_chg.ops.update_curr = &pm2xxx_charger_update_charger_current; - pm2->ac_chg.max_out_volt = pm2xxx_charger_voltage_map[ - ARRAY_SIZE(pm2xxx_charger_voltage_map) - 1]; - pm2->ac_chg.max_out_curr = pm2xxx_charger_current_map[ - ARRAY_SIZE(pm2xxx_charger_current_map) - 1]; - pm2->ac_chg.wdt_refresh = WD_KICK_INTERVAL; - pm2->ac_chg.enabled = true; - pm2->ac_chg.external = true; - - /* Create a work queue for the charger */ - pm2->charger_wq = alloc_ordered_workqueue("pm2xxx_charger_wq", - WQ_MEM_RECLAIM); - if (pm2->charger_wq == NULL) { - ret = -ENOMEM; - dev_err(pm2->dev, "failed to create work queue\n"); - goto free_device_info; - } - - /* Init work for charger detection */ - INIT_WORK(&pm2->ac_work, pm2xxx_charger_ac_work); - - /* Init work for checking HW status */ - INIT_WORK(&pm2->check_main_thermal_prot_work, - pm2xxx_charger_check_main_thermal_prot_work); - - /* Init work for HW failure check */ - INIT_DEFERRABLE_WORK(&pm2->check_hw_failure_work, - pm2xxx_charger_check_hw_failure_work); - - /* - * VDD ADC supply needs to be enabled from this driver when there - * is a charger connected to avoid erroneous BTEMP_HIGH/LOW - * interrupts during charging - */ - pm2->regu = regulator_get(pm2->dev, "vddadc"); - if (IS_ERR(pm2->regu)) { - ret = PTR_ERR(pm2->regu); - dev_err(pm2->dev, "failed to get vddadc regulator\n"); - goto free_charger_wq; - } - - /* Register AC charger class */ - pm2->ac_chg.psy = power_supply_register(pm2->dev, &pm2->ac_chg_desc, - &psy_cfg); - if (IS_ERR(pm2->ac_chg.psy)) { - dev_err(pm2->dev, "failed to register AC charger\n"); - ret = PTR_ERR(pm2->ac_chg.psy); - goto free_regulator; - } - - /* Register interrupts */ - ret = request_threaded_irq(gpio_to_irq(pm2->pdata->gpio_irq_number), - NULL, - pm2xxx_charger_irq[0].isr, - pm2->pdata->irq_type | IRQF_ONESHOT, - pm2xxx_charger_irq[0].name, pm2); - - if (ret != 0) { - dev_err(pm2->dev, "failed to request %s IRQ %d: %d\n", - pm2xxx_charger_irq[0].name, - gpio_to_irq(pm2->pdata->gpio_irq_number), ret); - goto unregister_pm2xxx_charger; - } - - ret = pm_runtime_set_active(pm2->dev); - if (ret) - dev_err(pm2->dev, "set active Error\n"); - - pm_runtime_enable(pm2->dev); - pm_runtime_set_autosuspend_delay(pm2->dev, PM2XXX_AUTOSUSPEND_DELAY); - pm_runtime_use_autosuspend(pm2->dev); - pm_runtime_resume(pm2->dev); - - /* pm interrupt can wake up system */ - ret = enable_irq_wake(gpio_to_irq(pm2->pdata->gpio_irq_number)); - if (ret) { - dev_err(pm2->dev, "failed to set irq wake\n"); - goto unregister_pm2xxx_interrupt; - } - - mutex_init(&pm2->lock); - - if (gpio_is_valid(pm2->pdata->lpn_gpio)) { - /* get lpn GPIO from platform data */ - pm2->lpn_pin = pm2->pdata->lpn_gpio; - - /* - * Charger detection mechanism requires pulling up the LPN pin - * while i2c communication if Charger is not connected - * LPN pin of PM2301 is GPIO60 of AB9540 - */ - ret = gpio_request(pm2->lpn_pin, "pm2301_lpm_gpio"); - - if (ret < 0) { - dev_err(pm2->dev, "pm2301_lpm_gpio request failed\n"); - goto disable_pm2_irq_wake; - } - ret = gpio_direction_output(pm2->lpn_pin, 0); - if (ret < 0) { - dev_err(pm2->dev, "pm2301_lpm_gpio direction failed\n"); - goto free_gpio; - } - set_lpn_pin(pm2); - } - - /* read interrupt registers */ - for (i = 0; i < PM2XXX_NUM_INT_REG; i++) - pm2xxx_reg_read(pm2, - pm2xxx_interrupt_registers[i], - &val); - - ret = pm2xxx_charger_detection(pm2, &val); - - if ((ret == 0) && val) { - pm2->ac.charger_connected = 1; - ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON, - AB8500_MAIN_CH_DET); - pm2->ac_conn = true; - power_supply_changed(pm2->ac_chg.psy); - sysfs_notify(&pm2->ac_chg.psy->dev.kobj, NULL, "present"); - } - - return 0; - -free_gpio: - if (gpio_is_valid(pm2->lpn_pin)) - gpio_free(pm2->lpn_pin); -disable_pm2_irq_wake: - disable_irq_wake(gpio_to_irq(pm2->pdata->gpio_irq_number)); -unregister_pm2xxx_interrupt: - /* disable interrupt */ - free_irq(gpio_to_irq(pm2->pdata->gpio_irq_number), pm2); -unregister_pm2xxx_charger: - /* unregister power supply */ - power_supply_unregister(pm2->ac_chg.psy); -free_regulator: - /* disable the regulator */ - regulator_put(pm2->regu); -free_charger_wq: - destroy_workqueue(pm2->charger_wq); -free_device_info: - kfree(pm2); - - return ret; -} - -static int pm2xxx_wall_charger_remove(struct i2c_client *i2c_client) -{ - struct pm2xxx_charger *pm2 = i2c_get_clientdata(i2c_client); - - /* Disable pm_runtime */ - pm_runtime_disable(pm2->dev); - /* Disable AC charging */ - pm2xxx_charger_ac_en(&pm2->ac_chg, false, 0, 0); - - /* Disable wake by pm interrupt */ - disable_irq_wake(gpio_to_irq(pm2->pdata->gpio_irq_number)); - - /* Disable interrupts */ - free_irq(gpio_to_irq(pm2->pdata->gpio_irq_number), pm2); - - /* Delete the work queue */ - destroy_workqueue(pm2->charger_wq); - - flush_scheduled_work(); - - /* disable the regulator */ - regulator_put(pm2->regu); - - power_supply_unregister(pm2->ac_chg.psy); - - if (gpio_is_valid(pm2->lpn_pin)) - gpio_free(pm2->lpn_pin); - - kfree(pm2); - - return 0; -} - -static const struct i2c_device_id pm2xxx_id[] = { - { "pm2301", 0 }, - { } -}; - -MODULE_DEVICE_TABLE(i2c, pm2xxx_id); - -static struct i2c_driver pm2xxx_charger_driver = { - .probe = pm2xxx_wall_charger_probe, - .remove = pm2xxx_wall_charger_remove, - .driver = { - .name = "pm2xxx-wall_charger", - .pm = IS_ENABLED(CONFIG_PM) ? &pm2xxx_pm_ops : NULL, - }, - .id_table = pm2xxx_id, -}; - -static int __init pm2xxx_charger_init(void) -{ - return i2c_add_driver(&pm2xxx_charger_driver); -} - -static void __exit pm2xxx_charger_exit(void) -{ - i2c_del_driver(&pm2xxx_charger_driver); -} - -device_initcall_sync(pm2xxx_charger_init); -module_exit(pm2xxx_charger_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Rajkumar kasirajan, Olivier Launay"); -MODULE_DESCRIPTION("PM2xxx charger management driver"); diff --git a/drivers/power/supply/rn5t618_power.c b/drivers/power/supply/rn5t618_power.c index dee520f0fdf5..819061918b2a 100644 --- a/drivers/power/supply/rn5t618_power.c +++ b/drivers/power/supply/rn5t618_power.c @@ -37,8 +37,27 @@ #define CHG_STATE_NO_BAT2 13 #define CHG_STATE_CHG_READY_VUSB 14 +#define GCHGDET_TYPE_MASK 0x30 +#define GCHGDET_TYPE_SDP 0x00 +#define GCHGDET_TYPE_CDP 0x10 +#define GCHGDET_TYPE_DCP 0x20 + #define FG_ENABLE 1 +/* + * Formula seems accurate for battery current, but for USB current around 70mA + * per step was seen on Kobo Clara HD but all sources show the same formula + * also fur USB current. To avoid accidentially unwanted high currents we stick + * to that formula + */ +#define TO_CUR_REG(x) ((x) / 100000 - 1) +#define FROM_CUR_REG(x) ((((x) & 0x1f) + 1) * 100000) +#define CHG_MIN_CUR 100000 +#define CHG_MAX_CUR 1800000 +#define ADP_MAX_CUR 2500000 +#define USB_MAX_CUR 1400000 + + struct rn5t618_power_info { struct rn5t618 *rn5t618; struct platform_device *pdev; @@ -48,12 +67,24 @@ struct rn5t618_power_info { int irq; }; +static enum power_supply_usb_type rn5t618_usb_types[] = { + POWER_SUPPLY_USB_TYPE_SDP, + POWER_SUPPLY_USB_TYPE_DCP, + POWER_SUPPLY_USB_TYPE_CDP, + POWER_SUPPLY_USB_TYPE_UNKNOWN +}; + static enum power_supply_property rn5t618_usb_props[] = { + /* input current limit is not very accurate */ + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_USB_TYPE, POWER_SUPPLY_PROP_ONLINE, }; static enum power_supply_property rn5t618_adp_props[] = { + /* input current limit is not very accurate */ + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_ONLINE, }; @@ -69,6 +100,7 @@ static enum power_supply_property rn5t618_battery_props[] = { POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_NOW, }; @@ -258,6 +290,36 @@ static int rn5t618_battery_ttf(struct rn5t618_power_info *info, return 0; } +static int rn5t618_battery_set_current_limit(struct rn5t618_power_info *info, + const union power_supply_propval *val) +{ + if (val->intval < CHG_MIN_CUR) + return -EINVAL; + + if (val->intval >= CHG_MAX_CUR) + return -EINVAL; + + return regmap_update_bits(info->rn5t618->regmap, + RN5T618_CHGISET, + 0x1F, TO_CUR_REG(val->intval)); +} + +static int rn5t618_battery_get_current_limit(struct rn5t618_power_info *info, + union power_supply_propval *val) +{ + unsigned int regval; + int ret; + + ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGISET, + ®val); + if (ret < 0) + return ret; + + val->intval = FROM_CUR_REG(regval); + + return 0; +} + static int rn5t618_battery_charge_full(struct rn5t618_power_info *info, union power_supply_propval *val) { @@ -323,6 +385,9 @@ static int rn5t618_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_TECHNOLOGY: val->intval = POWER_SUPPLY_TECHNOLOGY_LION; break; + case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: + ret = rn5t618_battery_get_current_limit(info, val); + break; case POWER_SUPPLY_PROP_CHARGE_FULL: ret = rn5t618_battery_charge_full(info, val); break; @@ -336,12 +401,38 @@ static int rn5t618_battery_get_property(struct power_supply *psy, return ret; } +static int rn5t618_battery_set_property(struct power_supply *psy, + enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct rn5t618_power_info *info = power_supply_get_drvdata(psy); + + switch (psp) { + case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: + return rn5t618_battery_set_current_limit(info, val); + default: + return -EINVAL; + } +} + +static int rn5t618_battery_property_is_writeable(struct power_supply *psy, + enum power_supply_property psp) +{ + switch (psp) { + case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: + return true; + default: + return false; + } +} + static int rn5t618_adp_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { struct rn5t618_power_info *info = power_supply_get_drvdata(psy); unsigned int chgstate; + unsigned int regval; bool online; int ret; @@ -365,6 +456,14 @@ static int rn5t618_adp_get_property(struct power_supply *psy, val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; break; + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + ret = regmap_read(info->rn5t618->regmap, + RN5T618_REGISET1, ®val); + if (ret < 0) + return ret; + + val->intval = FROM_CUR_REG(regval); + break; default: return -EINVAL; } @@ -372,12 +471,79 @@ static int rn5t618_adp_get_property(struct power_supply *psy, return 0; } +static int rn5t618_adp_set_property(struct power_supply *psy, + enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct rn5t618_power_info *info = power_supply_get_drvdata(psy); + int ret; + + switch (psp) { + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + if (val->intval > ADP_MAX_CUR) + return -EINVAL; + + if (val->intval < CHG_MIN_CUR) + return -EINVAL; + + ret = regmap_write(info->rn5t618->regmap, RN5T618_REGISET1, + TO_CUR_REG(val->intval)); + if (ret < 0) + return ret; + + break; + default: + return -EINVAL; + } + + return 0; +} + +static int rn5t618_adp_property_is_writeable(struct power_supply *psy, + enum power_supply_property psp) +{ + switch (psp) { + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + return true; + default: + return false; + } +} + +static int rc5t619_usb_get_type(struct rn5t618_power_info *info, + union power_supply_propval *val) +{ + unsigned int regval; + int ret; + + ret = regmap_read(info->rn5t618->regmap, RN5T618_GCHGDET, ®val); + if (ret < 0) + return ret; + + switch (regval & GCHGDET_TYPE_MASK) { + case GCHGDET_TYPE_SDP: + val->intval = POWER_SUPPLY_USB_TYPE_SDP; + break; + case GCHGDET_TYPE_CDP: + val->intval = POWER_SUPPLY_USB_TYPE_CDP; + break; + case GCHGDET_TYPE_DCP: + val->intval = POWER_SUPPLY_USB_TYPE_DCP; + break; + default: + val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN; + } + + return 0; +} + static int rn5t618_usb_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { struct rn5t618_power_info *info = power_supply_get_drvdata(psy); unsigned int chgstate; + unsigned int regval; bool online; int ret; @@ -401,6 +567,28 @@ static int rn5t618_usb_get_property(struct power_supply *psy, val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; break; + case POWER_SUPPLY_PROP_USB_TYPE: + if (!online || (info->rn5t618->variant != RC5T619)) + return -ENODATA; + + return rc5t619_usb_get_type(info, val); + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGCTL1, + ®val); + if (ret < 0) + return ret; + + val->intval = 0; + if (regval & 2) { + ret = regmap_read(info->rn5t618->regmap, + RN5T618_REGISET2, + ®val); + if (ret < 0) + return ret; + + val->intval = FROM_CUR_REG(regval); + } + break; default: return -EINVAL; } @@ -408,12 +596,53 @@ static int rn5t618_usb_get_property(struct power_supply *psy, return 0; } +static int rn5t618_usb_set_property(struct power_supply *psy, + enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct rn5t618_power_info *info = power_supply_get_drvdata(psy); + int ret; + + switch (psp) { + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + if (val->intval > USB_MAX_CUR) + return -EINVAL; + + if (val->intval < CHG_MIN_CUR) + return -EINVAL; + + ret = regmap_write(info->rn5t618->regmap, RN5T618_REGISET2, + 0xE0 | TO_CUR_REG(val->intval)); + if (ret < 0) + return ret; + + break; + default: + return -EINVAL; + } + + return 0; +} + +static int rn5t618_usb_property_is_writeable(struct power_supply *psy, + enum power_supply_property psp) +{ + switch (psp) { + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + return true; + default: + return false; + } +} + static const struct power_supply_desc rn5t618_battery_desc = { .name = "rn5t618-battery", .type = POWER_SUPPLY_TYPE_BATTERY, .properties = rn5t618_battery_props, .num_properties = ARRAY_SIZE(rn5t618_battery_props), .get_property = rn5t618_battery_get_property, + .set_property = rn5t618_battery_set_property, + .property_is_writeable = rn5t618_battery_property_is_writeable, }; static const struct power_supply_desc rn5t618_adp_desc = { @@ -422,14 +651,20 @@ static const struct power_supply_desc rn5t618_adp_desc = { .properties = rn5t618_adp_props, .num_properties = ARRAY_SIZE(rn5t618_adp_props), .get_property = rn5t618_adp_get_property, + .set_property = rn5t618_adp_set_property, + .property_is_writeable = rn5t618_adp_property_is_writeable, }; static const struct power_supply_desc rn5t618_usb_desc = { .name = "rn5t618-usb", .type = POWER_SUPPLY_TYPE_USB, + .usb_types = rn5t618_usb_types, + .num_usb_types = ARRAY_SIZE(rn5t618_usb_types), .properties = rn5t618_usb_props, .num_properties = ARRAY_SIZE(rn5t618_usb_props), .get_property = rn5t618_usb_get_property, + .set_property = rn5t618_usb_set_property, + .property_is_writeable = rn5t618_usb_property_is_writeable, }; static irqreturn_t rn5t618_charger_irq(int irq, void *data) diff --git a/drivers/power/supply/rt5033_battery.c b/drivers/power/supply/rt5033_battery.c index f330452341f0..9ad0afe83d1b 100644 --- a/drivers/power/supply/rt5033_battery.c +++ b/drivers/power/supply/rt5033_battery.c @@ -164,9 +164,16 @@ static const struct i2c_device_id rt5033_battery_id[] = { }; MODULE_DEVICE_TABLE(i2c, rt5033_battery_id); +static const struct of_device_id rt5033_battery_of_match[] = { + { .compatible = "richtek,rt5033-battery", }, + { } +}; +MODULE_DEVICE_TABLE(of, rt5033_battery_of_match); + static struct i2c_driver rt5033_battery_driver = { .driver = { .name = "rt5033-battery", + .of_match_table = rt5033_battery_of_match, }, .probe = rt5033_battery_probe, .remove = rt5033_battery_remove, diff --git a/drivers/power/supply/sbs-battery.c b/drivers/power/supply/sbs-battery.c index 8d7a10730e43..f84dbaab283a 100644 --- a/drivers/power/supply/sbs-battery.c +++ b/drivers/power/supply/sbs-battery.c @@ -189,6 +189,14 @@ static const enum power_supply_property sbs_properties[] = { /* Supports special manufacturer commands from TI BQ20Z65 and BQ20Z75 IC. */ #define SBS_FLAGS_TI_BQ20ZX5 BIT(0) +static const enum power_supply_property string_properties[] = { + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_MANUFACTURER, + POWER_SUPPLY_PROP_MODEL_NAME, +}; + +#define NR_STRING_BUFFERS ARRAY_SIZE(string_properties) + struct sbs_info { struct i2c_client *client; struct power_supply *power_supply; @@ -202,11 +210,32 @@ struct sbs_info { struct delayed_work work; struct mutex mode_lock; u32 flags; + int technology; + char strings[NR_STRING_BUFFERS][I2C_SMBUS_BLOCK_MAX + 1]; }; -static char model_name[I2C_SMBUS_BLOCK_MAX + 1]; -static char manufacturer[I2C_SMBUS_BLOCK_MAX + 1]; -static char chemistry[I2C_SMBUS_BLOCK_MAX + 1]; +static char *sbs_get_string_buf(struct sbs_info *chip, + enum power_supply_property psp) +{ + int i = 0; + + for (i = 0; i < NR_STRING_BUFFERS; i++) + if (string_properties[i] == psp) + return chip->strings[i]; + + return ERR_PTR(-EINVAL); +} + +static void sbs_invalidate_cached_props(struct sbs_info *chip) +{ + int i = 0; + + chip->technology = -1; + + for (i = 0; i < NR_STRING_BUFFERS; i++) + chip->strings[i][0] = 0; +} + static bool force_load; static int sbs_read_word_data(struct i2c_client *client, u8 address); @@ -244,6 +273,7 @@ static int sbs_update_presence(struct sbs_info *chip, bool is_present) chip->is_present = false; /* Disable PEC when no device is present */ client->flags &= ~I2C_CLIENT_PEC; + sbs_invalidate_cached_props(chip); return 0; } @@ -640,17 +670,45 @@ static int sbs_get_battery_property(struct i2c_client *client, return 0; } -static int sbs_get_battery_string_property(struct i2c_client *client, - int reg_offset, enum power_supply_property psp, char *val) +static int sbs_get_property_index(struct i2c_client *client, + enum power_supply_property psp) { - s32 ret; + int count; - ret = sbs_read_string_data(client, sbs_data[reg_offset].addr, val); + for (count = 0; count < ARRAY_SIZE(sbs_data); count++) + if (psp == sbs_data[count].psp) + return count; - if (ret < 0) - return ret; + dev_warn(&client->dev, + "%s: Invalid Property - %d\n", __func__, psp); - return 0; + return -EINVAL; +} + +static const char *sbs_get_constant_string(struct sbs_info *chip, + enum power_supply_property psp) +{ + int ret; + char *buf; + u8 addr; + + buf = sbs_get_string_buf(chip, psp); + if (IS_ERR(buf)) + return buf; + + if (!buf[0]) { + ret = sbs_get_property_index(chip->client, psp); + if (ret < 0) + return ERR_PTR(ret); + + addr = sbs_data[ret].addr; + + ret = sbs_read_string_data(chip->client, addr, buf); + if (ret < 0) + return ERR_PTR(ret); + } + + return buf; } static void sbs_unit_adjustment(struct i2c_client *client, @@ -773,48 +831,36 @@ static int sbs_get_battery_serial_number(struct i2c_client *client, return 0; } -static int sbs_get_property_index(struct i2c_client *client, - enum power_supply_property psp) -{ - int count; - for (count = 0; count < ARRAY_SIZE(sbs_data); count++) - if (psp == sbs_data[count].psp) - return count; - - dev_warn(&client->dev, - "%s: Invalid Property - %d\n", __func__, psp); - - return -EINVAL; -} - -static int sbs_get_chemistry(struct i2c_client *client, +static int sbs_get_chemistry(struct sbs_info *chip, union power_supply_propval *val) { - enum power_supply_property psp = POWER_SUPPLY_PROP_TECHNOLOGY; - int ret; + const char *chemistry; - ret = sbs_get_property_index(client, psp); - if (ret < 0) - return ret; + if (chip->technology != -1) { + val->intval = chip->technology; + return 0; + } - ret = sbs_get_battery_string_property(client, ret, psp, - chemistry); - if (ret < 0) - return ret; + chemistry = sbs_get_constant_string(chip, POWER_SUPPLY_PROP_TECHNOLOGY); + + if (IS_ERR(chemistry)) + return PTR_ERR(chemistry); if (!strncasecmp(chemistry, "LION", 4)) - val->intval = POWER_SUPPLY_TECHNOLOGY_LION; + chip->technology = POWER_SUPPLY_TECHNOLOGY_LION; else if (!strncasecmp(chemistry, "LiP", 3)) - val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO; + chip->technology = POWER_SUPPLY_TECHNOLOGY_LIPO; else if (!strncasecmp(chemistry, "NiCd", 4)) - val->intval = POWER_SUPPLY_TECHNOLOGY_NiCd; + chip->technology = POWER_SUPPLY_TECHNOLOGY_NiCd; else if (!strncasecmp(chemistry, "NiMH", 4)) - val->intval = POWER_SUPPLY_TECHNOLOGY_NiMH; + chip->technology = POWER_SUPPLY_TECHNOLOGY_NiMH; else - val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; + chip->technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; + + if (chip->technology == POWER_SUPPLY_TECHNOLOGY_UNKNOWN) + dev_warn(&chip->client->dev, "Unknown chemistry: %s\n", chemistry); - if (val->intval == POWER_SUPPLY_TECHNOLOGY_UNKNOWN) - dev_warn(&client->dev, "Unknown chemistry: %s\n", chemistry); + val->intval = chip->technology; return 0; } @@ -858,6 +904,7 @@ static int sbs_get_property(struct power_supply *psy, int ret = 0; struct sbs_info *chip = power_supply_get_drvdata(psy); struct i2c_client *client = chip->client; + const char *str; if (chip->gpio_detect) { ret = gpiod_get_value_cansleep(chip->gpio_detect); @@ -883,7 +930,7 @@ static int sbs_get_property(struct power_supply *psy, break; case POWER_SUPPLY_PROP_TECHNOLOGY: - ret = sbs_get_chemistry(client, val); + ret = sbs_get_chemistry(chip, val); if (ret < 0) break; @@ -935,23 +982,12 @@ static int sbs_get_property(struct power_supply *psy, break; case POWER_SUPPLY_PROP_MODEL_NAME: - ret = sbs_get_property_index(client, psp); - if (ret < 0) - break; - - ret = sbs_get_battery_string_property(client, ret, psp, - model_name); - val->strval = model_name; - break; - case POWER_SUPPLY_PROP_MANUFACTURER: - ret = sbs_get_property_index(client, psp); - if (ret < 0) - break; - - ret = sbs_get_battery_string_property(client, ret, psp, - manufacturer); - val->strval = manufacturer; + str = sbs_get_constant_string(chip, psp); + if (IS_ERR(str)) + ret = PTR_ERR(str); + else + val->strval = str; break; case POWER_SUPPLY_PROP_MANUFACTURE_YEAR: @@ -1098,6 +1134,7 @@ static int sbs_probe(struct i2c_client *client) psy_cfg.of_node = client->dev.of_node; psy_cfg.drv_data = chip; chip->last_state = POWER_SUPPLY_STATUS_UNKNOWN; + sbs_invalidate_cached_props(chip); mutex_init(&chip->mode_lock); /* use pdata if available, fall back to DT properties, diff --git a/drivers/power/supply/sc2731_charger.c b/drivers/power/supply/sc2731_charger.c index 335cb857ef30..288b79836c13 100644 --- a/drivers/power/supply/sc2731_charger.c +++ b/drivers/power/supply/sc2731_charger.c @@ -524,6 +524,7 @@ static const struct of_device_id sc2731_charger_of_match[] = { { .compatible = "sprd,sc2731-charger", }, { } }; +MODULE_DEVICE_TABLE(of, sc2731_charger_of_match); static struct platform_driver sc2731_charger_driver = { .driver = { diff --git a/drivers/power/supply/sc27xx_fuel_gauge.c b/drivers/power/supply/sc27xx_fuel_gauge.c index 9c627618c224..1ae8374e1ceb 100644 --- a/drivers/power/supply/sc27xx_fuel_gauge.c +++ b/drivers/power/supply/sc27xx_fuel_gauge.c @@ -1342,6 +1342,7 @@ static const struct of_device_id sc27xx_fgu_of_match[] = { { .compatible = "sprd,sc2731-fgu", }, { } }; +MODULE_DEVICE_TABLE(of, sc27xx_fgu_of_match); static struct platform_driver sc27xx_fgu_driver = { .probe = sc27xx_fgu_probe, diff --git a/drivers/power/supply/smb347-charger.c b/drivers/power/supply/smb347-charger.c index 3376f42d46c3..df240420f2de 100644 --- a/drivers/power/supply/smb347-charger.c +++ b/drivers/power/supply/smb347-charger.c @@ -10,7 +10,6 @@ #include <linux/delay.h> #include <linux/err.h> -#include <linux/gpio.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> diff --git a/drivers/power/supply/surface_battery.c b/drivers/power/supply/surface_battery.c index 7efa431a62b2..5ec2e6bb2465 100644 --- a/drivers/power/supply/surface_battery.c +++ b/drivers/power/supply/surface_battery.c @@ -345,6 +345,16 @@ static u32 spwr_notify_bat(struct ssam_event_notifier *nf, const struct ssam_eve struct spwr_battery_device *bat = container_of(nf, struct spwr_battery_device, notif); int status; + /* + * We cannot use strict matching when registering the notifier as the + * EC expects us to register it against instance ID 0. Strict matching + * would thus drop events, as those may have non-zero instance IDs in + * this subsystem. So we need to check the instance ID of the event + * here manually. + */ + if (event->instance_id != bat->sdev->uid.instance) + return 0; + dev_dbg(&bat->sdev->dev, "power event (cid = %#04x, iid = %#04x, tid = %#04x)\n", event->command_id, event->instance_id, event->target_id); @@ -720,8 +730,8 @@ static void spwr_battery_init(struct spwr_battery_device *bat, struct ssam_devic bat->notif.base.fn = spwr_notify_bat; bat->notif.event.reg = registry; bat->notif.event.id.target_category = sdev->uid.category; - bat->notif.event.id.instance = 0; - bat->notif.event.mask = SSAM_EVENT_MASK_STRICT; + bat->notif.event.id.instance = 0; /* need to register with instance 0 */ + bat->notif.event.mask = SSAM_EVENT_MASK_TARGET; bat->notif.event.flags = SSAM_EVENT_SEQUENCED; bat->psy_desc.name = bat->name; diff --git a/drivers/power/supply/surface_charger.c b/drivers/power/supply/surface_charger.c index 81a5b79822c9..a060c36c7766 100644 --- a/drivers/power/supply/surface_charger.c +++ b/drivers/power/supply/surface_charger.c @@ -66,7 +66,7 @@ struct spwr_ac_device { static int spwr_ac_update_unlocked(struct spwr_ac_device *ac) { - u32 old = ac->state; + __le32 old = ac->state; int status; lockdep_assert_held(&ac->lock); diff --git a/drivers/pps/clients/pps-ldisc.c b/drivers/pps/clients/pps-ldisc.c index bf26cc56b863..d73c4c2ed4e1 100644 --- a/drivers/pps/clients/pps-ldisc.c +++ b/drivers/pps/clients/pps-ldisc.c @@ -112,12 +112,13 @@ static int __init pps_tty_init(void) /* Init PPS_TTY data */ pps_ldisc_ops.owner = THIS_MODULE; + pps_ldisc_ops.num = N_PPS; pps_ldisc_ops.name = "pps_tty"; pps_ldisc_ops.dcd_change = pps_tty_dcd_change; pps_ldisc_ops.open = pps_tty_open; pps_ldisc_ops.close = pps_tty_close; - err = tty_register_ldisc(N_PPS, &pps_ldisc_ops); + err = tty_register_ldisc(&pps_ldisc_ops); if (err) pr_err("can't register PPS line discipline\n"); else @@ -128,13 +129,7 @@ static int __init pps_tty_init(void) static void __exit pps_tty_cleanup(void) { - int err; - - err = tty_unregister_ldisc(N_PPS); - if (err) - pr_err("can't unregister PPS line discipline\n"); - else - pr_info("PPS line discipline removed\n"); + tty_unregister_ldisc(&pps_ldisc_ops); } module_init(pps_tty_init); diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index c4d5c0667137..35e894f4a379 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -126,8 +126,7 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args) { struct pwm_device *pwm; - /* check, whether the driver supports a third cell for flags */ - if (pc->of_pwm_n_cells < 3) + if (pc->of_pwm_n_cells < 2) return ERR_PTR(-EINVAL); /* flags in the third cell are optional */ @@ -144,46 +143,29 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args) pwm->args.period = args->args[1]; pwm->args.polarity = PWM_POLARITY_NORMAL; - if (args->args_count > 2 && args->args[2] & PWM_POLARITY_INVERTED) - pwm->args.polarity = PWM_POLARITY_INVERSED; + if (pc->of_pwm_n_cells >= 3) { + if (args->args_count > 2 && args->args[2] & PWM_POLARITY_INVERTED) + pwm->args.polarity = PWM_POLARITY_INVERSED; + } return pwm; } EXPORT_SYMBOL_GPL(of_pwm_xlate_with_flags); -static struct pwm_device * -of_pwm_simple_xlate(struct pwm_chip *pc, const struct of_phandle_args *args) -{ - struct pwm_device *pwm; - - /* sanity check driver support */ - if (pc->of_pwm_n_cells < 2) - return ERR_PTR(-EINVAL); - - /* all cells are required */ - if (args->args_count != pc->of_pwm_n_cells) - return ERR_PTR(-EINVAL); - - if (args->args[0] >= pc->npwm) - return ERR_PTR(-EINVAL); - - pwm = pwm_request_from_chip(pc, args->args[0], NULL); - if (IS_ERR(pwm)) - return pwm; - - pwm->args.period = args->args[1]; - - return pwm; -} - static void of_pwmchip_add(struct pwm_chip *chip) { if (!chip->dev || !chip->dev->of_node) return; if (!chip->of_xlate) { - chip->of_xlate = of_pwm_simple_xlate; - chip->of_pwm_n_cells = 2; + u32 pwm_cells; + + if (of_property_read_u32(chip->dev->of_node, "#pwm-cells", + &pwm_cells)) + pwm_cells = 2; + + chip->of_xlate = of_pwm_xlate_with_flags; + chip->of_pwm_n_cells = pwm_cells; } of_node_get(chip->dev->of_node); @@ -324,22 +306,10 @@ EXPORT_SYMBOL_GPL(pwmchip_add); */ int pwmchip_remove(struct pwm_chip *chip) { - unsigned int i; - int ret = 0; - pwmchip_sysfs_unexport(chip); mutex_lock(&pwm_lock); - for (i = 0; i < chip->npwm; i++) { - struct pwm_device *pwm = &chip->pwms[i]; - - if (test_bit(PWMF_REQUESTED, &pwm->flags)) { - ret = -EBUSY; - goto out; - } - } - list_del_init(&chip->list); if (IS_ENABLED(CONFIG_OF)) @@ -347,12 +317,31 @@ int pwmchip_remove(struct pwm_chip *chip) free_pwms(chip); -out: mutex_unlock(&pwm_lock); - return ret; + + return 0; } EXPORT_SYMBOL_GPL(pwmchip_remove); +static void devm_pwmchip_remove(void *data) +{ + struct pwm_chip *chip = data; + + pwmchip_remove(chip); +} + +int devm_pwmchip_add(struct device *dev, struct pwm_chip *chip) +{ + int ret; + + ret = pwmchip_add(chip); + if (ret) + return ret; + + return devm_add_action_or_reset(dev, devm_pwmchip_remove, chip); +} +EXPORT_SYMBOL_GPL(devm_pwmchip_add); + /** * pwm_request() - request a PWM device * @pwm: global PWM device index @@ -554,7 +543,8 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state) if (state->period == pwm->state.period && state->duty_cycle == pwm->state.duty_cycle && state->polarity == pwm->state.polarity && - state->enabled == pwm->state.enabled) + state->enabled == pwm->state.enabled && + state->usage_power == pwm->state.usage_power) return 0; if (chip->ops->apply) { @@ -709,14 +699,14 @@ int pwm_adjust_config(struct pwm_device *pwm) } EXPORT_SYMBOL_GPL(pwm_adjust_config); -static struct pwm_chip *of_node_to_pwmchip(struct device_node *np) +static struct pwm_chip *fwnode_to_pwmchip(struct fwnode_handle *fwnode) { struct pwm_chip *chip; mutex_lock(&pwm_lock); list_for_each_entry(chip, &pwm_chips, list) - if (chip->dev && chip->dev->of_node == np) { + if (chip->dev && dev_fwnode(chip->dev) == fwnode) { mutex_unlock(&pwm_lock); return chip; } @@ -795,7 +785,7 @@ struct pwm_device *of_pwm_get(struct device *dev, struct device_node *np, return ERR_PTR(err); } - pc = of_node_to_pwmchip(args.np); + pc = fwnode_to_pwmchip(of_fwnode_handle(args.np)); if (IS_ERR(pc)) { if (PTR_ERR(pc) != -EPROBE_DEFER) pr_err("%s(): PWM chip not found\n", __func__); @@ -837,31 +827,9 @@ put: } EXPORT_SYMBOL_GPL(of_pwm_get); -#if IS_ENABLED(CONFIG_ACPI) -static struct pwm_chip *device_to_pwmchip(struct device *dev) -{ - struct pwm_chip *chip; - - mutex_lock(&pwm_lock); - - list_for_each_entry(chip, &pwm_chips, list) { - struct acpi_device *adev = ACPI_COMPANION(chip->dev); - - if ((chip->dev == dev) || (adev && &adev->dev == dev)) { - mutex_unlock(&pwm_lock); - return chip; - } - } - - mutex_unlock(&pwm_lock); - - return ERR_PTR(-EPROBE_DEFER); -} -#endif - /** * acpi_pwm_get() - request a PWM via parsing "pwms" property in ACPI - * @fwnode: firmware node to get the "pwm" property from + * @fwnode: firmware node to get the "pwms" property from * * Returns the PWM device parsed from the fwnode and index specified in the * "pwms" property or a negative error-code on failure. @@ -876,12 +844,10 @@ static struct pwm_chip *device_to_pwmchip(struct device *dev) * Returns: A pointer to the requested PWM device or an ERR_PTR()-encoded * error code on failure. */ -static struct pwm_device *acpi_pwm_get(struct fwnode_handle *fwnode) +static struct pwm_device *acpi_pwm_get(const struct fwnode_handle *fwnode) { - struct pwm_device *pwm = ERR_PTR(-ENODEV); -#if IS_ENABLED(CONFIG_ACPI) + struct pwm_device *pwm; struct fwnode_reference_args args; - struct acpi_device *acpi; struct pwm_chip *chip; int ret; @@ -891,14 +857,10 @@ static struct pwm_device *acpi_pwm_get(struct fwnode_handle *fwnode) if (ret < 0) return ERR_PTR(ret); - acpi = to_acpi_device_node(args.fwnode); - if (!acpi) - return ERR_PTR(-EINVAL); - if (args.nargs < 2) return ERR_PTR(-EPROTO); - chip = device_to_pwmchip(&acpi->dev); + chip = fwnode_to_pwmchip(args.fwnode); if (IS_ERR(chip)) return ERR_CAST(chip); @@ -911,7 +873,6 @@ static struct pwm_device *acpi_pwm_get(struct fwnode_handle *fwnode) if (args.nargs > 2 && args.args[2] & PWM_POLARITY_INVERTED) pwm->args.polarity = PWM_POLARITY_INVERSED; -#endif return pwm; } @@ -967,6 +928,7 @@ void pwm_remove_table(struct pwm_lookup *table, size_t num) */ struct pwm_device *pwm_get(struct device *dev, const char *con_id) { + const struct fwnode_handle *fwnode = dev ? dev_fwnode(dev) : NULL; const char *dev_id = dev ? dev_name(dev) : NULL; struct pwm_device *pwm; struct pwm_chip *chip; @@ -977,12 +939,12 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id) int err; /* look up via DT first */ - if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) - return of_pwm_get(dev, dev->of_node, con_id); + if (is_of_node(fwnode)) + return of_pwm_get(dev, to_of_node(fwnode), con_id); /* then lookup via ACPI */ - if (dev && is_acpi_node(dev->fwnode)) { - pwm = acpi_pwm_get(dev->fwnode); + if (is_acpi_node(fwnode)) { + pwm = acpi_pwm_get(fwnode); if (!IS_ERR(pwm) || PTR_ERR(pwm) != -ENOENT) return pwm; } @@ -1103,9 +1065,9 @@ out: } EXPORT_SYMBOL_GPL(pwm_put); -static void devm_pwm_release(struct device *dev, void *res) +static void devm_pwm_release(void *pwm) { - pwm_put(*(struct pwm_device **)res); + pwm_put(pwm); } /** @@ -1121,19 +1083,16 @@ static void devm_pwm_release(struct device *dev, void *res) */ struct pwm_device *devm_pwm_get(struct device *dev, const char *con_id) { - struct pwm_device **ptr, *pwm; - - ptr = devres_alloc(devm_pwm_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); + struct pwm_device *pwm; + int ret; pwm = pwm_get(dev, con_id); - if (!IS_ERR(pwm)) { - *ptr = pwm; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } + if (IS_ERR(pwm)) + return pwm; + + ret = devm_add_action_or_reset(dev, devm_pwm_release, pwm); + if (ret) + return ERR_PTR(ret); return pwm; } @@ -1154,19 +1113,16 @@ EXPORT_SYMBOL_GPL(devm_pwm_get); struct pwm_device *devm_of_pwm_get(struct device *dev, struct device_node *np, const char *con_id) { - struct pwm_device **ptr, *pwm; - - ptr = devres_alloc(devm_pwm_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); + struct pwm_device *pwm; + int ret; pwm = of_pwm_get(dev, np, con_id); - if (!IS_ERR(pwm)) { - *ptr = pwm; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } + if (IS_ERR(pwm)) + return pwm; + + ret = devm_add_action_or_reset(dev, devm_pwm_release, pwm); + if (ret) + return ERR_PTR(ret); return pwm; } @@ -1188,53 +1144,24 @@ struct pwm_device *devm_fwnode_pwm_get(struct device *dev, struct fwnode_handle *fwnode, const char *con_id) { - struct pwm_device **ptr, *pwm = ERR_PTR(-ENODEV); - - ptr = devres_alloc(devm_pwm_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); + struct pwm_device *pwm = ERR_PTR(-ENODEV); + int ret; if (is_of_node(fwnode)) pwm = of_pwm_get(dev, to_of_node(fwnode), con_id); else if (is_acpi_node(fwnode)) pwm = acpi_pwm_get(fwnode); + if (IS_ERR(pwm)) + return pwm; - if (!IS_ERR(pwm)) { - *ptr = pwm; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } + ret = devm_add_action_or_reset(dev, devm_pwm_release, pwm); + if (ret) + return ERR_PTR(ret); return pwm; } EXPORT_SYMBOL_GPL(devm_fwnode_pwm_get); -static int devm_pwm_match(struct device *dev, void *res, void *data) -{ - struct pwm_device **p = res; - - if (WARN_ON(!p || !*p)) - return 0; - - return *p == data; -} - -/** - * devm_pwm_put() - resource managed pwm_put() - * @dev: device for PWM consumer - * @pwm: PWM device - * - * Release a PWM previously allocated using devm_pwm_get(). Calling this - * function is usually not needed because devm-allocated resources are - * automatically released on driver detach. - */ -void devm_pwm_put(struct device *dev, struct pwm_device *pwm) -{ - WARN_ON(devres_release(dev, devm_pwm_release, devm_pwm_match, pwm)); -} -EXPORT_SYMBOL_GPL(devm_pwm_put); - #ifdef CONFIG_DEBUG_FS static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) { @@ -1259,6 +1186,9 @@ static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) seq_printf(s, " polarity: %s", state.polarity ? "inverse" : "normal"); + if (state.usage_power) + seq_puts(s, " usage_power"); + seq_puts(s, "\n"); } } diff --git a/drivers/pwm/pwm-atmel-hlcdc.c b/drivers/pwm/pwm-atmel-hlcdc.c index 6ab597e54005..4459325d3650 100644 --- a/drivers/pwm/pwm-atmel-hlcdc.c +++ b/drivers/pwm/pwm-atmel-hlcdc.c @@ -266,8 +266,6 @@ static int atmel_hlcdc_pwm_probe(struct platform_device *pdev) chip->chip.ops = &atmel_hlcdc_pwm_ops; chip->chip.dev = dev; chip->chip.npwm = 1; - chip->chip.of_xlate = of_pwm_xlate_with_flags; - chip->chip.of_pwm_n_cells = 3; ret = pwmchip_add(&chip->chip); if (ret) { diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c index 8451d3e846be..bf398f21484d 100644 --- a/drivers/pwm/pwm-atmel-tcb.c +++ b/drivers/pwm/pwm-atmel-tcb.c @@ -469,8 +469,6 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev) tcbpwm->chip.dev = &pdev->dev; tcbpwm->chip.ops = &atmel_tcb_pwm_ops; - tcbpwm->chip.of_xlate = of_pwm_xlate_with_flags; - tcbpwm->chip.of_pwm_n_cells = 3; tcbpwm->chip.npwm = NPWM; tcbpwm->channel = channel; tcbpwm->regmap = regmap; diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c index 29b5ad03f715..a8162bae3e8a 100644 --- a/drivers/pwm/pwm-atmel.c +++ b/drivers/pwm/pwm-atmel.c @@ -436,8 +436,6 @@ static int atmel_pwm_probe(struct platform_device *pdev) atmel_pwm->chip.dev = &pdev->dev; atmel_pwm->chip.ops = &atmel_pwm_ops; - atmel_pwm->chip.of_xlate = of_pwm_xlate_with_flags; - atmel_pwm->chip.of_pwm_n_cells = 3; atmel_pwm->chip.npwm = 4; ret = pwmchip_add(&atmel_pwm->chip); diff --git a/drivers/pwm/pwm-bcm-iproc.c b/drivers/pwm/pwm-bcm-iproc.c index edd2ce1760ab..0226bf697f09 100644 --- a/drivers/pwm/pwm-bcm-iproc.c +++ b/drivers/pwm/pwm-bcm-iproc.c @@ -210,8 +210,6 @@ static int iproc_pwmc_probe(struct platform_device *pdev) ip->chip.dev = &pdev->dev; ip->chip.ops = &iproc_pwm_ops; ip->chip.npwm = 4; - ip->chip.of_xlate = of_pwm_xlate_with_flags; - ip->chip.of_pwm_n_cells = 3; ip->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(ip->base)) diff --git a/drivers/pwm/pwm-bcm-kona.c b/drivers/pwm/pwm-bcm-kona.c index 800b9edf2e71..8c85c66ea5c9 100644 --- a/drivers/pwm/pwm-bcm-kona.c +++ b/drivers/pwm/pwm-bcm-kona.c @@ -272,8 +272,6 @@ static int kona_pwmc_probe(struct platform_device *pdev) kp->chip.dev = &pdev->dev; kp->chip.ops = &kona_pwm_ops; kp->chip.npwm = 6; - kp->chip.of_xlate = of_pwm_xlate_with_flags; - kp->chip.of_pwm_n_cells = 3; kp->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(kp->base)) diff --git a/drivers/pwm/pwm-bcm2835.c b/drivers/pwm/pwm-bcm2835.c index fc240d5b8121..50b8594be31d 100644 --- a/drivers/pwm/pwm-bcm2835.c +++ b/drivers/pwm/pwm-bcm2835.c @@ -159,8 +159,6 @@ static int bcm2835_pwm_probe(struct platform_device *pdev) pc->chip.dev = &pdev->dev; pc->chip.ops = &bcm2835_pwm_ops; pc->chip.npwm = 2; - pc->chip.of_xlate = of_pwm_xlate_with_flags; - pc->chip.of_pwm_n_cells = 3; platform_set_drvdata(pdev, pc); diff --git a/drivers/pwm/pwm-berlin.c b/drivers/pwm/pwm-berlin.c index acb6fbc3cc32..5537b5f6dd5d 100644 --- a/drivers/pwm/pwm-berlin.c +++ b/drivers/pwm/pwm-berlin.c @@ -56,17 +56,17 @@ static inline struct berlin_pwm_chip *to_berlin_pwm_chip(struct pwm_chip *chip) return container_of(chip, struct berlin_pwm_chip, chip); } -static inline u32 berlin_pwm_readl(struct berlin_pwm_chip *chip, +static inline u32 berlin_pwm_readl(struct berlin_pwm_chip *bpc, unsigned int channel, unsigned long offset) { - return readl_relaxed(chip->base + channel * 0x10 + offset); + return readl_relaxed(bpc->base + channel * 0x10 + offset); } -static inline void berlin_pwm_writel(struct berlin_pwm_chip *chip, +static inline void berlin_pwm_writel(struct berlin_pwm_chip *bpc, unsigned int channel, u32 value, unsigned long offset) { - writel_relaxed(value, chip->base + channel * 0x10 + offset); + writel_relaxed(value, bpc->base + channel * 0x10 + offset); } static int berlin_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) @@ -87,15 +87,15 @@ static void berlin_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) kfree(channel); } -static int berlin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm_dev, - int duty_ns, int period_ns) +static int berlin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + u64 duty_ns, u64 period_ns) { - struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip); + struct berlin_pwm_chip *bpc = to_berlin_pwm_chip(chip); bool prescale_4096 = false; u32 value, duty, period; u64 cycles; - cycles = clk_get_rate(pwm->clk); + cycles = clk_get_rate(bpc->clk); cycles *= period_ns; do_div(cycles, NSEC_PER_SEC); @@ -112,68 +112,101 @@ static int berlin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm_dev, do_div(cycles, period_ns); duty = cycles; - value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL); + value = berlin_pwm_readl(bpc, pwm->hwpwm, BERLIN_PWM_CONTROL); if (prescale_4096) value |= BERLIN_PWM_PRESCALE_4096; else value &= ~BERLIN_PWM_PRESCALE_4096; - berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_CONTROL); + berlin_pwm_writel(bpc, pwm->hwpwm, value, BERLIN_PWM_CONTROL); - berlin_pwm_writel(pwm, pwm_dev->hwpwm, duty, BERLIN_PWM_DUTY); - berlin_pwm_writel(pwm, pwm_dev->hwpwm, period, BERLIN_PWM_TCNT); + berlin_pwm_writel(bpc, pwm->hwpwm, duty, BERLIN_PWM_DUTY); + berlin_pwm_writel(bpc, pwm->hwpwm, period, BERLIN_PWM_TCNT); return 0; } static int berlin_pwm_set_polarity(struct pwm_chip *chip, - struct pwm_device *pwm_dev, + struct pwm_device *pwm, enum pwm_polarity polarity) { - struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip); + struct berlin_pwm_chip *bpc = to_berlin_pwm_chip(chip); u32 value; - value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL); + value = berlin_pwm_readl(bpc, pwm->hwpwm, BERLIN_PWM_CONTROL); if (polarity == PWM_POLARITY_NORMAL) value &= ~BERLIN_PWM_INVERT_POLARITY; else value |= BERLIN_PWM_INVERT_POLARITY; - berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_CONTROL); + berlin_pwm_writel(bpc, pwm->hwpwm, value, BERLIN_PWM_CONTROL); return 0; } -static int berlin_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm_dev) +static int berlin_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) { - struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip); + struct berlin_pwm_chip *bpc = to_berlin_pwm_chip(chip); u32 value; - value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_EN); + value = berlin_pwm_readl(bpc, pwm->hwpwm, BERLIN_PWM_EN); value |= BERLIN_PWM_ENABLE; - berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_EN); + berlin_pwm_writel(bpc, pwm->hwpwm, value, BERLIN_PWM_EN); return 0; } static void berlin_pwm_disable(struct pwm_chip *chip, - struct pwm_device *pwm_dev) + struct pwm_device *pwm) { - struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip); + struct berlin_pwm_chip *bpc = to_berlin_pwm_chip(chip); u32 value; - value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_EN); + value = berlin_pwm_readl(bpc, pwm->hwpwm, BERLIN_PWM_EN); value &= ~BERLIN_PWM_ENABLE; - berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_EN); + berlin_pwm_writel(bpc, pwm->hwpwm, value, BERLIN_PWM_EN); +} + +static int berlin_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + int err; + bool enabled = pwm->state.enabled; + + if (state->polarity != pwm->state.polarity) { + if (enabled) { + berlin_pwm_disable(chip, pwm); + enabled = false; + } + + err = berlin_pwm_set_polarity(chip, pwm, state->polarity); + if (err) + return err; + } + + if (!state->enabled) { + if (enabled) + berlin_pwm_disable(chip, pwm); + return 0; + } + + if (state->period != pwm->state.period || + state->duty_cycle != pwm->state.duty_cycle) { + err = berlin_pwm_config(chip, pwm, state->duty_cycle, state->period); + if (err) + return err; + } + + if (!enabled) + return berlin_pwm_enable(chip, pwm); + + return 0; } static const struct pwm_ops berlin_pwm_ops = { .request = berlin_pwm_request, .free = berlin_pwm_free, - .config = berlin_pwm_config, - .set_polarity = berlin_pwm_set_polarity, - .enable = berlin_pwm_enable, - .disable = berlin_pwm_disable, + .apply = berlin_pwm_apply, .owner = THIS_MODULE, }; @@ -185,99 +218,97 @@ MODULE_DEVICE_TABLE(of, berlin_pwm_match); static int berlin_pwm_probe(struct platform_device *pdev) { - struct berlin_pwm_chip *pwm; + struct berlin_pwm_chip *bpc; int ret; - pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); - if (!pwm) + bpc = devm_kzalloc(&pdev->dev, sizeof(*bpc), GFP_KERNEL); + if (!bpc) return -ENOMEM; - pwm->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(pwm->base)) - return PTR_ERR(pwm->base); + bpc->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(bpc->base)) + return PTR_ERR(bpc->base); - pwm->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(pwm->clk)) - return PTR_ERR(pwm->clk); + bpc->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(bpc->clk)) + return PTR_ERR(bpc->clk); - ret = clk_prepare_enable(pwm->clk); + ret = clk_prepare_enable(bpc->clk); if (ret) return ret; - pwm->chip.dev = &pdev->dev; - pwm->chip.ops = &berlin_pwm_ops; - pwm->chip.npwm = 4; - pwm->chip.of_xlate = of_pwm_xlate_with_flags; - pwm->chip.of_pwm_n_cells = 3; + bpc->chip.dev = &pdev->dev; + bpc->chip.ops = &berlin_pwm_ops; + bpc->chip.npwm = 4; - ret = pwmchip_add(&pwm->chip); + ret = pwmchip_add(&bpc->chip); if (ret < 0) { dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret); - clk_disable_unprepare(pwm->clk); + clk_disable_unprepare(bpc->clk); return ret; } - platform_set_drvdata(pdev, pwm); + platform_set_drvdata(pdev, bpc); return 0; } static int berlin_pwm_remove(struct platform_device *pdev) { - struct berlin_pwm_chip *pwm = platform_get_drvdata(pdev); - int ret; + struct berlin_pwm_chip *bpc = platform_get_drvdata(pdev); + + pwmchip_remove(&bpc->chip); - ret = pwmchip_remove(&pwm->chip); - clk_disable_unprepare(pwm->clk); + clk_disable_unprepare(bpc->clk); - return ret; + return 0; } #ifdef CONFIG_PM_SLEEP static int berlin_pwm_suspend(struct device *dev) { - struct berlin_pwm_chip *pwm = dev_get_drvdata(dev); + struct berlin_pwm_chip *bpc = dev_get_drvdata(dev); unsigned int i; - for (i = 0; i < pwm->chip.npwm; i++) { + for (i = 0; i < bpc->chip.npwm; i++) { struct berlin_pwm_channel *channel; - channel = pwm_get_chip_data(&pwm->chip.pwms[i]); + channel = pwm_get_chip_data(&bpc->chip.pwms[i]); if (!channel) continue; - channel->enable = berlin_pwm_readl(pwm, i, BERLIN_PWM_ENABLE); - channel->ctrl = berlin_pwm_readl(pwm, i, BERLIN_PWM_CONTROL); - channel->duty = berlin_pwm_readl(pwm, i, BERLIN_PWM_DUTY); - channel->tcnt = berlin_pwm_readl(pwm, i, BERLIN_PWM_TCNT); + channel->enable = berlin_pwm_readl(bpc, i, BERLIN_PWM_ENABLE); + channel->ctrl = berlin_pwm_readl(bpc, i, BERLIN_PWM_CONTROL); + channel->duty = berlin_pwm_readl(bpc, i, BERLIN_PWM_DUTY); + channel->tcnt = berlin_pwm_readl(bpc, i, BERLIN_PWM_TCNT); } - clk_disable_unprepare(pwm->clk); + clk_disable_unprepare(bpc->clk); return 0; } static int berlin_pwm_resume(struct device *dev) { - struct berlin_pwm_chip *pwm = dev_get_drvdata(dev); + struct berlin_pwm_chip *bpc = dev_get_drvdata(dev); unsigned int i; int ret; - ret = clk_prepare_enable(pwm->clk); + ret = clk_prepare_enable(bpc->clk); if (ret) return ret; - for (i = 0; i < pwm->chip.npwm; i++) { + for (i = 0; i < bpc->chip.npwm; i++) { struct berlin_pwm_channel *channel; - channel = pwm_get_chip_data(&pwm->chip.pwms[i]); + channel = pwm_get_chip_data(&bpc->chip.pwms[i]); if (!channel) continue; - berlin_pwm_writel(pwm, i, channel->ctrl, BERLIN_PWM_CONTROL); - berlin_pwm_writel(pwm, i, channel->duty, BERLIN_PWM_DUTY); - berlin_pwm_writel(pwm, i, channel->tcnt, BERLIN_PWM_TCNT); - berlin_pwm_writel(pwm, i, channel->enable, BERLIN_PWM_ENABLE); + berlin_pwm_writel(bpc, i, channel->ctrl, BERLIN_PWM_CONTROL); + berlin_pwm_writel(bpc, i, channel->duty, BERLIN_PWM_DUTY); + berlin_pwm_writel(bpc, i, channel->tcnt, BERLIN_PWM_TCNT); + berlin_pwm_writel(bpc, i, channel->enable, BERLIN_PWM_ENABLE); } return 0; diff --git a/drivers/pwm/pwm-clps711x.c b/drivers/pwm/pwm-clps711x.c index f3d17a590305..d7ad88685830 100644 --- a/drivers/pwm/pwm-clps711x.c +++ b/drivers/pwm/pwm-clps711x.c @@ -134,16 +134,7 @@ static int clps711x_pwm_probe(struct platform_device *pdev) spin_lock_init(&priv->lock); - platform_set_drvdata(pdev, priv); - - return pwmchip_add(&priv->chip); -} - -static int clps711x_pwm_remove(struct platform_device *pdev) -{ - struct clps711x_chip *priv = platform_get_drvdata(pdev); - - return pwmchip_remove(&priv->chip); + return devm_pwmchip_add(&pdev->dev, &priv->chip); } static const struct of_device_id __maybe_unused clps711x_pwm_dt_ids[] = { @@ -158,7 +149,6 @@ static struct platform_driver clps711x_pwm_driver = { .of_match_table = of_match_ptr(clps711x_pwm_dt_ids), }, .probe = clps711x_pwm_probe, - .remove = clps711x_pwm_remove, }; module_platform_driver(clps711x_pwm_driver); diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c index 02522a9a3073..7b357d1cf642 100644 --- a/drivers/pwm/pwm-crc.c +++ b/drivers/pwm/pwm-crc.c @@ -173,21 +173,11 @@ static int crystalcove_pwm_probe(struct platform_device *pdev) /* get the PMIC regmap */ pwm->regmap = pmic->regmap; - platform_set_drvdata(pdev, pwm); - - return pwmchip_add(&pwm->chip); -} - -static int crystalcove_pwm_remove(struct platform_device *pdev) -{ - struct crystalcove_pwm *pwm = platform_get_drvdata(pdev); - - return pwmchip_remove(&pwm->chip); + return devm_pwmchip_add(&pdev->dev, &pwm->chip); } static struct platform_driver crystalcove_pwm_driver = { .probe = crystalcove_pwm_probe, - .remove = crystalcove_pwm_remove, .driver = { .name = "crystal_cove_pwm", }, diff --git a/drivers/pwm/pwm-ep93xx.c b/drivers/pwm/pwm-ep93xx.c index 4ca70794ad96..8a3d781e6514 100644 --- a/drivers/pwm/pwm-ep93xx.c +++ b/drivers/pwm/pwm-ep93xx.c @@ -58,111 +58,112 @@ static void ep93xx_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) ep93xx_pwm_release_gpio(pdev); } -static int ep93xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns) +static int ep93xx_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) { + int ret; struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip); - void __iomem *base = ep93xx_pwm->base; - unsigned long long c; - unsigned long period_cycles; - unsigned long duty_cycles; - unsigned long term; - int ret = 0; - - /* - * The clock needs to be enabled to access the PWM registers. - * Configuration can be changed at any time. - */ - if (!pwm_is_enabled(pwm)) { - ret = clk_enable(ep93xx_pwm->clk); - if (ret) - return ret; - } + bool enabled = state->enabled; - c = clk_get_rate(ep93xx_pwm->clk); - c *= period_ns; - do_div(c, 1000000000); - period_cycles = c; + if (state->polarity != pwm->state.polarity) { + if (enabled) { + writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_ENABLE); + clk_disable_unprepare(ep93xx_pwm->clk); + enabled = false; + } - c = period_cycles; - c *= duty_ns; - do_div(c, period_ns); - duty_cycles = c; + /* + * The clock needs to be enabled to access the PWM registers. + * Polarity can only be changed when the PWM is disabled. + */ + ret = clk_prepare_enable(ep93xx_pwm->clk); + if (ret) + return ret; - if (period_cycles < 0x10000 && duty_cycles < 0x10000) { - term = readw(base + EP93XX_PWMx_TERM_COUNT); + if (state->polarity == PWM_POLARITY_INVERSED) + writew(0x1, ep93xx_pwm->base + EP93XX_PWMx_INVERT); + else + writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_INVERT); - /* Order is important if PWM is running */ - if (period_cycles > term) { - writew(period_cycles, base + EP93XX_PWMx_TERM_COUNT); - writew(duty_cycles, base + EP93XX_PWMx_DUTY_CYCLE); - } else { - writew(duty_cycles, base + EP93XX_PWMx_DUTY_CYCLE); - writew(period_cycles, base + EP93XX_PWMx_TERM_COUNT); - } - } else { - ret = -EINVAL; + clk_disable_unprepare(ep93xx_pwm->clk); } - if (!pwm_is_enabled(pwm)) - clk_disable(ep93xx_pwm->clk); - - return ret; -} - -static int ep93xx_pwm_polarity(struct pwm_chip *chip, struct pwm_device *pwm, - enum pwm_polarity polarity) -{ - struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip); - int ret; + if (!state->enabled) { + if (enabled) { + writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_ENABLE); + clk_disable_unprepare(ep93xx_pwm->clk); + } - /* - * The clock needs to be enabled to access the PWM registers. - * Polarity can only be changed when the PWM is disabled. - */ - ret = clk_enable(ep93xx_pwm->clk); - if (ret) - return ret; + return 0; + } - if (polarity == PWM_POLARITY_INVERSED) - writew(0x1, ep93xx_pwm->base + EP93XX_PWMx_INVERT); - else - writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_INVERT); + if (state->period != pwm->state.period || + state->duty_cycle != pwm->state.duty_cycle) { + struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip); + void __iomem *base = ep93xx_pwm->base; + unsigned long long c; + unsigned long period_cycles; + unsigned long duty_cycles; + unsigned long term; + + /* + * The clock needs to be enabled to access the PWM registers. + * Configuration can be changed at any time. + */ + if (!pwm_is_enabled(pwm)) { + ret = clk_prepare_enable(ep93xx_pwm->clk); + if (ret) + return ret; + } - clk_disable(ep93xx_pwm->clk); + c = clk_get_rate(ep93xx_pwm->clk); + c *= state->period; + do_div(c, 1000000000); + period_cycles = c; + + c = period_cycles; + c *= state->duty_cycle; + do_div(c, state->period); + duty_cycles = c; + + if (period_cycles < 0x10000 && duty_cycles < 0x10000) { + term = readw(base + EP93XX_PWMx_TERM_COUNT); + + /* Order is important if PWM is running */ + if (period_cycles > term) { + writew(period_cycles, base + EP93XX_PWMx_TERM_COUNT); + writew(duty_cycles, base + EP93XX_PWMx_DUTY_CYCLE); + } else { + writew(duty_cycles, base + EP93XX_PWMx_DUTY_CYCLE); + writew(period_cycles, base + EP93XX_PWMx_TERM_COUNT); + } + ret = 0; + } else { + ret = -EINVAL; + } - return 0; -} + if (!pwm_is_enabled(pwm)) + clk_disable_unprepare(ep93xx_pwm->clk); -static int ep93xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) -{ - struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip); - int ret; + if (ret) + return ret; + } - ret = clk_enable(ep93xx_pwm->clk); - if (ret) - return ret; + if (!enabled) { + ret = clk_prepare_enable(ep93xx_pwm->clk); + if (ret) + return ret; - writew(0x1, ep93xx_pwm->base + EP93XX_PWMx_ENABLE); + writew(0x1, ep93xx_pwm->base + EP93XX_PWMx_ENABLE); + } return 0; } -static void ep93xx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) -{ - struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip); - - writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_ENABLE); - clk_disable(ep93xx_pwm->clk); -} - static const struct pwm_ops ep93xx_pwm_ops = { .request = ep93xx_pwm_request, .free = ep93xx_pwm_free, - .config = ep93xx_pwm_config, - .set_polarity = ep93xx_pwm_polarity, - .enable = ep93xx_pwm_enable, - .disable = ep93xx_pwm_disable, + .apply = ep93xx_pwm_apply, .owner = THIS_MODULE, }; diff --git a/drivers/pwm/pwm-fsl-ftm.c b/drivers/pwm/pwm-fsl-ftm.c index 0e1ae9469eda..96ccd772280c 100644 --- a/drivers/pwm/pwm-fsl-ftm.c +++ b/drivers/pwm/pwm-fsl-ftm.c @@ -451,8 +451,6 @@ static int fsl_pwm_probe(struct platform_device *pdev) fpc->chip.ops = &fsl_pwm_ops; - fpc->chip.of_xlate = of_pwm_xlate_with_flags; - fpc->chip.of_pwm_n_cells = 3; fpc->chip.npwm = 8; ret = pwmchip_add(&fpc->chip); diff --git a/drivers/pwm/pwm-hibvt.c b/drivers/pwm/pwm-hibvt.c index 82d17fc75c21..4a6e9ad3c0ff 100644 --- a/drivers/pwm/pwm-hibvt.c +++ b/drivers/pwm/pwm-hibvt.c @@ -206,8 +206,6 @@ static int hibvt_pwm_probe(struct platform_device *pdev) pwm_chip->chip.ops = &hibvt_pwm_ops; pwm_chip->chip.dev = &pdev->dev; pwm_chip->chip.npwm = soc->num_pwms; - pwm_chip->chip.of_xlate = of_pwm_xlate_with_flags; - pwm_chip->chip.of_pwm_n_cells = 3; pwm_chip->soc = soc; pwm_chip->base = devm_platform_ioremap_resource(pdev, 0); diff --git a/drivers/pwm/pwm-img.c b/drivers/pwm/pwm-img.c index cc37054589cc..11b16ecc4f96 100644 --- a/drivers/pwm/pwm-img.c +++ b/drivers/pwm/pwm-img.c @@ -156,7 +156,7 @@ static int img_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) struct img_pwm_chip *pwm_chip = to_img_pwm_chip(chip); int ret; - ret = pm_runtime_get_sync(chip->dev); + ret = pm_runtime_resume_and_get(chip->dev); if (ret < 0) return ret; diff --git a/drivers/pwm/pwm-imx-tpm.c b/drivers/pwm/pwm-imx-tpm.c index 97c9133b6876..dbb50493abdd 100644 --- a/drivers/pwm/pwm-imx-tpm.c +++ b/drivers/pwm/pwm-imx-tpm.c @@ -363,8 +363,6 @@ static int pwm_imx_tpm_probe(struct platform_device *pdev) tpm->chip.dev = &pdev->dev; tpm->chip.ops = &imx_tpm_pwm_ops; - tpm->chip.of_xlate = of_pwm_xlate_with_flags; - tpm->chip.of_pwm_n_cells = 3; /* get number of channels */ val = readl(tpm->base + PWM_IMX_TPM_PARAM); diff --git a/drivers/pwm/pwm-imx1.c b/drivers/pwm/pwm-imx1.c index c957b365448e..bcd849496f8d 100644 --- a/drivers/pwm/pwm-imx1.c +++ b/drivers/pwm/pwm-imx1.c @@ -141,8 +141,6 @@ static int pwm_imx1_probe(struct platform_device *pdev) if (!imx) return -ENOMEM; - platform_set_drvdata(pdev, imx); - imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(imx->clk_ipg)) return dev_err_probe(&pdev->dev, PTR_ERR(imx->clk_ipg), @@ -161,16 +159,7 @@ static int pwm_imx1_probe(struct platform_device *pdev) if (IS_ERR(imx->mmio_base)) return PTR_ERR(imx->mmio_base); - return pwmchip_add(&imx->chip); -} - -static int pwm_imx1_remove(struct platform_device *pdev) -{ - struct pwm_imx1_chip *imx = platform_get_drvdata(pdev); - - pwm_imx1_clk_disable_unprepare(&imx->chip); - - return pwmchip_remove(&imx->chip); + return devm_pwmchip_add(&pdev->dev, &imx->chip); } static struct platform_driver pwm_imx1_driver = { @@ -179,7 +168,6 @@ static struct platform_driver pwm_imx1_driver = { .of_match_table = pwm_imx1_dt_ids, }, .probe = pwm_imx1_probe, - .remove = pwm_imx1_remove, }; module_platform_driver(pwm_imx1_driver); diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c index ba695115c160..f6588a96fbd9 100644 --- a/drivers/pwm/pwm-imx27.c +++ b/drivers/pwm/pwm-imx27.c @@ -329,9 +329,6 @@ static int pwm_imx27_probe(struct platform_device *pdev) imx->chip.dev = &pdev->dev; imx->chip.npwm = 1; - imx->chip.of_xlate = of_pwm_xlate_with_flags; - imx->chip.of_pwm_n_cells = 3; - imx->mmio_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(imx->mmio_base)) return PTR_ERR(imx->mmio_base); diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c index 5b6bdcdcecf5..990e7904c7f1 100644 --- a/drivers/pwm/pwm-jz4740.c +++ b/drivers/pwm/pwm-jz4740.c @@ -244,8 +244,6 @@ static int jz4740_pwm_probe(struct platform_device *pdev) jz4740->chip.dev = dev; jz4740->chip.ops = &jz4740_pwm_ops; jz4740->chip.npwm = info->num_pwms; - jz4740->chip.of_xlate = of_pwm_xlate_with_flags; - jz4740->chip.of_pwm_n_cells = 3; platform_set_drvdata(pdev, jz4740); diff --git a/drivers/pwm/pwm-lpc18xx-sct.c b/drivers/pwm/pwm-lpc18xx-sct.c index b643ac61a2e7..8e461f3baa05 100644 --- a/drivers/pwm/pwm-lpc18xx-sct.c +++ b/drivers/pwm/pwm-lpc18xx-sct.c @@ -371,8 +371,6 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev) lpc18xx_pwm->chip.dev = &pdev->dev; lpc18xx_pwm->chip.ops = &lpc18xx_pwm_ops; lpc18xx_pwm->chip.npwm = 16; - lpc18xx_pwm->chip.of_xlate = of_pwm_xlate_with_flags; - lpc18xx_pwm->chip.of_pwm_n_cells = 3; /* SCT counter must be in unify (32 bit) mode */ lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CONFIG, diff --git a/drivers/pwm/pwm-lpss-pci.c b/drivers/pwm/pwm-lpss-pci.c index cf749ea0de9f..c893ec3d2fb4 100644 --- a/drivers/pwm/pwm-lpss-pci.c +++ b/drivers/pwm/pwm-lpss-pci.c @@ -69,12 +69,8 @@ static int pwm_lpss_probe_pci(struct pci_dev *pdev, static void pwm_lpss_remove_pci(struct pci_dev *pdev) { - struct pwm_lpss_chip *lpwm = pci_get_drvdata(pdev); - pm_runtime_forbid(&pdev->dev); pm_runtime_get_sync(&pdev->dev); - - pwm_lpss_remove(lpwm); } #ifdef CONFIG_PM diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c index 986786be1e49..928570430cef 100644 --- a/drivers/pwm/pwm-lpss-platform.c +++ b/drivers/pwm/pwm-lpss-platform.c @@ -85,10 +85,8 @@ static int pwm_lpss_probe_platform(struct platform_device *pdev) static int pwm_lpss_remove_platform(struct platform_device *pdev) { - struct pwm_lpss_chip *lpwm = platform_get_drvdata(pdev); - pm_runtime_disable(&pdev->dev); - return pwm_lpss_remove(lpwm); + return 0; } static const struct acpi_device_id pwm_lpss_acpi_match[] = { diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c index 58b4031524af..36d4e83e6b79 100644 --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c @@ -236,7 +236,7 @@ struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r, lpwm->chip.ops = &pwm_lpss_ops; lpwm->chip.npwm = info->npwm; - ret = pwmchip_add(&lpwm->chip); + ret = devm_pwmchip_add(dev, &lpwm->chip); if (ret) { dev_err(dev, "failed to add PWM chip: %d\n", ret); return ERR_PTR(ret); @@ -252,12 +252,6 @@ struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r, } EXPORT_SYMBOL_GPL(pwm_lpss_probe); -int pwm_lpss_remove(struct pwm_lpss_chip *lpwm) -{ - return pwmchip_remove(&lpwm->chip); -} -EXPORT_SYMBOL_GPL(pwm_lpss_remove); - MODULE_DESCRIPTION("PWM driver for Intel LPSS"); MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h index 70db7e389d66..8b3476f25e06 100644 --- a/drivers/pwm/pwm-lpss.h +++ b/drivers/pwm/pwm-lpss.h @@ -35,6 +35,5 @@ struct pwm_lpss_boardinfo { struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r, const struct pwm_lpss_boardinfo *info); -int pwm_lpss_remove(struct pwm_lpss_chip *lpwm); #endif /* __PWM_LPSS_H */ diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index 9eb060613cb4..3cf3bcf5ddfc 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -551,8 +551,6 @@ static int meson_pwm_probe(struct platform_device *pdev) meson->chip.dev = &pdev->dev; meson->chip.ops = &meson_pwm_ops; meson->chip.npwm = MESON_NUM_PWMS; - meson->chip.of_xlate = of_pwm_xlate_with_flags; - meson->chip.of_pwm_n_cells = 3; meson->data = of_device_get_match_data(&pdev->dev); @@ -560,31 +558,21 @@ static int meson_pwm_probe(struct platform_device *pdev) if (err < 0) return err; - err = pwmchip_add(&meson->chip); + err = devm_pwmchip_add(&pdev->dev, &meson->chip); if (err < 0) { dev_err(&pdev->dev, "failed to register PWM chip: %d\n", err); return err; } - platform_set_drvdata(pdev, meson); - return 0; } -static int meson_pwm_remove(struct platform_device *pdev) -{ - struct meson_pwm *meson = platform_get_drvdata(pdev); - - return pwmchip_remove(&meson->chip); -} - static struct platform_driver meson_pwm_driver = { .driver = { .name = "meson-pwm", .of_match_table = meson_pwm_matches, }, .probe = meson_pwm_probe, - .remove = meson_pwm_remove, }; module_platform_driver(meson_pwm_driver); diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c index 0266e84e982c..a22180803bd7 100644 --- a/drivers/pwm/pwm-mxs.c +++ b/drivers/pwm/pwm-mxs.c @@ -138,8 +138,6 @@ static int mxs_pwm_probe(struct platform_device *pdev) mxs->chip.dev = &pdev->dev; mxs->chip.ops = &mxs_pwm_ops; - mxs->chip.of_xlate = of_pwm_xlate_with_flags; - mxs->chip.of_pwm_n_cells = 3; ret = of_property_read_u32(np, "fsl,pwm-number", &mxs->chip.npwm); if (ret < 0) { diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c index 612b3c859295..507a2d945b90 100644 --- a/drivers/pwm/pwm-omap-dmtimer.c +++ b/drivers/pwm/pwm-omap-dmtimer.c @@ -404,8 +404,6 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev) omap->chip.dev = &pdev->dev; omap->chip.ops = &pwm_omap_dmtimer_ops; omap->chip.npwm = 1; - omap->chip.of_xlate = of_pwm_xlate_with_flags; - omap->chip.of_pwm_n_cells = 3; mutex_init(&omap->mutex); diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c index 7c9f174de64e..42ed770b432c 100644 --- a/drivers/pwm/pwm-pca9685.c +++ b/drivers/pwm/pwm-pca9685.c @@ -23,11 +23,11 @@ #include <linux/bitmap.h> /* - * Because the PCA9685 has only one prescaler per chip, changing the period of - * one channel affects the period of all 16 PWM outputs! - * However, the ratio between each configured duty cycle and the chip-wide - * period remains constant, because the OFF time is set in proportion to the - * counter range. + * Because the PCA9685 has only one prescaler per chip, only the first channel + * that is enabled is allowed to change the prescale register. + * PWM channels requested afterwards must use a period that results in the same + * prescale setting as the one set by the first requested channel. + * GPIOs do not count as enabled PWMs as they are not using the prescaler. */ #define PCA9685_MODE1 0x00 @@ -78,8 +78,9 @@ struct pca9685 { struct pwm_chip chip; struct regmap *regmap; -#if IS_ENABLED(CONFIG_GPIOLIB) struct mutex lock; + DECLARE_BITMAP(pwms_enabled, PCA9685_MAXCHAN + 1); +#if IS_ENABLED(CONFIG_GPIOLIB) struct gpio_chip gpio; DECLARE_BITMAP(pwms_inuse, PCA9685_MAXCHAN + 1); #endif @@ -90,51 +91,120 @@ static inline struct pca9685 *to_pca(struct pwm_chip *chip) return container_of(chip, struct pca9685, chip); } +/* This function is supposed to be called with the lock mutex held */ +static bool pca9685_prescaler_can_change(struct pca9685 *pca, int channel) +{ + /* No PWM enabled: Change allowed */ + if (bitmap_empty(pca->pwms_enabled, PCA9685_MAXCHAN + 1)) + return true; + /* More than one PWM enabled: Change not allowed */ + if (bitmap_weight(pca->pwms_enabled, PCA9685_MAXCHAN + 1) > 1) + return false; + /* + * Only one PWM enabled: Change allowed if the PWM about to + * be changed is the one that is already enabled + */ + return test_bit(channel, pca->pwms_enabled); +} + +static int pca9685_read_reg(struct pca9685 *pca, unsigned int reg, unsigned int *val) +{ + struct device *dev = pca->chip.dev; + int err; + + err = regmap_read(pca->regmap, reg, val); + if (err) + dev_err(dev, "regmap_read of register 0x%x failed: %pe\n", reg, ERR_PTR(err)); + + return err; +} + +static int pca9685_write_reg(struct pca9685 *pca, unsigned int reg, unsigned int val) +{ + struct device *dev = pca->chip.dev; + int err; + + err = regmap_write(pca->regmap, reg, val); + if (err) + dev_err(dev, "regmap_write to register 0x%x failed: %pe\n", reg, ERR_PTR(err)); + + return err; +} + /* Helper function to set the duty cycle ratio to duty/4096 (e.g. duty=2048 -> 50%) */ static void pca9685_pwm_set_duty(struct pca9685 *pca, int channel, unsigned int duty) { + struct pwm_device *pwm = &pca->chip.pwms[channel]; + unsigned int on, off; + if (duty == 0) { /* Set the full OFF bit, which has the highest precedence */ - regmap_write(pca->regmap, REG_OFF_H(channel), LED_FULL); + pca9685_write_reg(pca, REG_OFF_H(channel), LED_FULL); + return; } else if (duty >= PCA9685_COUNTER_RANGE) { /* Set the full ON bit and clear the full OFF bit */ - regmap_write(pca->regmap, REG_ON_H(channel), LED_FULL); - regmap_write(pca->regmap, REG_OFF_H(channel), 0); - } else { - /* Set OFF time (clears the full OFF bit) */ - regmap_write(pca->regmap, REG_OFF_L(channel), duty & 0xff); - regmap_write(pca->regmap, REG_OFF_H(channel), (duty >> 8) & 0xf); - /* Clear the full ON bit */ - regmap_write(pca->regmap, REG_ON_H(channel), 0); + pca9685_write_reg(pca, REG_ON_H(channel), LED_FULL); + pca9685_write_reg(pca, REG_OFF_H(channel), 0); + return; } + + + if (pwm->state.usage_power && channel < PCA9685_MAXCHAN) { + /* + * If usage_power is set, the pca9685 driver will phase shift + * the individual channels relative to their channel number. + * This improves EMI because the enabled channels no longer + * turn on at the same time, while still maintaining the + * configured duty cycle / power output. + */ + on = channel * PCA9685_COUNTER_RANGE / PCA9685_MAXCHAN; + } else + on = 0; + + off = (on + duty) % PCA9685_COUNTER_RANGE; + + /* Set ON time (clears full ON bit) */ + pca9685_write_reg(pca, REG_ON_L(channel), on & 0xff); + pca9685_write_reg(pca, REG_ON_H(channel), (on >> 8) & 0xf); + /* Set OFF time (clears full OFF bit) */ + pca9685_write_reg(pca, REG_OFF_L(channel), off & 0xff); + pca9685_write_reg(pca, REG_OFF_H(channel), (off >> 8) & 0xf); } static unsigned int pca9685_pwm_get_duty(struct pca9685 *pca, int channel) { - unsigned int off_h = 0, val = 0; + struct pwm_device *pwm = &pca->chip.pwms[channel]; + unsigned int off = 0, on = 0, val = 0; if (WARN_ON(channel >= PCA9685_MAXCHAN)) { /* HW does not support reading state of "all LEDs" channel */ return 0; } - regmap_read(pca->regmap, LED_N_OFF_H(channel), &off_h); - if (off_h & LED_FULL) { + pca9685_read_reg(pca, LED_N_OFF_H(channel), &off); + if (off & LED_FULL) { /* Full OFF bit is set */ return 0; } - regmap_read(pca->regmap, LED_N_ON_H(channel), &val); - if (val & LED_FULL) { + pca9685_read_reg(pca, LED_N_ON_H(channel), &on); + if (on & LED_FULL) { /* Full ON bit is set */ return PCA9685_COUNTER_RANGE; } - if (regmap_read(pca->regmap, LED_N_OFF_L(channel), &val)) { - /* Reset val to 0 in case reading LED_N_OFF_L failed */ + pca9685_read_reg(pca, LED_N_OFF_L(channel), &val); + off = ((off & 0xf) << 8) | (val & 0xff); + if (!pwm->state.usage_power) + return off; + + /* Read ON register to calculate duty cycle of staggered output */ + if (pca9685_read_reg(pca, LED_N_ON_L(channel), &val)) { + /* Reset val to 0 in case reading LED_N_ON_L failed */ val = 0; } - return ((off_h & 0xf) << 8) | (val & 0xff); + on = ((on & 0xf) << 8) | (val & 0xff); + return (off - on) & (PCA9685_COUNTER_RANGE - 1); } #if IS_ENABLED(CONFIG_GPIOLIB) @@ -240,8 +310,6 @@ static int pca9685_pwm_gpio_probe(struct pca9685 *pca) { struct device *dev = pca->chip.dev; - mutex_init(&pca->lock); - pca->gpio.label = dev_name(dev); pca->gpio.parent = dev; pca->gpio.request = pca9685_pwm_gpio_request; @@ -277,16 +345,23 @@ static inline int pca9685_pwm_gpio_probe(struct pca9685 *pca) static void pca9685_set_sleep_mode(struct pca9685 *pca, bool enable) { - regmap_update_bits(pca->regmap, PCA9685_MODE1, - MODE1_SLEEP, enable ? MODE1_SLEEP : 0); + struct device *dev = pca->chip.dev; + int err = regmap_update_bits(pca->regmap, PCA9685_MODE1, + MODE1_SLEEP, enable ? MODE1_SLEEP : 0); + if (err) { + dev_err(dev, "regmap_update_bits of register 0x%x failed: %pe\n", + PCA9685_MODE1, ERR_PTR(err)); + return; + } + if (!enable) { /* Wait 500us for the oscillator to be back up */ udelay(500); } } -static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, - const struct pwm_state *state) +static int __pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) { struct pca9685 *pca = to_pca(chip); unsigned long long duty, prescale; @@ -307,8 +382,14 @@ static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, return 0; } - regmap_read(pca->regmap, PCA9685_PRESCALE, &val); + pca9685_read_reg(pca, PCA9685_PRESCALE, &val); if (prescale != val) { + if (!pca9685_prescaler_can_change(pca, pwm->hwpwm)) { + dev_err(chip->dev, + "pwm not changed: periods of enabled pwms must match!\n"); + return -EBUSY; + } + /* * Putting the chip briefly into SLEEP mode * at this point won't interfere with the @@ -319,7 +400,7 @@ static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, pca9685_set_sleep_mode(pca, true); /* Change the chip-wide output frequency */ - regmap_write(pca->regmap, PCA9685_PRESCALE, prescale); + pca9685_write_reg(pca, PCA9685_PRESCALE, prescale); /* Wake the chip up */ pca9685_set_sleep_mode(pca, false); @@ -331,6 +412,25 @@ static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, return 0; } +static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + struct pca9685 *pca = to_pca(chip); + int ret; + + mutex_lock(&pca->lock); + ret = __pca9685_pwm_apply(chip, pwm, state); + if (ret == 0) { + if (state->enabled) + set_bit(pwm->hwpwm, pca->pwms_enabled); + else + clear_bit(pwm->hwpwm, pca->pwms_enabled); + } + mutex_unlock(&pca->lock); + + return ret; +} + static void pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_state *state) { @@ -339,7 +439,7 @@ static void pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, unsigned int val = 0; /* Calculate (chip-wide) period from prescale value */ - regmap_read(pca->regmap, PCA9685_PRESCALE, &val); + pca9685_read_reg(pca, PCA9685_PRESCALE, &val); /* * PCA9685_OSC_CLOCK_MHZ is 25, i.e. an integer divider of 1000. * The following calculation is therefore only a multiplication @@ -372,6 +472,14 @@ static int pca9685_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) if (pca9685_pwm_test_and_set_inuse(pca, pwm->hwpwm)) return -EBUSY; + + if (pwm->hwpwm < PCA9685_MAXCHAN) { + /* PWMs - except the "all LEDs" channel - default to enabled */ + mutex_lock(&pca->lock); + set_bit(pwm->hwpwm, pca->pwms_enabled); + mutex_unlock(&pca->lock); + } + pm_runtime_get_sync(chip->dev); return 0; @@ -381,7 +489,11 @@ static void pca9685_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) { struct pca9685 *pca = to_pca(chip); + mutex_lock(&pca->lock); pca9685_pwm_set_duty(pca, pwm->hwpwm, 0); + clear_bit(pwm->hwpwm, pca->pwms_enabled); + mutex_unlock(&pca->lock); + pm_runtime_put(chip->dev); pca9685_pwm_clear_inuse(pca, pwm->hwpwm); } @@ -422,7 +534,11 @@ static int pca9685_pwm_probe(struct i2c_client *client, i2c_set_clientdata(client, pca); - regmap_read(pca->regmap, PCA9685_MODE2, ®); + mutex_init(&pca->lock); + + ret = pca9685_read_reg(pca, PCA9685_MODE2, ®); + if (ret) + return ret; if (device_property_read_bool(&client->dev, "invert")) reg |= MODE2_INVRT; @@ -434,16 +550,20 @@ static int pca9685_pwm_probe(struct i2c_client *client, else reg |= MODE2_OUTDRV; - regmap_write(pca->regmap, PCA9685_MODE2, reg); + ret = pca9685_write_reg(pca, PCA9685_MODE2, reg); + if (ret) + return ret; /* Disable all LED ALLCALL and SUBx addresses to avoid bus collisions */ - regmap_read(pca->regmap, PCA9685_MODE1, ®); + pca9685_read_reg(pca, PCA9685_MODE1, ®); reg &= ~(MODE1_ALLCALL | MODE1_SUB1 | MODE1_SUB2 | MODE1_SUB3); - regmap_write(pca->regmap, PCA9685_MODE1, reg); + pca9685_write_reg(pca, PCA9685_MODE1, reg); - /* Reset OFF registers to POR default */ - regmap_write(pca->regmap, PCA9685_ALL_LED_OFF_L, LED_FULL); - regmap_write(pca->regmap, PCA9685_ALL_LED_OFF_H, LED_FULL); + /* Reset OFF/ON registers to POR default */ + pca9685_write_reg(pca, PCA9685_ALL_LED_OFF_L, LED_FULL); + pca9685_write_reg(pca, PCA9685_ALL_LED_OFF_H, LED_FULL); + pca9685_write_reg(pca, PCA9685_ALL_LED_ON_L, 0); + pca9685_write_reg(pca, PCA9685_ALL_LED_ON_H, 0); pca->chip.ops = &pca9685_pwm_ops; /* Add an extra channel for ALL_LED */ diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c index cfb683827d32..e091a528e33c 100644 --- a/drivers/pwm/pwm-pxa.c +++ b/drivers/pwm/pwm-pxa.c @@ -165,7 +165,7 @@ pxa_pwm_of_xlate(struct pwm_chip *pc, const struct of_phandle_args *args) static int pwm_probe(struct platform_device *pdev) { const struct platform_device_id *id = platform_get_device_id(pdev); - struct pxa_pwm_chip *pwm; + struct pxa_pwm_chip *pc; int ret = 0; if (IS_ENABLED(CONFIG_OF) && id == NULL) @@ -174,46 +174,44 @@ static int pwm_probe(struct platform_device *pdev) if (id == NULL) return -EINVAL; - pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); - if (pwm == NULL) + pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); + if (pc == NULL) return -ENOMEM; - pwm->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(pwm->clk)) - return PTR_ERR(pwm->clk); + pc->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(pc->clk)) + return PTR_ERR(pc->clk); - pwm->chip.dev = &pdev->dev; - pwm->chip.ops = &pxa_pwm_ops; - pwm->chip.npwm = (id->driver_data & HAS_SECONDARY_PWM) ? 2 : 1; + pc->chip.dev = &pdev->dev; + pc->chip.ops = &pxa_pwm_ops; + pc->chip.npwm = (id->driver_data & HAS_SECONDARY_PWM) ? 2 : 1; if (IS_ENABLED(CONFIG_OF)) { - pwm->chip.of_xlate = pxa_pwm_of_xlate; - pwm->chip.of_pwm_n_cells = 1; + pc->chip.of_xlate = pxa_pwm_of_xlate; + pc->chip.of_pwm_n_cells = 1; } - pwm->mmio_base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(pwm->mmio_base)) - return PTR_ERR(pwm->mmio_base); + pc->mmio_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(pc->mmio_base)) + return PTR_ERR(pc->mmio_base); - ret = pwmchip_add(&pwm->chip); + ret = pwmchip_add(&pc->chip); if (ret < 0) { dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); return ret; } - platform_set_drvdata(pdev, pwm); + platform_set_drvdata(pdev, pc); return 0; } static int pwm_remove(struct platform_device *pdev) { - struct pxa_pwm_chip *chip; + struct pxa_pwm_chip *pc; - chip = platform_get_drvdata(pdev); - if (chip == NULL) - return -ENODEV; + pc = platform_get_drvdata(pdev); - return pwmchip_remove(&chip->chip); + return pwmchip_remove(&pc->chip); } static struct platform_driver pwm_driver = { diff --git a/drivers/pwm/pwm-renesas-tpu.c b/drivers/pwm/pwm-renesas-tpu.c index e2959fae0969..b853e7942605 100644 --- a/drivers/pwm/pwm-renesas-tpu.c +++ b/drivers/pwm/pwm-renesas-tpu.c @@ -408,8 +408,6 @@ static int tpu_probe(struct platform_device *pdev) tpu->chip.dev = &pdev->dev; tpu->chip.ops = &tpu_pwm_ops; - tpu->chip.of_xlate = of_pwm_xlate_with_flags; - tpu->chip.of_pwm_n_cells = 3; tpu->chip.npwm = TPU_CHANNEL_MAX; pm_runtime_enable(&pdev->dev); diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index 301785fa293e..cbe900877724 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c @@ -354,11 +354,6 @@ static int rockchip_pwm_probe(struct platform_device *pdev) pc->chip.ops = &rockchip_pwm_ops; pc->chip.npwm = 1; - if (pc->data->supports_polarity) { - pc->chip.of_xlate = of_pwm_xlate_with_flags; - pc->chip.of_pwm_n_cells = 3; - } - enable_conf = pc->data->enable_conf; ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl); enabled = (ctrl & enable_conf) == enable_conf; diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c index 515489fa4f6d..f6c528f02d43 100644 --- a/drivers/pwm/pwm-samsung.c +++ b/drivers/pwm/pwm-samsung.c @@ -526,9 +526,6 @@ static int pwm_samsung_probe(struct platform_device *pdev) ret = pwm_samsung_parse_dt(chip); if (ret) return ret; - - chip->chip.of_xlate = of_pwm_xlate_with_flags; - chip->chip.of_pwm_n_cells = 3; } else { if (!pdev->dev.platform_data) { dev_err(&pdev->dev, "no platform data specified\n"); diff --git a/drivers/pwm/pwm-sifive.c b/drivers/pwm/pwm-sifive.c index 688737f091ac..420edc4aa94a 100644 --- a/drivers/pwm/pwm-sifive.c +++ b/drivers/pwm/pwm-sifive.c @@ -242,8 +242,6 @@ static int pwm_sifive_probe(struct platform_device *pdev) chip = &ddata->chip; chip->dev = dev; chip->ops = &pwm_sifive_ops; - chip->of_xlate = of_pwm_xlate_with_flags; - chip->of_pwm_n_cells = 3; chip->npwm = 4; ddata->regs = devm_platform_ioremap_resource(pdev, 0); diff --git a/drivers/pwm/pwm-spear.c b/drivers/pwm/pwm-spear.c index 1a1cedfd11ce..48c31dac2f32 100644 --- a/drivers/pwm/pwm-spear.c +++ b/drivers/pwm/pwm-spear.c @@ -75,7 +75,7 @@ static inline void spear_pwm_writel(struct spear_pwm_chip *chip, } static int spear_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns) + u64 duty_ns, u64 period_ns) { struct spear_pwm_chip *pc = to_spear_pwm_chip(chip); u64 val, div, clk_rate; @@ -163,10 +163,35 @@ static void spear_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) clk_disable(pc->clk); } +static int spear_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + int err; + + if (state->polarity != PWM_POLARITY_NORMAL) + return -EINVAL; + + if (!state->enabled) { + if (pwm->state.enabled) + spear_pwm_disable(chip, pwm); + return 0; + } + + if (state->period != pwm->state.period || + state->duty_cycle != pwm->state.duty_cycle) { + err = spear_pwm_config(chip, pwm, state->duty_cycle, state->period); + if (err) + return err; + } + + if (!pwm->state.enabled) + return spear_pwm_enable(chip, pwm); + + return 0; +} + static const struct pwm_ops spear_pwm_ops = { - .config = spear_pwm_config, - .enable = spear_pwm_enable, - .disable = spear_pwm_disable, + .apply = spear_pwm_apply, .owner = THIS_MODULE, }; @@ -228,14 +253,13 @@ static int spear_pwm_probe(struct platform_device *pdev) static int spear_pwm_remove(struct platform_device *pdev) { struct spear_pwm_chip *pc = platform_get_drvdata(pdev); - int i; - for (i = 0; i < NUM_PWM; i++) - pwm_disable(&pc->chip.pwms[i]); + pwmchip_remove(&pc->chip); /* clk was prepared in probe, hence unprepare it here */ clk_unprepare(pc->clk); - return pwmchip_remove(&pc->chip); + + return 0; } static const struct of_device_id spear_pwm_of_match[] = { diff --git a/drivers/pwm/pwm-sprd.c b/drivers/pwm/pwm-sprd.c index 98c479dfae31..f2a85e8dd941 100644 --- a/drivers/pwm/pwm-sprd.c +++ b/drivers/pwm/pwm-sprd.c @@ -284,7 +284,9 @@ static int sprd_pwm_remove(struct platform_device *pdev) { struct sprd_pwm_chip *spc = platform_get_drvdata(pdev); - return pwmchip_remove(&spc->chip); + pwmchip_remove(&spc->chip); + + return 0; } static const struct of_device_id sprd_pwm_of_match[] = { diff --git a/drivers/pwm/pwm-stm32-lp.c b/drivers/pwm/pwm-stm32-lp.c index af08f564ef1d..93dd03618465 100644 --- a/drivers/pwm/pwm-stm32-lp.c +++ b/drivers/pwm/pwm-stm32-lp.c @@ -208,8 +208,6 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev) priv->chip.dev = &pdev->dev; priv->chip.ops = &stm32_pwm_lp_ops; priv->chip.npwm = 1; - priv->chip.of_xlate = of_pwm_xlate_with_flags; - priv->chip.of_pwm_n_cells = 3; ret = pwmchip_add(&priv->chip); if (ret < 0) diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c index c46fb90036ab..794ca5b02968 100644 --- a/drivers/pwm/pwm-stm32.c +++ b/drivers/pwm/pwm-stm32.c @@ -621,8 +621,6 @@ static int stm32_pwm_probe(struct platform_device *pdev) priv->regmap = ddata->regmap; priv->clk = ddata->clk; priv->max_arr = ddata->max_arr; - priv->chip.of_xlate = of_pwm_xlate_with_flags; - priv->chip.of_pwm_n_cells = 3; if (!priv->regmap || !priv->clk) return -EINVAL; diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c index e01becd102c0..c952604e91f3 100644 --- a/drivers/pwm/pwm-sun4i.c +++ b/drivers/pwm/pwm-sun4i.c @@ -460,8 +460,6 @@ static int sun4i_pwm_probe(struct platform_device *pdev) pwm->chip.dev = &pdev->dev; pwm->chip.ops = &sun4i_pwm_ops; pwm->chip.npwm = pwm->data->npwm; - pwm->chip.of_xlate = of_pwm_xlate_with_flags; - pwm->chip.of_pwm_n_cells = 3; spin_lock_init(&pwm->ctrl_lock); diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c index c529a170bcdd..11a10b575ace 100644 --- a/drivers/pwm/pwm-tegra.c +++ b/drivers/pwm/pwm-tegra.c @@ -300,32 +300,12 @@ static int tegra_pwm_probe(struct platform_device *pdev) static int tegra_pwm_remove(struct platform_device *pdev) { struct tegra_pwm_chip *pc = platform_get_drvdata(pdev); - unsigned int i; - int err; - - if (WARN_ON(!pc)) - return -ENODEV; - - err = clk_prepare_enable(pc->clk); - if (err < 0) - return err; - - for (i = 0; i < pc->chip.npwm; i++) { - struct pwm_device *pwm = &pc->chip.pwms[i]; - - if (!pwm_is_enabled(pwm)) - if (clk_prepare_enable(pc->clk) < 0) - continue; - pwm_writel(pc, i, 0); - - clk_disable_unprepare(pc->clk); - } + pwmchip_remove(&pc->chip); reset_control_assert(pc->rst); - clk_disable_unprepare(pc->clk); - return pwmchip_remove(&pc->chip); + return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c index b9a17ab0c202..dec3f1fb150c 100644 --- a/drivers/pwm/pwm-tiecap.c +++ b/drivers/pwm/pwm-tiecap.c @@ -48,16 +48,13 @@ static inline struct ecap_pwm_chip *to_ecap_pwm_chip(struct pwm_chip *chip) * duty_ns = 10^9 * duty_cycles / PWM_CLK_RATE */ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns) + int duty_ns, int period_ns, int enabled) { struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip); u32 period_cycles, duty_cycles; unsigned long long c; u16 value; - if (period_ns > NSEC_PER_SEC) - return -ERANGE; - c = pc->clk_rate; c = c * period_ns; do_div(c, NSEC_PER_SEC); @@ -82,7 +79,7 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, writew(value, pc->mmio_base + ECCTL2); - if (!pwm_is_enabled(pwm)) { + if (!enabled) { /* Update active registers if not running */ writel(duty_cycles, pc->mmio_base + CAP2); writel(period_cycles, pc->mmio_base + CAP1); @@ -96,7 +93,7 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, writel(period_cycles, pc->mmio_base + CAP3); } - if (!pwm_is_enabled(pwm)) { + if (!enabled) { value = readw(pc->mmio_base + ECCTL2); /* Disable APWM mode to put APWM output Low */ value &= ~ECCTL2_APWM_MODE; @@ -168,20 +165,49 @@ static void ecap_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) pm_runtime_put_sync(pc->chip.dev); } -static void ecap_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) +static int ecap_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) { - if (pwm_is_enabled(pwm)) { - dev_warn(chip->dev, "Removing PWM device without disabling\n"); - pm_runtime_put_sync(chip->dev); + int err; + int enabled = pwm->state.enabled; + + if (state->polarity != pwm->state.polarity) { + + if (enabled) { + ecap_pwm_disable(chip, pwm); + enabled = false; + } + + err = ecap_pwm_set_polarity(chip, pwm, state->polarity); + if (err) + return err; + } + + if (!state->enabled) { + if (enabled) + ecap_pwm_disable(chip, pwm); + return 0; } + + if (state->period != pwm->state.period || + state->duty_cycle != pwm->state.duty_cycle) { + if (state->period > NSEC_PER_SEC) + return -ERANGE; + + err = ecap_pwm_config(chip, pwm, state->duty_cycle, + state->period, enabled); + if (err) + return err; + } + + if (!enabled) + return ecap_pwm_enable(chip, pwm); + + return 0; } static const struct pwm_ops ecap_pwm_ops = { - .free = ecap_pwm_free, - .config = ecap_pwm_config, - .set_polarity = ecap_pwm_set_polarity, - .enable = ecap_pwm_enable, - .disable = ecap_pwm_disable, + .apply = ecap_pwm_apply, .owner = THIS_MODULE, }; @@ -224,8 +250,6 @@ static int ecap_pwm_probe(struct platform_device *pdev) pc->chip.dev = &pdev->dev; pc->chip.ops = &ecap_pwm_ops; - pc->chip.of_xlate = of_pwm_xlate_with_flags; - pc->chip.of_pwm_n_cells = 3; pc->chip.npwm = 1; pc->mmio_base = devm_platform_ioremap_resource(pdev, 0); diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index 90095a19bf2d..17909fa53211 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -447,8 +447,6 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev) pc->chip.dev = &pdev->dev; pc->chip.ops = &ehrpwm_pwm_ops; - pc->chip.of_xlate = of_pwm_xlate_with_flags; - pc->chip.of_pwm_n_cells = 3; pc->chip.npwm = NUM_PWM_CHANNEL; pc->mmio_base = devm_platform_ioremap_resource(pdev, 0); diff --git a/drivers/pwm/pwm-visconti.c b/drivers/pwm/pwm-visconti.c index 46d903786366..af4e37d3e3a6 100644 --- a/drivers/pwm/pwm-visconti.c +++ b/drivers/pwm/pwm-visconti.c @@ -82,17 +82,14 @@ static int visconti_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, return -ERANGE; /* - * PWMC controls a divider that divides the input clk by a - * power of two between 1 and 8. As a smaller divider yields - * higher precision, pick the smallest possible one. + * PWMC controls a divider that divides the input clk by a power of two + * between 1 and 8. As a smaller divider yields higher precision, pick + * the smallest possible one. As period is at most 0xffff << 3, pwmc0 is + * in the intended range [0..3]. */ - if (period > 0xffff) { - pwmc0 = ilog2(period >> 16); - if (WARN_ON(pwmc0 > 3)) - return -EINVAL; - } else { - pwmc0 = 0; - } + pwmc0 = fls(period >> 16); + if (WARN_ON(pwmc0 > 3)) + return -EINVAL; period >>= pwmc0; duty_cycle >>= pwmc0; diff --git a/drivers/pwm/pwm-vt8500.c b/drivers/pwm/pwm-vt8500.c index 52fe5d19473a..ea2aa151080a 100644 --- a/drivers/pwm/pwm-vt8500.c +++ b/drivers/pwm/pwm-vt8500.c @@ -207,8 +207,6 @@ static int vt8500_pwm_probe(struct platform_device *pdev) chip->chip.dev = &pdev->dev; chip->chip.ops = &vt8500_pwm_ops; - chip->chip.of_xlate = of_pwm_xlate_with_flags; - chip->chip.of_pwm_n_cells = 3; chip->chip.npwm = VT8500_NR_PWMS; chip->clk = devm_clk_get(&pdev->dev, NULL); @@ -240,15 +238,13 @@ static int vt8500_pwm_probe(struct platform_device *pdev) static int vt8500_pwm_remove(struct platform_device *pdev) { - struct vt8500_chip *chip; + struct vt8500_chip *chip = platform_get_drvdata(pdev); - chip = platform_get_drvdata(pdev); - if (chip == NULL) - return -ENODEV; + pwmchip_remove(&chip->chip); clk_unprepare(chip->clk); - return pwmchip_remove(&chip->chip); + return 0; } static struct platform_driver vt8500_pwm_driver = { diff --git a/drivers/regulator/lp87565-regulator.c b/drivers/regulator/lp87565-regulator.c index eeab9d3c824b..d059ae85047a 100644 --- a/drivers/regulator/lp87565-regulator.c +++ b/drivers/regulator/lp87565-regulator.c @@ -11,6 +11,17 @@ #include <linux/mfd/lp87565.h> +enum LP87565_regulator_id { + /* BUCK's */ + LP87565_BUCK_0, + LP87565_BUCK_1, + LP87565_BUCK_2, + LP87565_BUCK_3, + LP87565_BUCK_10, + LP87565_BUCK_23, + LP87565_BUCK_3210, +}; + #define LP87565_REGULATOR(_name, _id, _of, _ops, _n, _vr, _vm, \ _er, _em, _ev, _delay, _lr, _cr) \ [_id] = { \ diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index e68fcedc999c..9a6eedc3994a 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -26,6 +26,7 @@ config REMOTEPROC_CDEV config IMX_REMOTEPROC tristate "i.MX remoteproc support" depends on ARCH_MXC + depends on HAVE_ARM_SMCCC select MAILBOX help Say y here to support iMX's remote processors via the remote diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index d6338872c6db..d88f76f5305e 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -3,6 +3,7 @@ * Copyright (c) 2017 Pengutronix, Oleksij Rempel <kernel@pengutronix.de> */ +#include <linux/arm-smccc.h> #include <linux/clk.h> #include <linux/err.h> #include <linux/interrupt.h> @@ -50,6 +51,11 @@ #define IMX_RPROC_MEM_MAX 32 +#define IMX_SIP_RPROC 0xC2000005 +#define IMX_SIP_RPROC_START 0x00 +#define IMX_SIP_RPROC_STARTED 0x01 +#define IMX_SIP_RPROC_STOP 0x02 + /** * struct imx_rproc_mem - slim internal memory structure * @cpu_addr: MPU virtual address of the memory region @@ -74,6 +80,15 @@ struct imx_rproc_att { int flags; }; +/* Remote core start/stop method */ +enum imx_rproc_method { + IMX_RPROC_NONE, + /* Through syscon regmap */ + IMX_RPROC_MMIO, + /* Through ARM SMCCC */ + IMX_RPROC_SMC, +}; + struct imx_rproc_dcfg { u32 src_reg; u32 src_mask; @@ -81,6 +96,7 @@ struct imx_rproc_dcfg { u32 src_stop; const struct imx_rproc_att *att; size_t att_size; + enum imx_rproc_method method; }; struct imx_rproc { @@ -98,6 +114,36 @@ struct imx_rproc { void __iomem *rsc_table; }; +static const struct imx_rproc_att imx_rproc_att_imx8mn[] = { + /* dev addr , sys addr , size , flags */ + /* ITCM */ + { 0x00000000, 0x007E0000, 0x00020000, ATT_OWN }, + /* OCRAM_S */ + { 0x00180000, 0x00180000, 0x00009000, 0 }, + /* OCRAM */ + { 0x00900000, 0x00900000, 0x00020000, 0 }, + /* OCRAM */ + { 0x00920000, 0x00920000, 0x00020000, 0 }, + /* OCRAM */ + { 0x00940000, 0x00940000, 0x00050000, 0 }, + /* QSPI Code - alias */ + { 0x08000000, 0x08000000, 0x08000000, 0 }, + /* DDR (Code) - alias */ + { 0x10000000, 0x40000000, 0x0FFE0000, 0 }, + /* DTCM */ + { 0x20000000, 0x00800000, 0x00020000, ATT_OWN }, + /* OCRAM_S - alias */ + { 0x20180000, 0x00180000, 0x00008000, ATT_OWN }, + /* OCRAM */ + { 0x20200000, 0x00900000, 0x00020000, ATT_OWN }, + /* OCRAM */ + { 0x20220000, 0x00920000, 0x00020000, ATT_OWN }, + /* OCRAM */ + { 0x20240000, 0x00940000, 0x00040000, ATT_OWN }, + /* DDR (Data) */ + { 0x40000000, 0x40000000, 0x80000000, 0 }, +}; + static const struct imx_rproc_att imx_rproc_att_imx8mq[] = { /* dev addr , sys addr , size , flags */ /* TCML - alias */ @@ -126,6 +172,20 @@ static const struct imx_rproc_att imx_rproc_att_imx8mq[] = { { 0x40000000, 0x40000000, 0x80000000, 0 }, }; +static const struct imx_rproc_att imx_rproc_att_imx8ulp[] = { + {0x1FFC0000, 0x1FFC0000, 0xC0000, ATT_OWN}, + {0x21000000, 0x21000000, 0x10000, ATT_OWN}, + {0x80000000, 0x80000000, 0x60000000, 0} +}; + +static const struct imx_rproc_att imx_rproc_att_imx7ulp[] = { + {0x1FFD0000, 0x1FFD0000, 0x30000, ATT_OWN}, + {0x20000000, 0x20000000, 0x10000, ATT_OWN}, + {0x2F000000, 0x2F000000, 0x20000, ATT_OWN}, + {0x2F020000, 0x2F020000, 0x20000, ATT_OWN}, + {0x60000000, 0x60000000, 0x40000000, 0} +}; + static const struct imx_rproc_att imx_rproc_att_imx7d[] = { /* dev addr , sys addr , size , flags */ /* OCRAM_S (M4 Boot code) - alias */ @@ -176,6 +236,12 @@ static const struct imx_rproc_att imx_rproc_att_imx6sx[] = { { 0x80000000, 0x80000000, 0x60000000, 0 }, }; +static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn = { + .att = imx_rproc_att_imx8mn, + .att_size = ARRAY_SIZE(imx_rproc_att_imx8mn), + .method = IMX_RPROC_SMC, +}; + static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = { .src_reg = IMX7D_SRC_SCR, .src_mask = IMX7D_M4_RST_MASK, @@ -183,6 +249,19 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = { .src_stop = IMX7D_M4_STOP, .att = imx_rproc_att_imx8mq, .att_size = ARRAY_SIZE(imx_rproc_att_imx8mq), + .method = IMX_RPROC_MMIO, +}; + +static const struct imx_rproc_dcfg imx_rproc_cfg_imx8ulp = { + .att = imx_rproc_att_imx8ulp, + .att_size = ARRAY_SIZE(imx_rproc_att_imx8ulp), + .method = IMX_RPROC_NONE, +}; + +static const struct imx_rproc_dcfg imx_rproc_cfg_imx7ulp = { + .att = imx_rproc_att_imx7ulp, + .att_size = ARRAY_SIZE(imx_rproc_att_imx7ulp), + .method = IMX_RPROC_NONE, }; static const struct imx_rproc_dcfg imx_rproc_cfg_imx7d = { @@ -192,6 +271,7 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx7d = { .src_stop = IMX7D_M4_STOP, .att = imx_rproc_att_imx7d, .att_size = ARRAY_SIZE(imx_rproc_att_imx7d), + .method = IMX_RPROC_MMIO, }; static const struct imx_rproc_dcfg imx_rproc_cfg_imx6sx = { @@ -201,6 +281,7 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx6sx = { .src_stop = IMX6SX_M4_STOP, .att = imx_rproc_att_imx6sx, .att_size = ARRAY_SIZE(imx_rproc_att_imx6sx), + .method = IMX_RPROC_MMIO, }; static int imx_rproc_start(struct rproc *rproc) @@ -208,12 +289,24 @@ static int imx_rproc_start(struct rproc *rproc) struct imx_rproc *priv = rproc->priv; const struct imx_rproc_dcfg *dcfg = priv->dcfg; struct device *dev = priv->dev; + struct arm_smccc_res res; int ret; - ret = regmap_update_bits(priv->regmap, dcfg->src_reg, - dcfg->src_mask, dcfg->src_start); + switch (dcfg->method) { + case IMX_RPROC_MMIO: + ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, + dcfg->src_start); + break; + case IMX_RPROC_SMC: + arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_START, 0, 0, 0, 0, 0, 0, &res); + ret = res.a0; + break; + default: + return -EOPNOTSUPP; + } + if (ret) - dev_err(dev, "Failed to enable M4!\n"); + dev_err(dev, "Failed to enable remote core!\n"); return ret; } @@ -223,12 +316,26 @@ static int imx_rproc_stop(struct rproc *rproc) struct imx_rproc *priv = rproc->priv; const struct imx_rproc_dcfg *dcfg = priv->dcfg; struct device *dev = priv->dev; + struct arm_smccc_res res; int ret; - ret = regmap_update_bits(priv->regmap, dcfg->src_reg, - dcfg->src_mask, dcfg->src_stop); + switch (dcfg->method) { + case IMX_RPROC_MMIO: + ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, + dcfg->src_stop); + break; + case IMX_RPROC_SMC: + arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STOP, 0, 0, 0, 0, 0, 0, &res); + ret = res.a0; + if (res.a1) + dev_info(dev, "Not in wfi, force stopped\n"); + break; + default: + return -EOPNOTSUPP; + } + if (ret) - dev_err(dev, "Failed to stop M4!\n"); + dev_err(dev, "Failed to stop remote core\n"); return ret; } @@ -560,12 +667,37 @@ static void imx_rproc_free_mbox(struct rproc *rproc) static int imx_rproc_detect_mode(struct imx_rproc *priv) { + struct regmap_config config = { .name = "imx-rproc" }; const struct imx_rproc_dcfg *dcfg = priv->dcfg; struct device *dev = priv->dev; + struct regmap *regmap; + struct arm_smccc_res res; int ret; u32 val; - ret = regmap_read(priv->regmap, dcfg->src_reg, &val); + switch (dcfg->method) { + case IMX_RPROC_NONE: + priv->rproc->state = RPROC_DETACHED; + return 0; + case IMX_RPROC_SMC: + arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STARTED, 0, 0, 0, 0, 0, 0, &res); + if (res.a0) + priv->rproc->state = RPROC_DETACHED; + return 0; + default: + break; + } + + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon"); + if (IS_ERR(regmap)) { + dev_err(dev, "failed to find syscon\n"); + return PTR_ERR(regmap); + } + + priv->regmap = regmap; + regmap_attach_dev(dev, regmap, &config); + + ret = regmap_read(regmap, dcfg->src_reg, &val); if (ret) { dev_err(dev, "Failed to read src\n"); return ret; @@ -577,24 +709,44 @@ static int imx_rproc_detect_mode(struct imx_rproc *priv) return 0; } +static int imx_rproc_clk_enable(struct imx_rproc *priv) +{ + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + struct device *dev = priv->dev; + int ret; + + /* Remote core is not under control of Linux */ + if (dcfg->method == IMX_RPROC_NONE) + return 0; + + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) { + dev_err(dev, "Failed to get clock\n"); + return PTR_ERR(priv->clk); + } + + /* + * clk for M4 block including memory. Should be + * enabled before .start for FW transfer. + */ + ret = clk_prepare_enable(priv->clk); + if (ret) { + dev_err(dev, "Failed to enable clock\n"); + return ret; + } + + return 0; +} + static int imx_rproc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct imx_rproc *priv; struct rproc *rproc; - struct regmap_config config = { .name = "imx-rproc" }; const struct imx_rproc_dcfg *dcfg; - struct regmap *regmap; int ret; - regmap = syscon_regmap_lookup_by_phandle(np, "syscon"); - if (IS_ERR(regmap)) { - dev_err(dev, "failed to find syscon\n"); - return PTR_ERR(regmap); - } - regmap_attach_dev(dev, regmap, &config); - /* set some other name then imx */ rproc = rproc_alloc(dev, "imx-rproc", &imx_rproc_ops, NULL, sizeof(*priv)); @@ -609,7 +761,6 @@ static int imx_rproc_probe(struct platform_device *pdev) priv = rproc->priv; priv->rproc = rproc; - priv->regmap = regmap; priv->dcfg = dcfg; priv->dev = dev; @@ -635,25 +786,15 @@ static int imx_rproc_probe(struct platform_device *pdev) if (ret) goto err_put_mbox; - priv->clk = devm_clk_get(dev, NULL); - if (IS_ERR(priv->clk)) { - dev_err(dev, "Failed to get clock\n"); - ret = PTR_ERR(priv->clk); - goto err_put_mbox; - } - - /* - * clk for M4 block including memory. Should be - * enabled before .start for FW transfer. - */ - ret = clk_prepare_enable(priv->clk); - if (ret) { - dev_err(&rproc->dev, "Failed to enable clock\n"); + ret = imx_rproc_clk_enable(priv); + if (ret) goto err_put_mbox; - } INIT_WORK(&priv->rproc_work, imx_rproc_vq_work); + if (rproc->state != RPROC_DETACHED) + rproc->auto_boot = of_property_read_bool(np, "fsl,auto-boot"); + ret = rproc_add(rproc); if (ret) { dev_err(dev, "rproc_add failed\n"); @@ -688,10 +829,14 @@ static int imx_rproc_remove(struct platform_device *pdev) } static const struct of_device_id imx_rproc_of_match[] = { + { .compatible = "fsl,imx7ulp-cm4", .data = &imx_rproc_cfg_imx7ulp }, { .compatible = "fsl,imx7d-cm4", .data = &imx_rproc_cfg_imx7d }, { .compatible = "fsl,imx6sx-cm4", .data = &imx_rproc_cfg_imx6sx }, { .compatible = "fsl,imx8mq-cm4", .data = &imx_rproc_cfg_imx8mq }, { .compatible = "fsl,imx8mm-cm4", .data = &imx_rproc_cfg_imx8mq }, + { .compatible = "fsl,imx8mn-cm7", .data = &imx_rproc_cfg_imx8mn }, + { .compatible = "fsl,imx8mp-cm7", .data = &imx_rproc_cfg_imx8mn }, + { .compatible = "fsl,imx8ulp-cm33", .data = &imx_rproc_cfg_imx8ulp }, {}, }; MODULE_DEVICE_TABLE(of, imx_rproc_of_match); diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c index e5778e476245..1777a01fa84e 100644 --- a/drivers/remoteproc/pru_rproc.c +++ b/drivers/remoteproc/pru_rproc.c @@ -887,6 +887,9 @@ static const struct of_device_id pru_rproc_match[] = { { .compatible = "ti,am3356-pru", .data = &pru_data }, { .compatible = "ti,am4376-pru", .data = &pru_data }, { .compatible = "ti,am5728-pru", .data = &pru_data }, + { .compatible = "ti,am642-pru", .data = &k3_pru_data }, + { .compatible = "ti,am642-rtu", .data = &k3_rtu_data }, + { .compatible = "ti,am642-tx-pru", .data = &k3_tx_pru_data }, { .compatible = "ti,k2g-pru", .data = &pru_data }, { .compatible = "ti,am654-pru", .data = &k3_pru_data }, { .compatible = "ti,am654-rtu", .data = &k3_rtu_data }, diff --git a/drivers/remoteproc/qcom_q6v5.c b/drivers/remoteproc/qcom_q6v5.c index 9627a950928e..7e9244c748da 100644 --- a/drivers/remoteproc/qcom_q6v5.c +++ b/drivers/remoteproc/qcom_q6v5.c @@ -280,7 +280,7 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, return ret; } - q6v5->state = qcom_smem_state_get(&pdev->dev, "stop", &q6v5->stop_bit); + q6v5->state = devm_qcom_smem_state_get(&pdev->dev, "stop", &q6v5->stop_bit); if (IS_ERR(q6v5->state)) { dev_err(&pdev->dev, "failed to acquire stop state\n"); return PTR_ERR(q6v5->state); diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index b921fc26cd04..a79bee901e9b 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -689,6 +689,25 @@ static const struct adsp_data mpss_resource_init = { .ssctl_id = 0x12, }; +static const struct adsp_data sc8180x_mpss_resource = { + .crash_reason_smem = 421, + .firmware_name = "modem.mdt", + .pas_id = 4, + .has_aggre2_clk = false, + .auto_boot = false, + .active_pd_names = (char*[]){ + "load_state", + NULL + }, + .proxy_pd_names = (char*[]){ + "cx", + NULL + }, + .ssr_name = "mpss", + .sysmon_name = "modem", + .ssctl_id = 0x12, +}; + static const struct adsp_data slpi_resource_init = { .crash_reason_smem = 424, .firmware_name = "slpi.mdt", @@ -811,6 +830,9 @@ static const struct of_device_id adsp_of_match[] = { { .compatible = "qcom,qcs404-cdsp-pas", .data = &cdsp_resource_init }, { .compatible = "qcom,qcs404-wcss-pas", .data = &wcss_resource_init }, { .compatible = "qcom,sc7180-mpss-pas", .data = &mpss_resource_init}, + { .compatible = "qcom,sc8180x-adsp-pas", .data = &sm8150_adsp_resource}, + { .compatible = "qcom,sc8180x-cdsp-pas", .data = &sm8150_cdsp_resource}, + { .compatible = "qcom,sc8180x-mpss-pas", .data = &sc8180x_mpss_resource}, { .compatible = "qcom,sdm845-adsp-pas", .data = &adsp_resource_init}, { .compatible = "qcom,sdm845-cdsp-pas", .data = &cdsp_resource_init}, { .compatible = "qcom,sdx55-mpss-pas", .data = &sdx55_mpss_resource}, diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c index 5f3455aa7e0e..f1cbc6b2edbb 100644 --- a/drivers/remoteproc/qcom_wcnss.c +++ b/drivers/remoteproc/qcom_wcnss.c @@ -624,8 +624,8 @@ static int wcnss_probe(struct platform_device *pdev) wcnss->stop_ack_irq = ret; if (wcnss->stop_ack_irq) { - wcnss->state = qcom_smem_state_get(&pdev->dev, "stop", - &wcnss->stop_bit); + wcnss->state = devm_qcom_smem_state_get(&pdev->dev, "stop", + &wcnss->stop_bit); if (IS_ERR(wcnss->state)) { ret = PTR_ERR(wcnss->state); goto detach_pds; @@ -659,7 +659,6 @@ static int wcnss_remove(struct platform_device *pdev) of_platform_depopulate(&pdev->dev); - qcom_smem_state_put(wcnss->state); rproc_del(wcnss->rproc); qcom_remove_sysmon_subdev(wcnss->sysmon); diff --git a/drivers/remoteproc/remoteproc_cdev.c b/drivers/remoteproc/remoteproc_cdev.c index 0b8a84c04f76..4ad98b0b8caa 100644 --- a/drivers/remoteproc/remoteproc_cdev.c +++ b/drivers/remoteproc/remoteproc_cdev.c @@ -124,7 +124,7 @@ int rproc_char_device_add(struct rproc *rproc) void rproc_char_device_remove(struct rproc *rproc) { - __unregister_chrdev(MAJOR(rproc->dev.devt), rproc->index, 1, "remoteproc"); + cdev_del(&rproc->cdev); } void __init rproc_init_cdev(void) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 76dd8e2b1e7e..7de5905d276a 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -166,6 +166,7 @@ EXPORT_SYMBOL(rproc_va_to_pa); * @rproc: handle of a remote processor * @da: remoteproc device address to translate * @len: length of the memory region @da is pointing to + * @is_iomem: optional pointer filled in to indicate if @da is iomapped memory * * Some remote processors will ask us to allocate them physically contiguous * memory regions (which we call "carveouts"), and map them to specific @@ -183,12 +184,12 @@ EXPORT_SYMBOL(rproc_va_to_pa); * translations on the internal remoteproc memory regions through a platform * implementation specific da_to_va ops, if present. * - * The function returns a valid kernel address on success or NULL on failure. - * * Note: phys_to_virt(iommu_iova_to_phys(rproc->domain, da)) will work too, * but only on kernel direct mapped RAM memory. Instead, we're just using * here the output of the DMA API for the carveouts, which should be more * correct. + * + * Return: a valid kernel address on success or NULL on failure */ void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem) { @@ -509,7 +510,7 @@ static int copy_dma_range_map(struct device *to, struct device *from) * use RSC_DEVMEM resource entries to map their required @da to the physical * address of their base CMA region (ouch, hacky!). * - * Returns 0 on success, or an appropriate error code otherwise + * Return: 0 on success, or an appropriate error code otherwise */ static int rproc_handle_vdev(struct rproc *rproc, void *ptr, int offset, int avail) @@ -644,7 +645,7 @@ void rproc_vdev_release(struct kref *ref) * support dynamically allocating this address using the generic * DMA API (but currently there isn't a use case for that). * - * Returns 0 on success, or an appropriate error code otherwise + * Return: 0 on success, or an appropriate error code otherwise */ static int rproc_handle_trace(struct rproc *rproc, void *ptr, int offset, int avail) @@ -721,6 +722,8 @@ static int rproc_handle_trace(struct rproc *rproc, void *ptr, * tell us ranges of physical addresses the firmware is allowed to request, * and not allow firmwares to request access to physical addresses that * are outside those ranges. + * + * Return: 0 on success, or an appropriate error code otherwise */ static int rproc_handle_devmem(struct rproc *rproc, void *ptr, int offset, int avail) @@ -783,6 +786,8 @@ out: * * This function allocate specified memory entry @mem using * dma_alloc_coherent() as default allocator + * + * Return: 0 on success, or an appropriate error code otherwise */ static int rproc_alloc_carveout(struct rproc *rproc, struct rproc_mem_entry *mem) @@ -889,6 +894,8 @@ dma_free: * * This function releases specified memory entry @mem allocated via * rproc_alloc_carveout() function by @rproc. + * + * Return: 0 on success, or an appropriate error code otherwise */ static int rproc_release_carveout(struct rproc *rproc, struct rproc_mem_entry *mem) @@ -918,6 +925,8 @@ static int rproc_release_carveout(struct rproc *rproc, * (e.g. CMA) more efficiently, and also minimizes the number of TLB entries * needed to map it (in case @rproc is using an IOMMU). Reducing the TLB * pressure is important; it may have a substantial impact on performance. + * + * Return: 0 on success, or an appropriate error code otherwise */ static int rproc_handle_carveout(struct rproc *rproc, void *ptr, int offset, int avail) @@ -1006,6 +1015,8 @@ EXPORT_SYMBOL(rproc_add_carveout); * * This function allocates a rproc_mem_entry struct and fill it with parameters * provided by client. + * + * Return: a valid pointer on success, or NULL on failure */ __printf(8, 9) struct rproc_mem_entry * @@ -1050,6 +1061,8 @@ EXPORT_SYMBOL(rproc_mem_entry_init); * * This function allocates a rproc_mem_entry struct and fill it with parameters * provided by client. + * + * Return: a valid pointer on success, or NULL on failure */ __printf(5, 6) struct rproc_mem_entry * @@ -1789,7 +1802,7 @@ static int rproc_trigger_auto_boot(struct rproc *rproc) * We're initiating an asynchronous firmware loading, so we can * be built-in kernel code, without hanging the boot process. */ - ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, + ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, rproc->firmware, &rproc->dev, GFP_KERNEL, rproc, rproc_auto_boot_callback); if (ret < 0) @@ -1881,6 +1894,8 @@ static int __rproc_detach(struct rproc *rproc) * remoteproc functional again. * * This function can sleep, so it cannot be called from atomic context. + * + * Return: 0 on success or a negative value upon failure */ int rproc_trigger_recovery(struct rproc *rproc) { @@ -1965,7 +1980,7 @@ static void rproc_crash_handler_work(struct work_struct *work) * If the remote processor is already powered on, this function immediately * returns (successfully). * - * Returns 0 on success, and an appropriate error value otherwise. + * Return: 0 on success, and an appropriate error value otherwise */ int rproc_boot(struct rproc *rproc) { @@ -2100,6 +2115,8 @@ EXPORT_SYMBOL(rproc_shutdown); * no longer available. From there it should be possible to remove the * platform driver and even power cycle the application processor (if the HW * supports it) without needing to switch off the remote processor. + * + * Return: 0 on success, and an appropriate error value otherwise */ int rproc_detach(struct rproc *rproc) { @@ -2152,7 +2169,7 @@ EXPORT_SYMBOL(rproc_detach); * This function increments the remote processor's refcount, so always * use rproc_put() to decrement it back once rproc isn't needed anymore. * - * Returns the rproc handle on success, and NULL on failure. + * Return: rproc handle on success, and NULL on failure */ #ifdef CONFIG_OF struct rproc *rproc_get_by_phandle(phandle phandle) @@ -2302,8 +2319,6 @@ static int rproc_validate(struct rproc *rproc) * This is called by the platform-specific rproc implementation, whenever * a new remote processor device is probed. * - * Returns 0 on success and an appropriate error code otherwise. - * * Note: this function initiates an asynchronous firmware loading * context, which will look for virtio devices supported by the rproc's * firmware. @@ -2311,35 +2326,39 @@ static int rproc_validate(struct rproc *rproc) * If found, those virtio devices will be created and added, so as a result * of registering this remote processor, additional virtio drivers might be * probed. + * + * Return: 0 on success and an appropriate error code otherwise */ int rproc_add(struct rproc *rproc) { struct device *dev = &rproc->dev; int ret; - ret = device_add(dev); + ret = rproc_validate(rproc); if (ret < 0) return ret; - ret = rproc_validate(rproc); + /* add char device for this remoteproc */ + ret = rproc_char_device_add(rproc); if (ret < 0) return ret; + ret = device_add(dev); + if (ret < 0) { + put_device(dev); + goto rproc_remove_cdev; + } + dev_info(dev, "%s is available\n", rproc->name); /* create debugfs entries */ rproc_create_debug_dir(rproc); - /* add char device for this remoteproc */ - ret = rproc_char_device_add(rproc); - if (ret < 0) - return ret; - /* if rproc is marked always-on, request it to boot */ if (rproc->auto_boot) { ret = rproc_trigger_auto_boot(rproc); if (ret < 0) - return ret; + goto rproc_remove_dev; } /* expose to rproc_get_by_phandle users */ @@ -2348,6 +2367,13 @@ int rproc_add(struct rproc *rproc) mutex_unlock(&rproc_list_mutex); return 0; + +rproc_remove_dev: + rproc_delete_debug_dir(rproc); + device_del(dev); +rproc_remove_cdev: + rproc_char_device_remove(rproc); + return ret; } EXPORT_SYMBOL(rproc_add); @@ -2364,7 +2390,7 @@ static void devm_rproc_remove(void *rproc) * This function performs like rproc_add() but the registered rproc device will * automatically be removed on driver detach. * - * Returns: 0 on success, negative errno on failure + * Return: 0 on success, negative errno on failure */ int devm_rproc_add(struct device *dev, struct rproc *rproc) { @@ -2472,10 +2498,10 @@ static int rproc_alloc_ops(struct rproc *rproc, const struct rproc_ops *ops) * implementations should then call rproc_add() to complete * the registration of the remote processor. * - * On success the new rproc is returned, and on failure, NULL. - * * Note: _never_ directly deallocate @rproc, even if it was not registered * yet. Instead, when you need to unroll rproc_alloc(), use rproc_free(). + * + * Return: new rproc pointer on success, and NULL on failure */ struct rproc *rproc_alloc(struct device *dev, const char *name, const struct rproc_ops *ops, @@ -2588,7 +2614,7 @@ EXPORT_SYMBOL(rproc_put); * of the outstanding reference created by rproc_alloc. To decrement that * one last refcount, one still needs to call rproc_free(). * - * Returns 0 on success and -EINVAL if @rproc isn't valid. + * Return: 0 on success and -EINVAL if @rproc isn't valid */ int rproc_del(struct rproc *rproc) { @@ -2603,7 +2629,6 @@ int rproc_del(struct rproc *rproc) mutex_unlock(&rproc->lock); rproc_delete_debug_dir(rproc); - rproc_char_device_remove(rproc); /* the rproc is downref'ed as soon as it's removed from the klist */ mutex_lock(&rproc_list_mutex); @@ -2614,6 +2639,7 @@ int rproc_del(struct rproc *rproc) synchronize_rcu(); device_del(&rproc->dev); + rproc_char_device_remove(rproc); return 0; } @@ -2635,7 +2661,7 @@ static void devm_rproc_free(struct device *dev, void *res) * This function performs like rproc_alloc() but the acquired rproc device will * automatically be released on driver detach. * - * Returns: new rproc instance, or NULL on failure + * Return: new rproc instance, or NULL on failure */ struct rproc *devm_rproc_alloc(struct device *dev, const char *name, const struct rproc_ops *ops, @@ -2687,7 +2713,7 @@ EXPORT_SYMBOL(rproc_remove_subdev); * rproc_get_by_child() - acquire rproc handle of @dev's ancestor * @dev: child device to find ancestor of * - * Returns the ancestor rproc instance, or NULL if not found. + * Return: the ancestor rproc instance, or NULL if not found */ struct rproc *rproc_get_by_child(struct device *dev) { diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c index 11423588965a..469c52e62faf 100644 --- a/drivers/remoteproc/remoteproc_elf_loader.c +++ b/drivers/remoteproc/remoteproc_elf_loader.c @@ -31,6 +31,8 @@ * @fw: the ELF firmware image * * Make sure this fw image is sane (ie a correct ELF32/ELF64 file). + * + * Return: 0 on success and -EINVAL upon any failure */ int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw) { @@ -117,11 +119,11 @@ EXPORT_SYMBOL(rproc_elf_sanity_check); * @rproc: the remote processor handle * @fw: the ELF firmware image * - * This function returns the entry point address of the ELF - * image. - * * Note that the boot address is not a configurable property of all remote * processors. Some will always boot at a specific hard-coded address. + * + * Return: entry point address of the ELF image + * */ u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw) { @@ -152,6 +154,8 @@ EXPORT_SYMBOL(rproc_elf_get_boot_addr); * might be different: they might not have iommus, and would prefer to * directly allocate memory for every segment/resource. This is not yet * supported, though. + * + * Return: 0 on success and an appropriate error code otherwise */ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw) { @@ -362,7 +366,7 @@ EXPORT_SYMBOL(rproc_elf_load_rsc_table); * This function finds the location of the loaded resource table. Don't * call this function if the table wasn't loaded yet - it's a bug if you do. * - * Returns the pointer to the resource table if it is found or NULL otherwise. + * Return: pointer to the resource table if it is found or NULL otherwise. * If the table wasn't loaded yet the result is unspecified. */ struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc, diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c index 0cc617f76068..cf4d54e98e6a 100644 --- a/drivers/remoteproc/remoteproc_virtio.c +++ b/drivers/remoteproc/remoteproc_virtio.c @@ -45,7 +45,7 @@ static bool rproc_virtio_notify(struct virtqueue *vq) * when the remote processor signals that a specific virtqueue has pending * messages available. * - * Returns IRQ_NONE if no message was found in the @notifyid virtqueue, + * Return: IRQ_NONE if no message was found in the @notifyid virtqueue, * and otherwise returns IRQ_HANDLED. */ irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int notifyid) @@ -325,7 +325,7 @@ static void rproc_virtio_dev_release(struct device *dev) * This function registers a virtio device. This vdev's partent is * the rproc device. * - * Returns 0 on success or an appropriate error value otherwise. + * Return: 0 on success or an appropriate error value otherwise */ int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id) { @@ -432,6 +432,8 @@ out: * @data: must be null * * This function unregisters an existing virtio device. + * + * Return: 0 */ int rproc_remove_virtio_dev(struct device *dev, void *data) { diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c index 7353f9e7e7af..b643efcf995a 100644 --- a/drivers/remoteproc/stm32_rproc.c +++ b/drivers/remoteproc/stm32_rproc.c @@ -474,14 +474,12 @@ static int stm32_rproc_attach(struct rproc *rproc) static int stm32_rproc_detach(struct rproc *rproc) { struct stm32_rproc *ddata = rproc->priv; - int err, dummy_data, idx; + int err, idx; /* Inform the remote processor of the detach */ idx = stm32_rproc_mbox_idx(rproc, STM32_MBX_DETACH); if (idx >= 0 && ddata->mb[idx].chan) { - /* A dummy data is sent to allow to block on transmit */ - err = mbox_send_message(ddata->mb[idx].chan, - &dummy_data); + err = mbox_send_message(ddata->mb[idx].chan, "stop"); if (err < 0) dev_warn(&rproc->dev, "warning: remote FW detach without ack\n"); } @@ -493,15 +491,13 @@ static int stm32_rproc_detach(struct rproc *rproc) static int stm32_rproc_stop(struct rproc *rproc) { struct stm32_rproc *ddata = rproc->priv; - int err, dummy_data, idx; + int err, idx; /* request shutdown of the remote processor */ if (rproc->state != RPROC_OFFLINE) { idx = stm32_rproc_mbox_idx(rproc, STM32_MBX_SHUTDOWN); if (idx >= 0 && ddata->mb[idx].chan) { - /* a dummy data is sent to allow to block on transmit */ - err = mbox_send_message(ddata->mb[idx].chan, - &dummy_data); + err = mbox_send_message(ddata->mb[idx].chan, "detach"); if (err < 0) dev_warn(&rproc->dev, "warning: remote FW shutdown without ack\n"); } @@ -556,7 +552,7 @@ static void stm32_rproc_kick(struct rproc *rproc, int vqid) continue; if (!ddata->mb[i].chan) return; - err = mbox_send_message(ddata->mb[i].chan, (void *)(long)vqid); + err = mbox_send_message(ddata->mb[i].chan, "kick"); if (err < 0) dev_err(&rproc->dev, "%s: failed (%s, err:%d)\n", __func__, ddata->mb[i].name, err); @@ -580,7 +576,7 @@ static int stm32_rproc_da_to_pa(struct rproc *rproc, continue; *pa = da - p_mem->dev_addr + p_mem->bus_addr; - dev_dbg(dev, "da %llx to pa %#x\n", da, *pa); + dev_dbg(dev, "da %llx to pa %pap\n", da, pa); return 0; } diff --git a/drivers/remoteproc/ti_k3_r5_remoteproc.c b/drivers/remoteproc/ti_k3_r5_remoteproc.c index 5cf8d030a1f0..71615210df3e 100644 --- a/drivers/remoteproc/ti_k3_r5_remoteproc.c +++ b/drivers/remoteproc/ti_k3_r5_remoteproc.c @@ -40,6 +40,8 @@ #define PROC_BOOT_CFG_FLAG_R5_ATCM_EN 0x00002000 /* Available from J7200 SoCs onwards */ #define PROC_BOOT_CFG_FLAG_R5_MEM_INIT_DIS 0x00004000 +/* Applicable to only AM64x SoCs */ +#define PROC_BOOT_CFG_FLAG_R5_SINGLE_CORE 0x00008000 /* R5 TI-SCI Processor Control Flags */ #define PROC_BOOT_CTRL_FLAG_R5_CORE_HALT 0x00000001 @@ -49,6 +51,8 @@ #define PROC_BOOT_STATUS_FLAG_R5_WFI 0x00000002 #define PROC_BOOT_STATUS_FLAG_R5_CLK_GATED 0x00000004 #define PROC_BOOT_STATUS_FLAG_R5_LOCKSTEP_PERMITTED 0x00000100 +/* Applicable to only AM64x SoCs */ +#define PROC_BOOT_STATUS_FLAG_R5_SINGLECORE_ONLY 0x00000200 /** * struct k3_r5_mem - internal memory structure @@ -64,19 +68,29 @@ struct k3_r5_mem { size_t size; }; +/* + * All cluster mode values are not applicable on all SoCs. The following + * are the modes supported on various SoCs: + * Split mode : AM65x, J721E, J7200 and AM64x SoCs + * LockStep mode : AM65x, J721E and J7200 SoCs + * Single-CPU mode : AM64x SoCs only + */ enum cluster_mode { CLUSTER_MODE_SPLIT = 0, CLUSTER_MODE_LOCKSTEP, + CLUSTER_MODE_SINGLECPU, }; /** * struct k3_r5_soc_data - match data to handle SoC variations * @tcm_is_double: flag to denote the larger unified TCMs in certain modes * @tcm_ecc_autoinit: flag to denote the auto-initialization of TCMs for ECC + * @single_cpu_mode: flag to denote if SoC/IP supports Single-CPU mode */ struct k3_r5_soc_data { bool tcm_is_double; bool tcm_ecc_autoinit; + bool single_cpu_mode; }; /** @@ -369,6 +383,13 @@ static inline int k3_r5_core_run(struct k3_r5_core *core) * applicable cores to allow loading into the TCMs. The .prepare() ops is * invoked by remoteproc core before any firmware loading, and is followed * by the .start() ops after loading to actually let the R5 cores run. + * + * The Single-CPU mode on applicable SoCs (eg: AM64x) only uses Core0 to + * execute code, but combines the TCMs from both cores. The resets for both + * cores need to be released to make this possible, as the TCMs are in general + * private to each core. Only Core0 needs to be unhalted for running the + * cluster in this mode. The function uses the same reset logic as LockStep + * mode for this (though the behavior is agnostic of the reset release order). */ static int k3_r5_rproc_prepare(struct rproc *rproc) { @@ -386,7 +407,9 @@ static int k3_r5_rproc_prepare(struct rproc *rproc) return ret; mem_init_dis = !!(cfg & PROC_BOOT_CFG_FLAG_R5_MEM_INIT_DIS); - ret = (cluster->mode == CLUSTER_MODE_LOCKSTEP) ? + /* Re-use LockStep-mode reset logic for Single-CPU mode */ + ret = (cluster->mode == CLUSTER_MODE_LOCKSTEP || + cluster->mode == CLUSTER_MODE_SINGLECPU) ? k3_r5_lockstep_release(cluster) : k3_r5_split_release(core); if (ret) { dev_err(dev, "unable to enable cores for TCM loading, ret = %d\n", @@ -427,6 +450,12 @@ static int k3_r5_rproc_prepare(struct rproc *rproc) * cores. The cores themselves are only halted in the .stop() ops, and the * .unprepare() ops is invoked by the remoteproc core after the remoteproc is * stopped. + * + * The Single-CPU mode on applicable SoCs (eg: AM64x) combines the TCMs from + * both cores. The access is made possible only with releasing the resets for + * both cores, but with only Core0 unhalted. This function re-uses the same + * reset assert logic as LockStep mode for this mode (though the behavior is + * agnostic of the reset assert order). */ static int k3_r5_rproc_unprepare(struct rproc *rproc) { @@ -436,7 +465,9 @@ static int k3_r5_rproc_unprepare(struct rproc *rproc) struct device *dev = kproc->dev; int ret; - ret = (cluster->mode == CLUSTER_MODE_LOCKSTEP) ? + /* Re-use LockStep-mode reset logic for Single-CPU mode */ + ret = (cluster->mode == CLUSTER_MODE_LOCKSTEP || + cluster->mode == CLUSTER_MODE_SINGLECPU) ? k3_r5_lockstep_reset(cluster) : k3_r5_split_reset(core); if (ret) dev_err(dev, "unable to disable cores, ret = %d\n", ret); @@ -455,6 +486,10 @@ static int k3_r5_rproc_unprepare(struct rproc *rproc) * first followed by Core0. The Split-mode requires that Core0 to be maintained * always in a higher power state that Core1 (implying Core1 needs to be started * always only after Core0 is started). + * + * The Single-CPU mode on applicable SoCs (eg: AM64x) only uses Core0 to execute + * code, so only Core0 needs to be unhalted. The function uses the same logic + * flow as Split-mode for this. */ static int k3_r5_rproc_start(struct rproc *rproc) { @@ -539,6 +574,10 @@ put_mbox: * Core0 to be maintained always in a higher power state that Core1 (implying * Core1 needs to be stopped first before Core0). * + * The Single-CPU mode on applicable SoCs (eg: AM64x) only uses Core0 to execute + * code, so only Core0 needs to be halted. The function uses the same logic + * flow as Split-mode for this. + * * Note that the R5F halt operation in general is not effective when the R5F * core is running, but is needed to make sure the core won't run after * deasserting the reset the subsequent time. The asserting of reset can @@ -665,7 +704,9 @@ static const struct rproc_ops k3_r5_rproc_ops = { * * Each R5FSS has a cluster-level setting for configuring the processor * subsystem either in a safety/fault-tolerant LockStep mode or a performance - * oriented Split mode. Each R5F core has a number of settings to either + * oriented Split mode on most SoCs. A fewer SoCs support a non-safety mode + * as an alternate for LockStep mode that exercises only a single R5F core + * called Single-CPU mode. Each R5F core has a number of settings to either * enable/disable each of the TCMs, control which TCM appears at the R5F core's * address 0x0. These settings need to be configured before the resets for the * corresponding core are released. These settings are all protected and managed @@ -677,11 +718,13 @@ static const struct rproc_ops k3_r5_rproc_ops = { * the cores are halted before the .prepare() step. * * The function is called from k3_r5_cluster_rproc_init() and is invoked either - * once (in LockStep mode) or twice (in Split mode). Support for LockStep-mode - * is dictated by an eFUSE register bit, and the config settings retrieved from - * DT are adjusted accordingly as per the permitted cluster mode. All cluster - * level settings like Cluster mode and TEINIT (exception handling state - * dictating ARM or Thumb mode) can only be set and retrieved using Core0. + * once (in LockStep mode or Single-CPU modes) or twice (in Split mode). Support + * for LockStep-mode is dictated by an eFUSE register bit, and the config + * settings retrieved from DT are adjusted accordingly as per the permitted + * cluster mode. Another eFUSE register bit dictates if the R5F cluster only + * supports a Single-CPU mode. All cluster level settings like Cluster mode and + * TEINIT (exception handling state dictating ARM or Thumb mode) can only be set + * and retrieved using Core0. * * The function behavior is different based on the cluster mode. The R5F cores * are configured independently as per their individual settings in Split mode. @@ -700,10 +743,16 @@ static int k3_r5_rproc_configure(struct k3_r5_rproc *kproc) u32 set_cfg = 0, clr_cfg = 0; u64 boot_vec = 0; bool lockstep_en; + bool single_cpu; int ret; core0 = list_first_entry(&cluster->cores, struct k3_r5_core, elem); - core = (cluster->mode == CLUSTER_MODE_LOCKSTEP) ? core0 : kproc->core; + if (cluster->mode == CLUSTER_MODE_LOCKSTEP || + cluster->mode == CLUSTER_MODE_SINGLECPU) { + core = core0; + } else { + core = kproc->core; + } ret = ti_sci_proc_get_status(core->tsp, &boot_vec, &cfg, &ctrl, &stat); @@ -713,23 +762,48 @@ static int k3_r5_rproc_configure(struct k3_r5_rproc *kproc) dev_dbg(dev, "boot_vector = 0x%llx, cfg = 0x%x ctrl = 0x%x stat = 0x%x\n", boot_vec, cfg, ctrl, stat); + /* check if only Single-CPU mode is supported on applicable SoCs */ + if (cluster->soc_data->single_cpu_mode) { + single_cpu = + !!(stat & PROC_BOOT_STATUS_FLAG_R5_SINGLECORE_ONLY); + if (single_cpu && cluster->mode == CLUSTER_MODE_SPLIT) { + dev_err(cluster->dev, "split-mode not permitted, force configuring for single-cpu mode\n"); + cluster->mode = CLUSTER_MODE_SINGLECPU; + } + goto config; + } + + /* check conventional LockStep vs Split mode configuration */ lockstep_en = !!(stat & PROC_BOOT_STATUS_FLAG_R5_LOCKSTEP_PERMITTED); if (!lockstep_en && cluster->mode == CLUSTER_MODE_LOCKSTEP) { dev_err(cluster->dev, "lockstep mode not permitted, force configuring for split-mode\n"); cluster->mode = CLUSTER_MODE_SPLIT; } +config: /* always enable ARM mode and set boot vector to 0 */ boot_vec = 0x0; if (core == core0) { clr_cfg = PROC_BOOT_CFG_FLAG_R5_TEINIT; - /* - * LockStep configuration bit is Read-only on Split-mode _only_ - * devices and system firmware will NACK any requests with the - * bit configured, so program it only on permitted devices - */ - if (lockstep_en) - clr_cfg |= PROC_BOOT_CFG_FLAG_R5_LOCKSTEP; + if (cluster->soc_data->single_cpu_mode) { + /* + * Single-CPU configuration bit can only be configured + * on Core0 and system firmware will NACK any requests + * with the bit configured, so program it only on + * permitted cores + */ + if (cluster->mode == CLUSTER_MODE_SINGLECPU) + set_cfg = PROC_BOOT_CFG_FLAG_R5_SINGLE_CORE; + } else { + /* + * LockStep configuration bit is Read-only on Split-mode + * _only_ devices and system firmware will NACK any + * requests with the bit configured, so program it only + * on permitted devices + */ + if (lockstep_en) + clr_cfg |= PROC_BOOT_CFG_FLAG_R5_LOCKSTEP; + } } if (core->atcm_enable) @@ -894,12 +968,12 @@ static void k3_r5_reserved_mem_exit(struct k3_r5_rproc *kproc) * cores are usable in Split-mode, but only the Core0 TCMs can be used in * LockStep-mode. The newer revisions of the R5FSS IP maximizes these TCMs by * leveraging the Core1 TCMs as well in certain modes where they would have - * otherwise been unusable (Eg: LockStep-mode on J7200 SoCs). This is done by - * making a Core1 TCM visible immediately after the corresponding Core0 TCM. - * The SoC memory map uses the larger 64 KB sizes for the Core0 TCMs, and the - * dts representation reflects this increased size on supported SoCs. The Core0 - * TCM sizes therefore have to be adjusted to only half the original size in - * Split mode. + * otherwise been unusable (Eg: LockStep-mode on J7200 SoCs, Single-CPU mode on + * AM64x SoCs). This is done by making a Core1 TCM visible immediately after the + * corresponding Core0 TCM. The SoC memory map uses the larger 64 KB sizes for + * the Core0 TCMs, and the dts representation reflects this increased size on + * supported SoCs. The Core0 TCM sizes therefore have to be adjusted to only + * half the original size in Split mode. */ static void k3_r5_adjust_tcm_sizes(struct k3_r5_rproc *kproc) { @@ -909,6 +983,7 @@ static void k3_r5_adjust_tcm_sizes(struct k3_r5_rproc *kproc) struct k3_r5_core *core0; if (cluster->mode == CLUSTER_MODE_LOCKSTEP || + cluster->mode == CLUSTER_MODE_SINGLECPU || !cluster->soc_data->tcm_is_double) return; @@ -987,8 +1062,9 @@ static int k3_r5_cluster_rproc_init(struct platform_device *pdev) goto err_add; } - /* create only one rproc in lockstep mode */ - if (cluster->mode == CLUSTER_MODE_LOCKSTEP) + /* create only one rproc in lockstep mode or single-cpu mode */ + if (cluster->mode == CLUSTER_MODE_LOCKSTEP || + cluster->mode == CLUSTER_MODE_SINGLECPU) break; } @@ -1020,11 +1096,12 @@ static void k3_r5_cluster_rproc_exit(void *data) struct rproc *rproc; /* - * lockstep mode has only one rproc associated with first core, whereas - * split-mode has two rprocs associated with each core, and requires - * that core1 be powered down first + * lockstep mode and single-cpu modes have only one rproc associated + * with first core, whereas split-mode has two rprocs associated with + * each core, and requires that core1 be powered down first */ - core = (cluster->mode == CLUSTER_MODE_LOCKSTEP) ? + core = (cluster->mode == CLUSTER_MODE_LOCKSTEP || + cluster->mode == CLUSTER_MODE_SINGLECPU) ? list_first_entry(&cluster->cores, struct k3_r5_core, elem) : list_last_entry(&cluster->cores, struct k3_r5_core, elem); @@ -1272,9 +1349,9 @@ static int k3_r5_core_of_init(struct platform_device *pdev) core->tsp = k3_r5_core_of_get_tsp(dev, core->ti_sci); if (IS_ERR(core->tsp)) { + ret = PTR_ERR(core->tsp); dev_err(dev, "failed to construct ti-sci proc control, ret = %d\n", ret); - ret = PTR_ERR(core->tsp); goto err; } @@ -1396,7 +1473,12 @@ static int k3_r5_probe(struct platform_device *pdev) return -ENOMEM; cluster->dev = dev; - cluster->mode = CLUSTER_MODE_LOCKSTEP; + /* + * default to most common efuse configurations - Split-mode on AM64x + * and LockStep-mode on all others + */ + cluster->mode = data->single_cpu_mode ? + CLUSTER_MODE_SPLIT : CLUSTER_MODE_LOCKSTEP; cluster->soc_data = data; INIT_LIST_HEAD(&cluster->cores); @@ -1450,17 +1532,26 @@ static int k3_r5_probe(struct platform_device *pdev) static const struct k3_r5_soc_data am65_j721e_soc_data = { .tcm_is_double = false, .tcm_ecc_autoinit = false, + .single_cpu_mode = false, }; static const struct k3_r5_soc_data j7200_soc_data = { .tcm_is_double = true, .tcm_ecc_autoinit = true, + .single_cpu_mode = false, +}; + +static const struct k3_r5_soc_data am64_soc_data = { + .tcm_is_double = true, + .tcm_ecc_autoinit = true, + .single_cpu_mode = true, }; static const struct of_device_id k3_r5_of_match[] = { { .compatible = "ti,am654-r5fss", .data = &am65_j721e_soc_data, }, { .compatible = "ti,j721e-r5fss", .data = &am65_j721e_soc_data, }, { .compatible = "ti,j7200-r5fss", .data = &j7200_soc_data, }, + { .compatible = "ti,am64-r5fss", .data = &am64_soc_data, }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, k3_r5_of_match); diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c index 47cd12db2356..16fdefafec5d 100644 --- a/drivers/rtc/rtc-hid-sensor-time.c +++ b/drivers/rtc/rtc-hid-sensor-time.c @@ -328,3 +328,4 @@ module_platform_driver(hid_time_platform_driver); MODULE_DESCRIPTION("HID Sensor Time"); MODULE_AUTHOR("Alexander Holler <holler@ahsoftware.de>"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(IIO_HID); diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index c8df75e99f4c..e34c6cc61983 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -621,7 +621,6 @@ void dasd_set_target_state(struct dasd_device *device, int target) mutex_unlock(&device->state_mutex); dasd_put_device(device); } -EXPORT_SYMBOL(dasd_set_target_state); /* * Enable devices with device numbers in [from..to]. diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index fd42a5fffaed..6bb775236c16 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -69,25 +69,24 @@ static const u8 DASD_DIAG_CMS1[] = { 0xc3, 0xd4, 0xe2, 0xf1 };/* EBCDIC CMS1 */ * resulting condition code and DIAG return code. */ static inline int __dia250(void *iob, int cmd) { - register unsigned long reg2 asm ("2") = (unsigned long) iob; + union register_pair rx = { .even = (unsigned long)iob, }; typedef union { struct dasd_diag_init_io init_io; struct dasd_diag_rw_io rw_io; } addr_type; - int rc; + int cc; - rc = 3; + cc = 3; asm volatile( - " diag 2,%2,0x250\n" - "0: ipm %0\n" - " srl %0,28\n" - " or %0,3\n" + " diag %[rx],%[cmd],0x250\n" + "0: ipm %[cc]\n" + " srl %[cc],28\n" "1:\n" EX_TABLE(0b,1b) - : "+d" (rc), "=m" (*(addr_type *) iob) - : "d" (cmd), "d" (reg2), "m" (*(addr_type *) iob) - : "3", "cc"); - return rc; + : [cc] "+&d" (cc), [rx] "+&d" (rx.pair), "+m" (*(addr_type *)iob) + : [cmd] "d" (cmd) + : "cc"); + return cc | rx.odd; } static inline int dia250(void *iob, int cmd) diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index a6ac505cbdd7..0de1a463c509 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -746,7 +746,7 @@ static void create_uid(struct dasd_eckd_private *private) memcpy(uid->vendor, private->ned->HDA_manufacturer, sizeof(uid->vendor) - 1); EBCASC(uid->vendor, sizeof(uid->vendor) - 1); - memcpy(uid->serial, private->ned->HDA_location, + memcpy(uid->serial, &private->ned->serial, sizeof(uid->serial) - 1); EBCASC(uid->serial, sizeof(uid->serial) - 1); uid->ssid = private->gneq->subsystemID; diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index 73651211789f..65e4630ad2ae 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -332,8 +332,10 @@ struct dasd_ned { __u8 dev_type[6]; __u8 dev_model[3]; __u8 HDA_manufacturer[3]; - __u8 HDA_location[2]; - __u8 HDA_seqno[12]; + struct { + __u8 HDA_location[2]; + __u8 HDA_seqno[12]; + } serial; __u8 ID; __u8 unit_addr; } __attribute__ ((packed)); diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 7faa56399999..29180bdf0977 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -17,7 +17,6 @@ #include <linux/blkdev.h> #include <linux/completion.h> #include <linux/interrupt.h> -#include <linux/platform_device.h> #include <linux/pfn_t.h> #include <linux/uio.h> #include <linux/dax.h> @@ -984,94 +983,11 @@ dcssblk_check_params(void) } /* - * Suspend / Resume - */ -static int dcssblk_freeze(struct device *dev) -{ - struct dcssblk_dev_info *dev_info; - int rc = 0; - - list_for_each_entry(dev_info, &dcssblk_devices, lh) { - switch (dev_info->segment_type) { - case SEG_TYPE_SR: - case SEG_TYPE_ER: - case SEG_TYPE_SC: - if (!dev_info->is_shared) - rc = -EINVAL; - break; - default: - rc = -EINVAL; - break; - } - if (rc) - break; - } - if (rc) - pr_err("Suspending the system failed because DCSS device %s " - "is writable\n", - dev_info->segment_name); - return rc; -} - -static int dcssblk_restore(struct device *dev) -{ - struct dcssblk_dev_info *dev_info; - struct segment_info *entry; - unsigned long start, end; - int rc = 0; - - list_for_each_entry(dev_info, &dcssblk_devices, lh) { - list_for_each_entry(entry, &dev_info->seg_list, lh) { - segment_unload(entry->segment_name); - rc = segment_load(entry->segment_name, SEGMENT_SHARED, - &start, &end); - if (rc < 0) { -// TODO in_use check ? - segment_warning(rc, entry->segment_name); - goto out_panic; - } - if (start != entry->start || end != entry->end) { - pr_err("The address range of DCSS %s changed " - "while the system was suspended\n", - entry->segment_name); - goto out_panic; - } - } - } - return 0; -out_panic: - panic("fatal dcssblk resume error\n"); -} - -static int dcssblk_thaw(struct device *dev) -{ - return 0; -} - -static const struct dev_pm_ops dcssblk_pm_ops = { - .freeze = dcssblk_freeze, - .thaw = dcssblk_thaw, - .restore = dcssblk_restore, -}; - -static struct platform_driver dcssblk_pdrv = { - .driver = { - .name = "dcssblk", - .pm = &dcssblk_pm_ops, - }, -}; - -static struct platform_device *dcssblk_pdev; - - -/* * The init/exit functions. */ static void __exit dcssblk_exit(void) { - platform_device_unregister(dcssblk_pdev); - platform_driver_unregister(&dcssblk_pdrv); root_device_unregister(dcssblk_root_dev); unregister_blkdev(dcssblk_major, DCSSBLK_NAME); } @@ -1081,22 +997,9 @@ dcssblk_init(void) { int rc; - rc = platform_driver_register(&dcssblk_pdrv); - if (rc) - return rc; - - dcssblk_pdev = platform_device_register_simple("dcssblk", -1, NULL, - 0); - if (IS_ERR(dcssblk_pdev)) { - rc = PTR_ERR(dcssblk_pdev); - goto out_pdrv; - } - dcssblk_root_dev = root_device_register("dcssblk"); - if (IS_ERR(dcssblk_root_dev)) { - rc = PTR_ERR(dcssblk_root_dev); - goto out_pdev; - } + if (IS_ERR(dcssblk_root_dev)) + return PTR_ERR(dcssblk_root_dev); rc = device_create_file(dcssblk_root_dev, &dev_attr_add); if (rc) goto out_root; @@ -1114,10 +1017,7 @@ dcssblk_init(void) out_root: root_device_unregister(dcssblk_root_dev); -out_pdev: - platform_device_unregister(dcssblk_pdev); -out_pdrv: - platform_driver_unregister(&dcssblk_pdrv); + return rc; } diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index 91ef710edfd2..ce98fab4d43c 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c @@ -39,8 +39,6 @@ #include <linux/hdreg.h> /* HDIO_GETGEO */ #include <linux/device.h> #include <linux/bio.h> -#include <linux/suspend.h> -#include <linux/platform_device.h> #include <linux/gfp.h> #include <linux/uaccess.h> @@ -140,7 +138,7 @@ static long xpram_page_out (unsigned long page_addr, unsigned int xpage_index) /* * Check if xpram is available. */ -static int xpram_present(void) +static int __init xpram_present(void) { unsigned long mem_page; int rc; @@ -156,7 +154,7 @@ static int xpram_present(void) /* * Return index of the last available xpram page. */ -static unsigned long xpram_highest_page_index(void) +static unsigned long __init xpram_highest_page_index(void) { unsigned int page_index, add_bit; unsigned long mem_page; @@ -384,42 +382,6 @@ out: } /* - * Resume failed: Print error message and call panic. - */ -static void xpram_resume_error(const char *message) -{ - pr_err("Resuming the system failed: %s\n", message); - panic("xpram resume error\n"); -} - -/* - * Check if xpram setup changed between suspend and resume. - */ -static int xpram_restore(struct device *dev) -{ - if (!xpram_pages) - return 0; - if (xpram_present() != 0) - xpram_resume_error("xpram disappeared"); - if (xpram_pages != xpram_highest_page_index() + 1) - xpram_resume_error("Size of xpram changed"); - return 0; -} - -static const struct dev_pm_ops xpram_pm_ops = { - .restore = xpram_restore, -}; - -static struct platform_driver xpram_pdrv = { - .driver = { - .name = XPRAM_NAME, - .pm = &xpram_pm_ops, - }, -}; - -static struct platform_device *xpram_pdev; - -/* * Finally, the init/exit functions. */ static void __exit xpram_exit(void) @@ -430,8 +392,6 @@ static void __exit xpram_exit(void) blk_cleanup_disk(xpram_disks[i]); } unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME); - platform_device_unregister(xpram_pdev); - platform_driver_unregister(&xpram_pdrv); } static int __init xpram_init(void) @@ -449,24 +409,7 @@ static int __init xpram_init(void) rc = xpram_setup_sizes(xpram_pages); if (rc) return rc; - rc = platform_driver_register(&xpram_pdrv); - if (rc) - return rc; - xpram_pdev = platform_device_register_simple(XPRAM_NAME, -1, NULL, 0); - if (IS_ERR(xpram_pdev)) { - rc = PTR_ERR(xpram_pdev); - goto fail_platform_driver_unregister; - } - rc = xpram_setup_blkdev(); - if (rc) - goto fail_platform_device_unregister; - return 0; - -fail_platform_device_unregister: - platform_device_unregister(xpram_pdev); -fail_platform_driver_unregister: - platform_driver_unregister(&xpram_pdrv); - return rc; + return xpram_setup_blkdev(); } module_init(xpram_init); diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 02523f4e29f4..67c0009ca545 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -925,7 +925,7 @@ static void tty3215_close(struct tty_struct *tty, struct file * filp) /* * Returns the amount of free space in the output buffer. */ -static int tty3215_write_room(struct tty_struct *tty) +static unsigned int tty3215_write_room(struct tty_struct *tty) { struct raw3215_info *raw = tty->driver_data; @@ -981,7 +981,7 @@ static void tty3215_flush_chars(struct tty_struct *tty) /* * Returns the number of characters in the output buffer */ -static int tty3215_chars_in_buffer(struct tty_struct *tty) +static unsigned int tty3215_chars_in_buffer(struct tty_struct *tty) { struct raw3215_info *raw = tty->driver_data; diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c index 7bc616b253f1..9fa92e45e0ee 100644 --- a/drivers/s390/char/monreader.c +++ b/drivers/s390/char/monreader.c @@ -21,7 +21,6 @@ #include <linux/spinlock.h> #include <linux/interrupt.h> #include <linux/poll.h> -#include <linux/device.h> #include <linux/slab.h> #include <net/iucv/iucv.h> #include <linux/uaccess.h> @@ -79,8 +78,6 @@ static u8 user_data_sever[16] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; -static struct device *monreader_device; - /****************************************************************************** * helper functions * *****************************************************************************/ @@ -319,7 +316,6 @@ static int mon_open(struct inode *inode, struct file *filp) goto out_path; } filp->private_data = monpriv; - dev_set_drvdata(monreader_device, monpriv); return nonseekable_open(inode, filp); out_path: @@ -354,7 +350,6 @@ static int mon_close(struct inode *inode, struct file *filp) atomic_set(&monpriv->msglim_count, 0); monpriv->write_index = 0; monpriv->read_index = 0; - dev_set_drvdata(monreader_device, NULL); for (i = 0; i < MON_MSGLIM; i++) kfree(monpriv->msg_array[i]); @@ -456,94 +451,6 @@ static struct miscdevice mon_dev = { .minor = MISC_DYNAMIC_MINOR, }; - -/****************************************************************************** - * suspend / resume * - *****************************************************************************/ -static int monreader_freeze(struct device *dev) -{ - struct mon_private *monpriv = dev_get_drvdata(dev); - int rc; - - if (!monpriv) - return 0; - if (monpriv->path) { - rc = iucv_path_sever(monpriv->path, user_data_sever); - if (rc) - pr_warn("Disconnecting the z/VM *MONITOR system service failed with rc=%i\n", - rc); - iucv_path_free(monpriv->path); - } - atomic_set(&monpriv->iucv_severed, 0); - atomic_set(&monpriv->iucv_connected, 0); - atomic_set(&monpriv->read_ready, 0); - atomic_set(&monpriv->msglim_count, 0); - monpriv->write_index = 0; - monpriv->read_index = 0; - monpriv->path = NULL; - return 0; -} - -static int monreader_thaw(struct device *dev) -{ - struct mon_private *monpriv = dev_get_drvdata(dev); - int rc; - - if (!monpriv) - return 0; - rc = -ENOMEM; - monpriv->path = iucv_path_alloc(MON_MSGLIM, IUCV_IPRMDATA, GFP_KERNEL); - if (!monpriv->path) - goto out; - rc = iucv_path_connect(monpriv->path, &monreader_iucv_handler, - MON_SERVICE, NULL, user_data_connect, monpriv); - if (rc) { - pr_err("Connecting to the z/VM *MONITOR system service " - "failed with rc=%i\n", rc); - goto out_path; - } - wait_event(mon_conn_wait_queue, - atomic_read(&monpriv->iucv_connected) || - atomic_read(&monpriv->iucv_severed)); - if (atomic_read(&monpriv->iucv_severed)) - goto out_path; - return 0; -out_path: - rc = -EIO; - iucv_path_free(monpriv->path); - monpriv->path = NULL; -out: - atomic_set(&monpriv->iucv_severed, 1); - return rc; -} - -static int monreader_restore(struct device *dev) -{ - int rc; - - segment_unload(mon_dcss_name); - rc = segment_load(mon_dcss_name, SEGMENT_SHARED, - &mon_dcss_start, &mon_dcss_end); - if (rc < 0) { - segment_warning(rc, mon_dcss_name); - panic("fatal monreader resume error: no monitor dcss\n"); - } - return monreader_thaw(dev); -} - -static const struct dev_pm_ops monreader_pm_ops = { - .freeze = monreader_freeze, - .thaw = monreader_thaw, - .restore = monreader_restore, -}; - -static struct device_driver monreader_driver = { - .name = "monreader", - .bus = &iucv_bus, - .pm = &monreader_pm_ops, -}; - - /****************************************************************************** * module init/exit * *****************************************************************************/ @@ -567,36 +474,16 @@ static int __init mon_init(void) return rc; } - rc = driver_register(&monreader_driver); - if (rc) - goto out_iucv; - monreader_device = kzalloc(sizeof(struct device), GFP_KERNEL); - if (!monreader_device) { - rc = -ENOMEM; - goto out_driver; - } - - dev_set_name(monreader_device, "monreader-dev"); - monreader_device->bus = &iucv_bus; - monreader_device->parent = iucv_root; - monreader_device->driver = &monreader_driver; - monreader_device->release = (void (*)(struct device *))kfree; - rc = device_register(monreader_device); - if (rc) { - put_device(monreader_device); - goto out_driver; - } - rc = segment_type(mon_dcss_name); if (rc < 0) { segment_warning(rc, mon_dcss_name); - goto out_device; + goto out_iucv; } if (rc != SEG_TYPE_SC) { pr_err("The specified *MONITOR DCSS %s does not have the " "required type SC\n", mon_dcss_name); rc = -EINVAL; - goto out_device; + goto out_iucv; } rc = segment_load(mon_dcss_name, SEGMENT_SHARED, @@ -604,7 +491,7 @@ static int __init mon_init(void) if (rc < 0) { segment_warning(rc, mon_dcss_name); rc = -EINVAL; - goto out_device; + goto out_iucv; } dcss_mkname(mon_dcss_name, &user_data_connect[8]); @@ -619,10 +506,6 @@ static int __init mon_init(void) out: segment_unload(mon_dcss_name); -out_device: - device_unregister(monreader_device); -out_driver: - driver_unregister(&monreader_driver); out_iucv: iucv_unregister(&monreader_iucv_handler, 1); return rc; @@ -632,8 +515,6 @@ static void __exit mon_exit(void) { segment_unload(mon_dcss_name); misc_deregister(&mon_dev); - device_unregister(monreader_device); - driver_unregister(&monreader_driver); iucv_unregister(&monreader_iucv_handler, 1); return; } diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c index fdc0c0b7a6f5..9cd1ea92d619 100644 --- a/drivers/s390/char/monwriter.c +++ b/drivers/s390/char/monwriter.c @@ -20,7 +20,6 @@ #include <linux/ctype.h> #include <linux/poll.h> #include <linux/mutex.h> -#include <linux/platform_device.h> #include <linux/slab.h> #include <linux/uaccess.h> #include <asm/ebcdic.h> @@ -40,10 +39,7 @@ struct mon_buf { char *data; }; -static LIST_HEAD(mon_priv_list); - struct mon_private { - struct list_head priv_list; struct list_head list; struct monwrite_hdr hdr; size_t hdr_to_read; @@ -199,7 +195,6 @@ static int monwrite_open(struct inode *inode, struct file *filp) monpriv->hdr_to_read = sizeof(monpriv->hdr); mutex_init(&monpriv->thread_mutex); filp->private_data = monpriv; - list_add_tail(&monpriv->priv_list, &mon_priv_list); return nonseekable_open(inode, filp); } @@ -217,7 +212,6 @@ static int monwrite_close(struct inode *inode, struct file *filp) kfree(entry->data); kfree(entry); } - list_del(&monpriv->priv_list); kfree(monpriv); return 0; } @@ -294,105 +288,23 @@ static struct miscdevice mon_dev = { }; /* - * suspend/resume - */ - -static int monwriter_freeze(struct device *dev) -{ - struct mon_private *monpriv; - struct mon_buf *monbuf; - - list_for_each_entry(monpriv, &mon_priv_list, priv_list) { - list_for_each_entry(monbuf, &monpriv->list, list) { - if (monbuf->hdr.mon_function != MONWRITE_GEN_EVENT) - monwrite_diag(&monbuf->hdr, monbuf->data, - APPLDATA_STOP_REC); - } - } - return 0; -} - -static int monwriter_restore(struct device *dev) -{ - struct mon_private *monpriv; - struct mon_buf *monbuf; - - list_for_each_entry(monpriv, &mon_priv_list, priv_list) { - list_for_each_entry(monbuf, &monpriv->list, list) { - if (monbuf->hdr.mon_function == MONWRITE_START_INTERVAL) - monwrite_diag(&monbuf->hdr, monbuf->data, - APPLDATA_START_INTERVAL_REC); - if (monbuf->hdr.mon_function == MONWRITE_START_CONFIG) - monwrite_diag(&monbuf->hdr, monbuf->data, - APPLDATA_START_CONFIG_REC); - } - } - return 0; -} - -static int monwriter_thaw(struct device *dev) -{ - return monwriter_restore(dev); -} - -static const struct dev_pm_ops monwriter_pm_ops = { - .freeze = monwriter_freeze, - .thaw = monwriter_thaw, - .restore = monwriter_restore, -}; - -static struct platform_driver monwriter_pdrv = { - .driver = { - .name = "monwriter", - .pm = &monwriter_pm_ops, - }, -}; - -static struct platform_device *monwriter_pdev; - -/* * module init/exit */ static int __init mon_init(void) { - int rc; - if (!MACHINE_IS_VM) return -ENODEV; - - rc = platform_driver_register(&monwriter_pdrv); - if (rc) - return rc; - - monwriter_pdev = platform_device_register_simple("monwriter", -1, NULL, - 0); - if (IS_ERR(monwriter_pdev)) { - rc = PTR_ERR(monwriter_pdev); - goto out_driver; - } - /* * misc_register() has to be the last action in module_init(), because * file operations will be available right after this. */ - rc = misc_register(&mon_dev); - if (rc) - goto out_device; - return 0; - -out_device: - platform_device_unregister(monwriter_pdev); -out_driver: - platform_driver_unregister(&monwriter_pdrv); - return rc; + return misc_register(&mon_dev); } static void __exit mon_exit(void) { misc_deregister(&mon_dev); - platform_device_unregister(monwriter_pdev); - platform_driver_unregister(&monwriter_pdrv); } module_init(mon_init); diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index 6627820a5eb9..792b4bfa6d9a 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -18,8 +18,6 @@ #include <linux/reboot.h> #include <linux/jiffies.h> #include <linux/init.h> -#include <linux/suspend.h> -#include <linux/completion.h> #include <linux/platform_device.h> #include <asm/types.h> #include <asm/irq.h> @@ -49,9 +47,6 @@ static struct sclp_req sclp_init_req; static void *sclp_read_sccb; static struct init_sccb *sclp_init_sccb; -/* Suspend request */ -static DECLARE_COMPLETION(sclp_request_queue_flushed); - /* Number of console pages to allocate, used by sclp_con.c and sclp_vt220.c */ int sclp_console_pages = SCLP_CONSOLE_PAGES; /* Flag to indicate if buffer pages are dropped on buffer full condition */ @@ -59,11 +54,6 @@ int sclp_console_drop = 1; /* Number of times the console dropped buffer pages */ unsigned long sclp_console_full; -static void sclp_suspend_req_cb(struct sclp_req *req, void *data) -{ - complete(&sclp_request_queue_flushed); -} - static int __init sclp_setup_console_pages(char *str) { int pages, rc; @@ -88,8 +78,6 @@ static int __init sclp_setup_console_drop(char *str) __setup("sclp_con_drop=", sclp_setup_console_drop); -static struct sclp_req sclp_suspend_req; - /* Timer for request retries. */ static struct timer_list sclp_request_timer; @@ -123,12 +111,6 @@ static volatile enum sclp_mask_state_t { sclp_mask_state_initializing } sclp_mask_state = sclp_mask_state_idle; -/* Internal state: is the driver suspended? */ -static enum sclp_suspend_state_t { - sclp_suspend_state_running, - sclp_suspend_state_suspended, -} sclp_suspend_state = sclp_suspend_state_running; - /* Maximum retry counts */ #define SCLP_INIT_RETRY 3 #define SCLP_MASK_RETRY 3 @@ -314,8 +296,6 @@ sclp_process_queue(void) del_timer(&sclp_request_timer); while (!list_empty(&sclp_req_queue)) { req = list_entry(sclp_req_queue.next, struct sclp_req, list); - if (!req->sccb) - goto do_post; rc = __sclp_start_request(req); if (rc == 0) break; @@ -327,7 +307,6 @@ sclp_process_queue(void) sclp_request_timeout_normal); break; } -do_post: /* Post-processing for aborted request */ list_del(&req->list); if (req->callback) { @@ -341,10 +320,8 @@ do_post: static int __sclp_can_add_request(struct sclp_req *req) { - if (req == &sclp_suspend_req || req == &sclp_init_req) + if (req == &sclp_init_req) return 1; - if (sclp_suspend_state != sclp_suspend_state_running) - return 0; if (sclp_init_state != sclp_init_state_initialized) return 0; if (sclp_activation_state != sclp_activation_state_active) @@ -378,16 +355,10 @@ sclp_add_request(struct sclp_req *req) /* Start if request is first in list */ if (sclp_running_state == sclp_running_state_idle && req->list.prev == &sclp_req_queue) { - if (!req->sccb) { - list_del(&req->list); - rc = -ENODATA; - goto out; - } rc = __sclp_start_request(req); if (rc) list_del(&req->list); } -out: spin_unlock_irqrestore(&sclp_lock, flags); return rc; } @@ -693,7 +664,6 @@ sclp_register(struct sclp_register *reg) /* Trigger initial state change callback */ reg->sclp_receive_mask = 0; reg->sclp_send_mask = 0; - reg->pm_event_posted = 0; list_add(®->list, &sclp_reg_list); spin_unlock_irqrestore(&sclp_lock, flags); rc = sclp_init_mask(1); @@ -1011,112 +981,6 @@ static struct notifier_block sclp_reboot_notifier = { .notifier_call = sclp_reboot_event }; -/* - * Suspend/resume SCLP notifier implementation - */ - -static void sclp_pm_event(enum sclp_pm_event sclp_pm_event, int rollback) -{ - struct sclp_register *reg; - unsigned long flags; - - if (!rollback) { - spin_lock_irqsave(&sclp_lock, flags); - list_for_each_entry(reg, &sclp_reg_list, list) - reg->pm_event_posted = 0; - spin_unlock_irqrestore(&sclp_lock, flags); - } - do { - spin_lock_irqsave(&sclp_lock, flags); - list_for_each_entry(reg, &sclp_reg_list, list) { - if (rollback && reg->pm_event_posted) - goto found; - if (!rollback && !reg->pm_event_posted) - goto found; - } - spin_unlock_irqrestore(&sclp_lock, flags); - return; -found: - spin_unlock_irqrestore(&sclp_lock, flags); - if (reg->pm_event_fn) - reg->pm_event_fn(reg, sclp_pm_event); - reg->pm_event_posted = rollback ? 0 : 1; - } while (1); -} - -/* - * Susend/resume callbacks for platform device - */ - -static int sclp_freeze(struct device *dev) -{ - unsigned long flags; - int rc; - - sclp_pm_event(SCLP_PM_EVENT_FREEZE, 0); - - spin_lock_irqsave(&sclp_lock, flags); - sclp_suspend_state = sclp_suspend_state_suspended; - spin_unlock_irqrestore(&sclp_lock, flags); - - /* Init supend data */ - memset(&sclp_suspend_req, 0, sizeof(sclp_suspend_req)); - sclp_suspend_req.callback = sclp_suspend_req_cb; - sclp_suspend_req.status = SCLP_REQ_FILLED; - init_completion(&sclp_request_queue_flushed); - - rc = sclp_add_request(&sclp_suspend_req); - if (rc == 0) - wait_for_completion(&sclp_request_queue_flushed); - else if (rc != -ENODATA) - goto fail_thaw; - - rc = sclp_deactivate(); - if (rc) - goto fail_thaw; - return 0; - -fail_thaw: - spin_lock_irqsave(&sclp_lock, flags); - sclp_suspend_state = sclp_suspend_state_running; - spin_unlock_irqrestore(&sclp_lock, flags); - sclp_pm_event(SCLP_PM_EVENT_THAW, 1); - return rc; -} - -static int sclp_undo_suspend(enum sclp_pm_event event) -{ - unsigned long flags; - int rc; - - rc = sclp_reactivate(); - if (rc) - return rc; - - spin_lock_irqsave(&sclp_lock, flags); - sclp_suspend_state = sclp_suspend_state_running; - spin_unlock_irqrestore(&sclp_lock, flags); - - sclp_pm_event(event, 0); - return 0; -} - -static int sclp_thaw(struct device *dev) -{ - return sclp_undo_suspend(SCLP_PM_EVENT_THAW); -} - -static int sclp_restore(struct device *dev) -{ - return sclp_undo_suspend(SCLP_PM_EVENT_RESTORE); -} - -static const struct dev_pm_ops sclp_pm_ops = { - .freeze = sclp_freeze, - .thaw = sclp_thaw, - .restore = sclp_restore, -}; - static ssize_t con_pages_show(struct device_driver *dev, char *buf) { return sprintf(buf, "%i\n", sclp_console_pages); @@ -1155,13 +1019,10 @@ static const struct attribute_group *sclp_drv_attr_groups[] = { static struct platform_driver sclp_pdrv = { .driver = { .name = "sclp", - .pm = &sclp_pm_ops, .groups = sclp_drv_attr_groups, }, }; -static struct platform_device *sclp_pdev; - /* Initialize SCLP driver. Return zero if driver is operational, non-zero * otherwise. */ static int @@ -1215,23 +1076,6 @@ fail_unlock: return rc; } -/* - * SCLP panic notifier: If we are suspended, we thaw SCLP in order to be able - * to print the panic message. - */ -static int sclp_panic_notify(struct notifier_block *self, - unsigned long event, void *data) -{ - if (sclp_suspend_state == sclp_suspend_state_suspended) - sclp_undo_suspend(SCLP_PM_EVENT_THAW); - return NOTIFY_OK; -} - -static struct notifier_block sclp_on_panic_nb = { - .notifier_call = sclp_panic_notify, - .priority = SCLP_PANIC_PRIO, -}; - static __init int sclp_initcall(void) { int rc; @@ -1240,23 +1084,7 @@ static __init int sclp_initcall(void) if (rc) return rc; - sclp_pdev = platform_device_register_simple("sclp", -1, NULL, 0); - rc = PTR_ERR_OR_ZERO(sclp_pdev); - if (rc) - goto fail_platform_driver_unregister; - - rc = atomic_notifier_chain_register(&panic_notifier_list, - &sclp_on_panic_nb); - if (rc) - goto fail_platform_device_unregister; - return sclp_init(); - -fail_platform_device_unregister: - platform_device_unregister(sclp_pdev); -fail_platform_driver_unregister: - platform_driver_unregister(&sclp_pdrv); - return rc; } arch_initcall(sclp_initcall); diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index 6de919944a39..8dd8ad83b78b 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h @@ -81,15 +81,6 @@ typedef unsigned int sclp_cmdw_t; #define GDS_KEY_SELFDEFTEXTMSG 0x31 -enum sclp_pm_event { - SCLP_PM_EVENT_FREEZE, - SCLP_PM_EVENT_THAW, - SCLP_PM_EVENT_RESTORE, -}; - -#define SCLP_PANIC_PRIO 1 -#define SCLP_PANIC_PRIO_CLIENT 0 - typedef u64 sccb_mask_t; struct sccb_header { @@ -293,10 +284,6 @@ struct sclp_register { void (*state_change_fn)(struct sclp_register *); /* called for events in cp_receive_mask/sclp_receive_mask */ void (*receiver_fn)(struct evbuf_header *); - /* called for power management events */ - void (*pm_event_fn)(struct sclp_register *, enum sclp_pm_event); - /* pm event posted flag */ - int pm_event_posted; }; /* externals from sclp.c */ diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index d41bc144c183..ab0518cfdcfe 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c @@ -20,7 +20,6 @@ #include <linux/mmzone.h> #include <linux/memory.h> #include <linux/module.h> -#include <linux/platform_device.h> #include <asm/ctl_reg.h> #include <asm/chpid.h> #include <asm/setup.h> @@ -168,7 +167,6 @@ static DEFINE_MUTEX(sclp_mem_mutex); static LIST_HEAD(sclp_mem_list); static u8 sclp_max_storage_id; static DECLARE_BITMAP(sclp_storage_ids, 256); -static int sclp_mem_state_changed; struct memory_increment { struct list_head list; @@ -359,8 +357,6 @@ static int sclp_mem_notifier(struct notifier_block *nb, rc = -EINVAL; break; } - if (!rc) - sclp_mem_state_changed = 1; mutex_unlock(&sclp_mem_mutex); return rc ? NOTIFY_BAD : NOTIFY_OK; } @@ -456,28 +452,8 @@ static void __init insert_increment(u16 rn, int standby, int assigned) list_add(&new_incr->list, prev); } -static int sclp_mem_freeze(struct device *dev) -{ - if (!sclp_mem_state_changed) - return 0; - pr_err("Memory hotplug state changed, suspend refused.\n"); - return -EPERM; -} - -static const struct dev_pm_ops sclp_mem_pm_ops = { - .freeze = sclp_mem_freeze, -}; - -static struct platform_driver sclp_mem_pdrv = { - .driver = { - .name = "sclp_mem", - .pm = &sclp_mem_pm_ops, - }, -}; - static int __init sclp_detect_standby_memory(void) { - struct platform_device *sclp_pdev; struct read_storage_sccb *sccb; int i, id, assigned, rc; @@ -530,17 +506,7 @@ static int __init sclp_detect_standby_memory(void) rc = register_memory_notifier(&sclp_mem_nb); if (rc) goto out; - rc = platform_driver_register(&sclp_mem_pdrv); - if (rc) - goto out; - sclp_pdev = platform_device_register_simple("sclp_mem", -1, NULL, 0); - rc = PTR_ERR_OR_ZERO(sclp_pdev); - if (rc) - goto out_driver; sclp_add_standby_memory(); - goto out; -out_driver: - platform_driver_unregister(&sclp_mem_pdrv); out: free_page((unsigned long) sccb); return rc; diff --git a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c index cc01a7b8595d..de028868c6f4 100644 --- a/drivers/s390/char/sclp_con.c +++ b/drivers/s390/char/sclp_con.c @@ -36,8 +36,6 @@ static LIST_HEAD(sclp_con_outqueue); static struct sclp_buffer *sclp_conbuf; /* Timer for delayed output of console messages */ static struct timer_list sclp_con_timer; -/* Suspend mode flag */ -static int sclp_con_suspended; /* Flag that output queue is currently running */ static int sclp_con_queue_running; @@ -64,7 +62,7 @@ sclp_conbuf_callback(struct sclp_buffer *buffer, int rc) if (!list_empty(&sclp_con_outqueue)) buffer = list_first_entry(&sclp_con_outqueue, struct sclp_buffer, list); - if (!buffer || sclp_con_suspended) { + if (!buffer) { sclp_con_queue_running = 0; spin_unlock_irqrestore(&sclp_con_lock, flags); break; @@ -86,7 +84,7 @@ static void sclp_conbuf_emit(void) if (sclp_conbuf) list_add_tail(&sclp_conbuf->list, &sclp_con_outqueue); sclp_conbuf = NULL; - if (sclp_con_queue_running || sclp_con_suspended) + if (sclp_con_queue_running) goto out_unlock; if (list_empty(&sclp_con_outqueue)) goto out_unlock; @@ -180,8 +178,6 @@ sclp_console_write(struct console *console, const char *message, if (list_empty(&sclp_con_pages)) sclp_console_full++; while (list_empty(&sclp_con_pages)) { - if (sclp_con_suspended) - goto out; if (sclp_console_drop_buffer()) break; spin_unlock_irqrestore(&sclp_con_lock, flags); @@ -214,7 +210,6 @@ sclp_console_write(struct console *console, const char *message, !timer_pending(&sclp_con_timer)) { mod_timer(&sclp_con_timer, jiffies + HZ / 10); } -out: spin_unlock_irqrestore(&sclp_con_lock, flags); } @@ -235,32 +230,6 @@ sclp_console_flush(void) sclp_console_sync_queue(); } -/* - * Resume console: If there are cached messages, emit them. - */ -static void sclp_console_resume(void) -{ - unsigned long flags; - - spin_lock_irqsave(&sclp_con_lock, flags); - sclp_con_suspended = 0; - spin_unlock_irqrestore(&sclp_con_lock, flags); - sclp_conbuf_emit(); -} - -/* - * Suspend console: Set suspend flag and flush console - */ -static void sclp_console_suspend(void) -{ - unsigned long flags; - - spin_lock_irqsave(&sclp_con_lock, flags); - sclp_con_suspended = 1; - spin_unlock_irqrestore(&sclp_con_lock, flags); - sclp_console_flush(); -} - static int sclp_console_notify(struct notifier_block *self, unsigned long event, void *data) { @@ -270,7 +239,7 @@ static int sclp_console_notify(struct notifier_block *self, static struct notifier_block on_panic_nb = { .notifier_call = sclp_console_notify, - .priority = SCLP_PANIC_PRIO_CLIENT, + .priority = 1, }; static struct notifier_block on_reboot_nb = { @@ -292,22 +261,6 @@ static struct console sclp_console = }; /* - * This function is called for SCLP suspend and resume events. - */ -void sclp_console_pm_event(enum sclp_pm_event sclp_pm_event) -{ - switch (sclp_pm_event) { - case SCLP_PM_EVENT_FREEZE: - sclp_console_suspend(); - break; - case SCLP_PM_EVENT_RESTORE: - case SCLP_PM_EVENT_THAW: - sclp_console_resume(); - break; - } -} - -/* * called by console_init() in drivers/char/tty_io.c at boot-time. */ static int __init diff --git a/drivers/s390/char/sclp_ftp.c b/drivers/s390/char/sclp_ftp.c index dfdd6c8fd17e..1e9de99dcd02 100644 --- a/drivers/s390/char/sclp_ftp.c +++ b/drivers/s390/char/sclp_ftp.c @@ -231,7 +231,6 @@ static struct sclp_register sclp_ftp_event = { .receive_mask = EVTYP_DIAG_TEST_MASK, /* want rx events */ .receiver_fn = sclp_ftp_rxcb, /* async callback (rx) */ .state_change_fn = NULL, - .pm_event_fn = NULL, }; /** diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c index 76956c2131cd..ade721467804 100644 --- a/drivers/s390/char/sclp_quiesce.c +++ b/drivers/s390/char/sclp_quiesce.c @@ -18,10 +18,6 @@ #include "sclp.h" -static void (*old_machine_restart)(char *); -static void (*old_machine_halt)(void); -static void (*old_machine_power_off)(void); - /* Shutdown handler. Signal completion of shutdown by loading special PSW. */ static void do_machine_quiesce(void) { @@ -37,42 +33,15 @@ static void do_machine_quiesce(void) /* Handler for quiesce event. Start shutdown procedure. */ static void sclp_quiesce_handler(struct evbuf_header *evbuf) { - if (_machine_restart != (void *) do_machine_quiesce) { - old_machine_restart = _machine_restart; - old_machine_halt = _machine_halt; - old_machine_power_off = _machine_power_off; - _machine_restart = (void *) do_machine_quiesce; - _machine_halt = do_machine_quiesce; - _machine_power_off = do_machine_quiesce; - } + _machine_restart = (void *) do_machine_quiesce; + _machine_halt = do_machine_quiesce; + _machine_power_off = do_machine_quiesce; ctrl_alt_del(); } -/* Undo machine restart/halt/power_off modification on resume */ -static void sclp_quiesce_pm_event(struct sclp_register *reg, - enum sclp_pm_event sclp_pm_event) -{ - switch (sclp_pm_event) { - case SCLP_PM_EVENT_RESTORE: - if (old_machine_restart) { - _machine_restart = old_machine_restart; - _machine_halt = old_machine_halt; - _machine_power_off = old_machine_power_off; - old_machine_restart = NULL; - old_machine_halt = NULL; - old_machine_power_off = NULL; - } - break; - case SCLP_PM_EVENT_FREEZE: - case SCLP_PM_EVENT_THAW: - break; - } -} - static struct sclp_register sclp_quiesce_event = { .receive_mask = EVTYP_SIGQUIESCE_MASK, .receiver_fn = sclp_quiesce_handler, - .pm_event_fn = sclp_quiesce_pm_event }; /* Initialize quiesce driver. */ diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c index d6c84e354df5..1690326553b1 100644 --- a/drivers/s390/char/sclp_rw.c +++ b/drivers/s390/char/sclp_rw.c @@ -26,16 +26,9 @@ */ #define MAX_SCCB_ROOM (PAGE_SIZE - sizeof(struct sclp_buffer)) -static void sclp_rw_pm_event(struct sclp_register *reg, - enum sclp_pm_event sclp_pm_event) -{ - sclp_console_pm_event(sclp_pm_event); -} - /* Event type structure for write message and write priority message */ static struct sclp_register sclp_rw_event = { .send_mask = EVTYP_MSG_MASK, - .pm_event_fn = sclp_rw_pm_event, }; /* @@ -325,10 +318,10 @@ sclp_buffer_space(struct sclp_buffer *buffer) /* * Return number of characters in buffer */ -int +unsigned int sclp_chars_in_buffer(struct sclp_buffer *buffer) { - int count; + unsigned int count; count = buffer->char_sum; if (buffer->current_line != NULL) diff --git a/drivers/s390/char/sclp_rw.h b/drivers/s390/char/sclp_rw.h index 93d706e4935c..9b779ee4f979 100644 --- a/drivers/s390/char/sclp_rw.h +++ b/drivers/s390/char/sclp_rw.h @@ -86,12 +86,6 @@ void *sclp_unmake_buffer(struct sclp_buffer *); int sclp_buffer_space(struct sclp_buffer *); int sclp_write(struct sclp_buffer *buffer, const unsigned char *, int); int sclp_emit_buffer(struct sclp_buffer *,void (*)(struct sclp_buffer *,int)); -int sclp_chars_in_buffer(struct sclp_buffer *); - -#ifdef CONFIG_SCLP_CONSOLE -void sclp_console_pm_event(enum sclp_pm_event sclp_pm_event); -#else -static inline void sclp_console_pm_event(enum sclp_pm_event sclp_pm_event) { } -#endif +unsigned int sclp_chars_in_buffer(struct sclp_buffer *); #endif /* __SCLP_RW_H__ */ diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index 4456ceb23bd2..6be9de8ed37d 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c @@ -86,12 +86,12 @@ sclp_tty_close(struct tty_struct *tty, struct file *filp) * a string of newlines. Every newline creates a new message which * needs 82 bytes. */ -static int +static unsigned int sclp_tty_write_room (struct tty_struct *tty) { unsigned long flags; struct list_head *l; - int count; + unsigned int count; spin_lock_irqsave(&sclp_tty_lock, flags); count = 0; @@ -280,20 +280,17 @@ sclp_tty_flush_chars(struct tty_struct *tty) * characters in the write buffer (will not be written as long as there is a * final line feed missing). */ -static int +static unsigned int sclp_tty_chars_in_buffer(struct tty_struct *tty) { unsigned long flags; - struct list_head *l; struct sclp_buffer *t; - int count; + unsigned int count = 0; spin_lock_irqsave(&sclp_tty_lock, flags); - count = 0; if (sclp_ttybuf != NULL) count = sclp_chars_in_buffer(sclp_ttybuf); - list_for_each(l, &sclp_tty_outqueue) { - t = list_entry(l, struct sclp_buffer, list); + list_for_each_entry(t, &sclp_tty_outqueue, list) { count += sclp_chars_in_buffer(t); } spin_unlock_irqrestore(&sclp_tty_lock, flags); diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index 5b8a7b090a97..da2496306c04 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c @@ -36,8 +36,8 @@ #define SCLP_VT220_MINOR 65 #define SCLP_VT220_DRIVER_NAME "sclp_vt220" #define SCLP_VT220_DEVICE_NAME "ttysclp" -#define SCLP_VT220_CONSOLE_NAME "ttyS" -#define SCLP_VT220_CONSOLE_INDEX 1 /* console=ttyS1 */ +#define SCLP_VT220_CONSOLE_NAME "ttysclp" +#define SCLP_VT220_CONSOLE_INDEX 0 /* console=ttysclp0 */ /* Representation of a single write request */ struct sclp_vt220_request { @@ -70,9 +70,6 @@ static LIST_HEAD(sclp_vt220_empty); /* List of pending requests */ static LIST_HEAD(sclp_vt220_outqueue); -/* Suspend mode flag */ -static int sclp_vt220_suspended; - /* Flag that output queue is currently running */ static int sclp_vt220_queue_running; @@ -96,15 +93,12 @@ static int __initdata sclp_vt220_init_count; static int sclp_vt220_flush_later; static void sclp_vt220_receiver_fn(struct evbuf_header *evbuf); -static void sclp_vt220_pm_event_fn(struct sclp_register *reg, - enum sclp_pm_event sclp_pm_event); static int __sclp_vt220_emit(struct sclp_vt220_request *request); static void sclp_vt220_emit_current(void); /* Registration structure for SCLP output event buffers */ static struct sclp_register sclp_vt220_register = { .send_mask = EVTYP_VT220MSG_MASK, - .pm_event_fn = sclp_vt220_pm_event_fn, }; /* Registration structure for SCLP input event buffers */ @@ -136,7 +130,7 @@ sclp_vt220_process_queue(struct sclp_vt220_request *request) if (!list_empty(&sclp_vt220_outqueue)) request = list_entry(sclp_vt220_outqueue.next, struct sclp_vt220_request, list); - if (!request || sclp_vt220_suspended) { + if (!request) { sclp_vt220_queue_running = 0; spin_unlock_irqrestore(&sclp_vt220_lock, flags); break; @@ -242,7 +236,7 @@ sclp_vt220_emit_current(void) } sclp_vt220_flush_later = 0; } - if (sclp_vt220_queue_running || sclp_vt220_suspended) + if (sclp_vt220_queue_running) goto out_unlock; if (list_empty(&sclp_vt220_outqueue)) goto out_unlock; @@ -421,7 +415,7 @@ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule, if (list_empty(&sclp_vt220_empty)) sclp_console_full++; while (list_empty(&sclp_vt220_empty)) { - if (may_fail || sclp_vt220_suspended) + if (may_fail) goto out; if (sclp_vt220_drop_buffer()) break; @@ -610,12 +604,12 @@ sclp_vt220_flush_chars(struct tty_struct *tty) * to change as output buffers get emptied, or if the output flow * control is acted. */ -static int +static unsigned int sclp_vt220_write_room(struct tty_struct *tty) { unsigned long flags; struct list_head *l; - int count; + unsigned int count; spin_lock_irqsave(&sclp_vt220_lock, flags); count = 0; @@ -630,16 +624,15 @@ sclp_vt220_write_room(struct tty_struct *tty) /* * Return number of buffered chars. */ -static int +static unsigned int sclp_vt220_chars_in_buffer(struct tty_struct *tty) { unsigned long flags; struct list_head *l; struct sclp_vt220_request *r; - int count; + unsigned int count = 0; spin_lock_irqsave(&sclp_vt220_lock, flags); - count = 0; if (sclp_vt220_current_request != NULL) count = sclp_vt220_chars_stored(sclp_vt220_current_request); list_for_each(l, &sclp_vt220_outqueue) { @@ -792,46 +785,6 @@ static void __sclp_vt220_flush_buffer(void) spin_unlock_irqrestore(&sclp_vt220_lock, flags); } -/* - * Resume console: If there are cached messages, emit them. - */ -static void sclp_vt220_resume(void) -{ - unsigned long flags; - - spin_lock_irqsave(&sclp_vt220_lock, flags); - sclp_vt220_suspended = 0; - spin_unlock_irqrestore(&sclp_vt220_lock, flags); - sclp_vt220_emit_current(); -} - -/* - * Suspend console: Set suspend flag and flush console - */ -static void sclp_vt220_suspend(void) -{ - unsigned long flags; - - spin_lock_irqsave(&sclp_vt220_lock, flags); - sclp_vt220_suspended = 1; - spin_unlock_irqrestore(&sclp_vt220_lock, flags); - __sclp_vt220_flush_buffer(); -} - -static void sclp_vt220_pm_event_fn(struct sclp_register *reg, - enum sclp_pm_event sclp_pm_event) -{ - switch (sclp_pm_event) { - case SCLP_PM_EVENT_FREEZE: - sclp_vt220_suspend(); - break; - case SCLP_PM_EVENT_RESTORE: - case SCLP_PM_EVENT_THAW: - sclp_vt220_resume(); - break; - } -} - #ifdef CONFIG_SCLP_VT220_CONSOLE static void diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index 307a80f85c07..adc33846bf8e 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c @@ -1071,7 +1071,7 @@ static void tty3270_cleanup(struct tty_struct *tty) /* * We always have room. */ -static int +static unsigned int tty3270_write_room(struct tty_struct *tty) { return INT_MAX; @@ -1640,7 +1640,7 @@ tty3270_do_write(struct tty3270 *tp, struct tty_struct *tty, int i_msg, i; spin_lock_bh(&tp->view.lock); - for (i_msg = 0; !tty->stopped && i_msg < count; i_msg++) { + for (i_msg = 0; !tty->flow.stopped && i_msg < count; i_msg++) { if (tp->esc_state != 0) { /* Continue escape sequence. */ tty3270_escape_sequence(tp, buf[i_msg]); @@ -1757,22 +1757,6 @@ tty3270_flush_chars(struct tty_struct *tty) } /* - * Returns the number of characters in the output buffer. This is - * used in tty_wait_until_sent to wait until all characters have - * appeared on the screen. - */ -static int -tty3270_chars_in_buffer(struct tty_struct *tty) -{ - return 0; -} - -static void -tty3270_flush_buffer(struct tty_struct *tty) -{ -} - -/* * Check for visible/invisible input switches */ static void @@ -1892,8 +1876,6 @@ static const struct tty_operations tty3270_ops = { .put_char = tty3270_put_char, .flush_chars = tty3270_flush_chars, .write_room = tty3270_write_room, - .chars_in_buffer = tty3270_chars_in_buffer, - .flush_buffer = tty3270_flush_buffer, .throttle = tty3270_throttle, .unthrottle = tty3270_unthrottle, .hangup = tty3270_hangup, diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index 58333cb4503f..ed970ecfafdf 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c @@ -679,34 +679,10 @@ static const struct attribute_group *vmlogrdr_attr_groups[] = { NULL, }; -static int vmlogrdr_pm_prepare(struct device *dev) -{ - int rc; - struct vmlogrdr_priv_t *priv = dev_get_drvdata(dev); - - rc = 0; - if (priv) { - spin_lock_bh(&priv->priv_lock); - if (priv->dev_in_use) - rc = -EBUSY; - spin_unlock_bh(&priv->priv_lock); - } - if (rc) - pr_err("vmlogrdr: device %s is busy. Refuse to suspend.\n", - dev_name(dev)); - return rc; -} - - -static const struct dev_pm_ops vmlogrdr_pm_ops = { - .prepare = vmlogrdr_pm_prepare, -}; - static struct class *vmlogrdr_class; static struct device_driver vmlogrdr_driver = { .name = "vmlogrdr", .bus = &iucv_bus, - .pm = &vmlogrdr_pm_ops, .groups = vmlogrdr_drv_attr_groups, }; diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c index cb466ed7eb5e..e56535c99888 100644 --- a/drivers/s390/cio/airq.c +++ b/drivers/s390/cio/airq.c @@ -93,7 +93,7 @@ static irqreturn_t do_airq_interrupt(int irq, void *dummy) struct hlist_head *head; set_cpu_flag(CIF_NOHZ_DELAY); - tpi_info = (struct tpi_info *) &get_irq_regs()->int_code; + tpi_info = &get_irq_regs()->tpi_info; trace_s390_cio_adapter_int(tpi_info); head = &airq_lists[tpi_info->isc]; rcu_read_lock(); diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 444385da5792..9748165e08e9 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -45,27 +45,6 @@ static void __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev) } } -/* - * Remove references from ccw devices to ccw group device and from - * ccw group device to ccw devices. - */ -static void __ccwgroup_remove_cdev_refs(struct ccwgroup_device *gdev) -{ - struct ccw_device *cdev; - int i; - - for (i = 0; i < gdev->count; i++) { - cdev = gdev->cdev[i]; - if (!cdev) - continue; - spin_lock_irq(cdev->ccwlock); - dev_set_drvdata(&cdev->dev, NULL); - spin_unlock_irq(cdev->ccwlock); - gdev->cdev[i] = NULL; - put_device(&cdev->dev); - } -} - /** * ccwgroup_set_online() - enable a ccwgroup device * @gdev: target ccwgroup device @@ -175,7 +154,6 @@ static void ccwgroup_ungroup(struct ccwgroup_device *gdev) if (device_is_registered(&gdev->dev)) { __ccwgroup_remove_symlinks(gdev); device_unregister(&gdev->dev); - __ccwgroup_remove_cdev_refs(gdev); } mutex_unlock(&gdev->reg_mutex); } @@ -228,7 +206,23 @@ static void ccwgroup_ungroup_workfn(struct work_struct *work) static void ccwgroup_release(struct device *dev) { - kfree(to_ccwgroupdev(dev)); + struct ccwgroup_device *gdev = to_ccwgroupdev(dev); + unsigned int i; + + for (i = 0; i < gdev->count; i++) { + struct ccw_device *cdev = gdev->cdev[i]; + unsigned long flags; + + if (cdev) { + spin_lock_irqsave(cdev->ccwlock, flags); + if (dev_get_drvdata(&cdev->dev) == gdev) + dev_set_drvdata(&cdev->dev, NULL); + spin_unlock_irqrestore(cdev->ccwlock, flags); + put_device(&cdev->dev); + } + } + + kfree(gdev); } static int __ccwgroup_create_symlinks(struct ccwgroup_device *gdev) @@ -396,15 +390,6 @@ int ccwgroup_create_dev(struct device *parent, struct ccwgroup_driver *gdrv, mutex_unlock(&gdev->reg_mutex); return 0; error: - for (i = 0; i < num_devices; i++) - if (gdev->cdev[i]) { - spin_lock_irq(gdev->cdev[i]->ccwlock); - if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) - dev_set_drvdata(&gdev->cdev[i]->dev, NULL); - spin_unlock_irq(gdev->cdev[i]->ccwlock); - put_device(&gdev->cdev[i]->dev); - gdev->cdev[i] = NULL; - } mutex_unlock(&gdev->reg_mutex); put_device(&gdev->dev); return rc; @@ -416,7 +401,7 @@ static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, { struct ccwgroup_device *gdev = to_ccwgroupdev(data); - if (action == BUS_NOTIFY_UNBIND_DRIVER) { + if (action == BUS_NOTIFY_UNBOUND_DRIVER) { get_device(&gdev->dev); schedule_work(&gdev->ungroup_work); } @@ -514,15 +499,6 @@ EXPORT_SYMBOL(ccwgroup_driver_register); */ void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver) { - struct device *dev; - - /* We don't want ccwgroup devices to live longer than their driver. */ - while ((dev = driver_find_next_device(&cdriver->driver, NULL))) { - struct ccwgroup_device *gdev = to_ccwgroupdev(dev); - - ccwgroup_ungroup(gdev); - put_device(dev); - } driver_unregister(&cdriver->driver); } EXPORT_SYMBOL(ccwgroup_driver_unregister); diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index e42113825415..1097e76982a5 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c @@ -255,6 +255,9 @@ static ssize_t chp_status_write(struct device *dev, if (!num_args) return count; + /* Wait until previous actions have settled. */ + css_wait_for_slow_path(); + if (!strncasecmp(cmd, "on", 2) || !strcmp(cmd, "1")) { mutex_lock(&cp->lock); error = s390_vary_chpid(cp->chpid, 1); diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index c22d9ee27ba1..297fb399363c 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -801,8 +801,6 @@ int chsc_chp_vary(struct chp_id chpid, int on) { struct channel_path *chp = chpid_to_chp(chpid); - /* Wait until previous actions have settled. */ - css_wait_for_slow_path(); /* * Redo PathVerification on the devices the chpid connects to */ diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 6d716db2a46a..923f5ca4f5e6 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -536,7 +536,7 @@ static irqreturn_t do_cio_interrupt(int irq, void *dummy) struct irb *irb; set_cpu_flag(CIF_NOHZ_DELAY); - tpi_info = (struct tpi_info *) &get_irq_regs()->int_code; + tpi_info = &get_irq_regs()->tpi_info; trace_s390_cio_interrupt(tpi_info); irb = this_cpu_ptr(&cio_irb); sch = (struct subchannel *)(unsigned long) tpi_info->intparm; diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h index dcdaba689b20..1cb9daf9c645 100644 --- a/drivers/s390/cio/cio.h +++ b/drivers/s390/cio/cio.h @@ -9,6 +9,7 @@ #include <asm/cio.h> #include <asm/fcx.h> #include <asm/schid.h> +#include <asm/tpi.h> #include "chsc.h" /* @@ -46,18 +47,6 @@ struct pmcw { /* ... in an operand exception. */ } __attribute__ ((packed)); -/* I/O-Interruption Code as stored by TEST PENDING INTERRUPTION (TPI). */ -struct tpi_info { - struct subchannel_id schid; - u32 intparm; - u32 adapter_IO:1; - u32 directed_irq:1; - u32 isc:3; - u32 :27; - u32 type:3; - u32 :12; -} __packed __aligned(4); - /* Target SCHIB configuration. */ struct schib_config { u64 mba; diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index b7b590646d58..5584aa46c94e 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c @@ -163,13 +163,14 @@ static inline u64 time_to_avg_nsec(u32 value, u32 count) */ static inline void cmf_activate(void *area, unsigned int onoff) { - register void * __gpr2 asm("2"); - register long __gpr1 asm("1"); - - __gpr2 = area; - __gpr1 = onoff; /* activate channel measurement */ - asm("schm" : : "d" (__gpr2), "d" (__gpr1) ); + asm volatile( + " lgr 1,%[r1]\n" + " lgr 2,%[mbo]\n" + " schm\n" + : + : [r1] "d" ((unsigned long)onoff), [mbo] "d" (area) + : "1", "2"); } static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc, diff --git a/drivers/s390/cio/ioasm.c b/drivers/s390/cio/ioasm.c index 4c5244d6052b..180913007824 100644 --- a/drivers/s390/cio/ioasm.c +++ b/drivers/s390/cio/ioasm.c @@ -16,18 +16,19 @@ static inline int __stsch(struct subchannel_id schid, struct schib *addr) { - register struct subchannel_id reg1 asm ("1") = schid; + unsigned long r1 = *(unsigned int *)&schid; int ccode = -EIO; asm volatile( - " stsch 0(%3)\n" - "0: ipm %0\n" - " srl %0,28\n" + " lgr 1,%[r1]\n" + " stsch %[addr]\n" + "0: ipm %[cc]\n" + " srl %[cc],28\n" "1:\n" EX_TABLE(0b, 1b) - : "+d" (ccode), "=m" (*addr) - : "d" (reg1), "a" (addr) - : "cc"); + : [cc] "+&d" (ccode), [addr] "=Q" (*addr) + : [r1] "d" (r1) + : "cc", "1"); return ccode; } @@ -44,18 +45,19 @@ EXPORT_SYMBOL(stsch); static inline int __msch(struct subchannel_id schid, struct schib *addr) { - register struct subchannel_id reg1 asm ("1") = schid; + unsigned long r1 = *(unsigned int *)&schid; int ccode = -EIO; asm volatile( - " msch 0(%2)\n" - "0: ipm %0\n" - " srl %0,28\n" + " lgr 1,%[r1]\n" + " msch %[addr]\n" + "0: ipm %[cc]\n" + " srl %[cc],28\n" "1:\n" EX_TABLE(0b, 1b) - : "+d" (ccode) - : "d" (reg1), "a" (addr), "m" (*addr) - : "cc"); + : [cc] "+&d" (ccode) + : [r1] "d" (r1), [addr] "Q" (*addr) + : "cc", "1"); return ccode; } @@ -71,16 +73,17 @@ int msch(struct subchannel_id schid, struct schib *addr) static inline int __tsch(struct subchannel_id schid, struct irb *addr) { - register struct subchannel_id reg1 asm ("1") = schid; + unsigned long r1 = *(unsigned int *)&schid; int ccode; asm volatile( - " tsch 0(%3)\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode), "=m" (*addr) - : "d" (reg1), "a" (addr) - : "cc"); + " lgr 1,%[r1]\n" + " tsch %[addr]\n" + " ipm %[cc]\n" + " srl %[cc],28" + : [cc] "=&d" (ccode), [addr] "=Q" (*addr) + : [r1] "d" (r1) + : "cc", "1"); return ccode; } @@ -96,18 +99,19 @@ int tsch(struct subchannel_id schid, struct irb *addr) static inline int __ssch(struct subchannel_id schid, union orb *addr) { - register struct subchannel_id reg1 asm("1") = schid; + unsigned long r1 = *(unsigned int *)&schid; int ccode = -EIO; asm volatile( - " ssch 0(%2)\n" - "0: ipm %0\n" - " srl %0,28\n" + " lgr 1,%[r1]\n" + " ssch %[addr]\n" + "0: ipm %[cc]\n" + " srl %[cc],28\n" "1:\n" EX_TABLE(0b, 1b) - : "+d" (ccode) - : "d" (reg1), "a" (addr), "m" (*addr) - : "cc", "memory"); + : [cc] "+&d" (ccode) + : [r1] "d" (r1), [addr] "Q" (*addr) + : "cc", "memory", "1"); return ccode; } @@ -124,16 +128,17 @@ EXPORT_SYMBOL(ssch); static inline int __csch(struct subchannel_id schid) { - register struct subchannel_id reg1 asm("1") = schid; + unsigned long r1 = *(unsigned int *)&schid; int ccode; asm volatile( + " lgr 1,%[r1]\n" " csch\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode) - : "d" (reg1) - : "cc"); + " ipm %[cc]\n" + " srl %[cc],28\n" + : [cc] "=&d" (ccode) + : [r1] "d" (r1) + : "cc", "1"); return ccode; } @@ -153,11 +158,11 @@ int tpi(struct tpi_info *addr) int ccode; asm volatile( - " tpi 0(%2)\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode), "=m" (*addr) - : "a" (addr) + " tpi %[addr]\n" + " ipm %[cc]\n" + " srl %[cc],28" + : [cc] "=&d" (ccode), [addr] "=Q" (*addr) + : : "cc"); trace_s390_cio_tpi(addr, ccode); @@ -170,13 +175,13 @@ int chsc(void *chsc_area) int cc = -EIO; asm volatile( - " .insn rre,0xb25f0000,%2,0\n" - "0: ipm %0\n" - " srl %0,28\n" + " .insn rre,0xb25f0000,%[chsc_area],0\n" + "0: ipm %[cc]\n" + " srl %[cc],28\n" "1:\n" EX_TABLE(0b, 1b) - : "+d" (cc), "=m" (*(addr_type *) chsc_area) - : "d" (chsc_area), "m" (*(addr_type *) chsc_area) + : [cc] "+&d" (cc), "+m" (*(addr_type *)chsc_area) + : [chsc_area] "d" (chsc_area) : "cc"); trace_s390_cio_chsc(chsc_area, cc); @@ -186,17 +191,17 @@ EXPORT_SYMBOL(chsc); static inline int __rsch(struct subchannel_id schid) { - register struct subchannel_id reg1 asm("1") = schid; + unsigned long r1 = *(unsigned int *)&schid; int ccode; asm volatile( + " lgr 1,%[r1]\n" " rsch\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode) - : "d" (reg1) - : "cc", "memory"); - + " ipm %[cc]\n" + " srl %[cc],28\n" + : [cc] "=&d" (ccode) + : [r1] "d" (r1) + : "cc", "memory", "1"); return ccode; } @@ -212,16 +217,17 @@ int rsch(struct subchannel_id schid) static inline int __hsch(struct subchannel_id schid) { - register struct subchannel_id reg1 asm("1") = schid; + unsigned long r1 = *(unsigned int *)&schid; int ccode; asm volatile( + " lgr 1,%[r1]\n" " hsch\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode) - : "d" (reg1) - : "cc"); + " ipm %[cc]\n" + " srl %[cc],28\n" + : [cc] "=&d" (ccode) + : [r1] "d" (r1) + : "cc", "1"); return ccode; } @@ -238,16 +244,17 @@ EXPORT_SYMBOL(hsch); static inline int __xsch(struct subchannel_id schid) { - register struct subchannel_id reg1 asm("1") = schid; + unsigned long r1 = *(unsigned int *)&schid; int ccode; asm volatile( + " lgr 1,%[r1]\n" " xsch\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode) - : "d" (reg1) - : "cc"); + " ipm %[cc]\n" + " srl %[cc],28\n" + : [cc] "=&d" (ccode) + : [r1] "d" (r1) + : "cc", "1"); return ccode; } @@ -266,11 +273,11 @@ static inline int __stcrw(struct crw *crw) int ccode; asm volatile( - " stcrw 0(%2)\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (ccode), "=m" (*crw) - : "a" (crw) + " stcrw %[crw]\n" + " ipm %[cc]\n" + " srl %[cc],28\n" + : [cc] "=&d" (ccode), [crw] "=Q" (*crw) + : : "cc"); return ccode; } diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 0e0044d70844..f69ffbb8edc9 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -88,15 +88,15 @@ enum qdio_irq_states { static inline int do_sqbs(u64 token, unsigned char state, int queue, int *start, int *count) { - register unsigned long _ccq asm ("0") = *count; - register unsigned long _token asm ("1") = token; unsigned long _queuestart = ((unsigned long)queue << 32) | *start; + unsigned long _ccq = *count; asm volatile( - " .insn rsy,0xeb000000008A,%1,0,0(%2)" - : "+d" (_ccq), "+d" (_queuestart) - : "d" ((unsigned long)state), "d" (_token) - : "memory", "cc"); + " lgr 1,%[token]\n" + " .insn rsy,0xeb000000008a,%[qs],%[ccq],0(%[state])" + : [ccq] "+&d" (_ccq), [qs] "+&d" (_queuestart) + : [state] "d" ((unsigned long)state), [token] "d" (token) + : "memory", "cc", "1"); *count = _ccq & 0xff; *start = _queuestart & 0xff; @@ -106,16 +106,17 @@ static inline int do_sqbs(u64 token, unsigned char state, int queue, static inline int do_eqbs(u64 token, unsigned char *state, int queue, int *start, int *count, int ack) { - register unsigned long _ccq asm ("0") = *count; - register unsigned long _token asm ("1") = token; unsigned long _queuestart = ((unsigned long)queue << 32) | *start; unsigned long _state = (unsigned long)ack << 63; + unsigned long _ccq = *count; asm volatile( - " .insn rrf,0xB99c0000,%1,%2,0,0" - : "+d" (_ccq), "+d" (_queuestart), "+d" (_state) - : "d" (_token) - : "memory", "cc"); + " lgr 1,%[token]\n" + " .insn rrf,0xb99c0000,%[qs],%[state],%[ccq],0" + : [ccq] "+&d" (_ccq), [qs] "+&d" (_queuestart), + [state] "+&d" (_state) + : [token] "d" (token) + : "memory", "cc", "1"); *count = _ccq & 0xff; *start = _queuestart & 0xff; *state = _state & 0xff; diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 307ce7ff5ca4..3052fab00597 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -31,38 +31,41 @@ MODULE_DESCRIPTION("QDIO base support"); MODULE_LICENSE("GPL"); static inline int do_siga_sync(unsigned long schid, - unsigned int out_mask, unsigned int in_mask, + unsigned long out_mask, unsigned long in_mask, unsigned int fc) { - register unsigned long __fc asm ("0") = fc; - register unsigned long __schid asm ("1") = schid; - register unsigned long out asm ("2") = out_mask; - register unsigned long in asm ("3") = in_mask; int cc; asm volatile( + " lgr 0,%[fc]\n" + " lgr 1,%[schid]\n" + " lgr 2,%[out]\n" + " lgr 3,%[in]\n" " siga 0\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (cc) - : "d" (__fc), "d" (__schid), "d" (out), "d" (in) : "cc"); + " ipm %[cc]\n" + " srl %[cc],28\n" + : [cc] "=&d" (cc) + : [fc] "d" (fc), [schid] "d" (schid), + [out] "d" (out_mask), [in] "d" (in_mask) + : "cc", "0", "1", "2", "3"); return cc; } -static inline int do_siga_input(unsigned long schid, unsigned int mask, - unsigned int fc) +static inline int do_siga_input(unsigned long schid, unsigned long mask, + unsigned long fc) { - register unsigned long __fc asm ("0") = fc; - register unsigned long __schid asm ("1") = schid; - register unsigned long __mask asm ("2") = mask; int cc; asm volatile( + " lgr 0,%[fc]\n" + " lgr 1,%[schid]\n" + " lgr 2,%[mask]\n" " siga 0\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (cc) - : "d" (__fc), "d" (__schid), "d" (__mask) : "cc"); + " ipm %[cc]\n" + " srl %[cc],28\n" + : [cc] "=&d" (cc) + : [fc] "d" (fc), [schid] "d" (schid), [mask] "d" (mask) + : "cc", "0", "1", "2"); return cc; } @@ -78,23 +81,24 @@ static inline int do_siga_input(unsigned long schid, unsigned int mask, * Note: For IQDC unicast queues only the highest priority queue is processed. */ static inline int do_siga_output(unsigned long schid, unsigned long mask, - unsigned int *bb, unsigned int fc, + unsigned int *bb, unsigned long fc, unsigned long aob) { - register unsigned long __fc asm("0") = fc; - register unsigned long __schid asm("1") = schid; - register unsigned long __mask asm("2") = mask; - register unsigned long __aob asm("3") = aob; int cc; asm volatile( + " lgr 0,%[fc]\n" + " lgr 1,%[schid]\n" + " lgr 2,%[mask]\n" + " lgr 3,%[aob]\n" " siga 0\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (cc), "+d" (__fc), "+d" (__aob) - : "d" (__schid), "d" (__mask) - : "cc"); - *bb = __fc >> 31; + " lgr %[fc],0\n" + " ipm %[cc]\n" + " srl %[cc],28\n" + : [cc] "=&d" (cc), [fc] "+&d" (fc) + : [schid] "d" (schid), [mask] "d" (mask), [aob] "d" (aob) + : "cc", "0", "1", "2", "3"); + *bb = fc >> 31; return cc; } diff --git a/drivers/s390/cio/trace.h b/drivers/s390/cio/trace.h index 4803139bce14..86993de25345 100644 --- a/drivers/s390/cio/trace.h +++ b/drivers/s390/cio/trace.h @@ -168,10 +168,8 @@ TRACE_EVENT(s390_cio_tpi, memset(&__entry->tpi_info, 0, sizeof(struct tpi_info)); else if (addr) __entry->tpi_info = *addr; - else { - memcpy(&__entry->tpi_info, &S390_lowcore.subchannel_id, - sizeof(struct tpi_info)); - } + else + __entry->tpi_info = S390_lowcore.tpi_info; __entry->cssid = __entry->tpi_info.schid.cssid; __entry->ssid = __entry->tpi_info.schid.ssid; __entry->schno = __entry->tpi_info.schid.sch_no; diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 2758d05a802d..d2560186d771 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright IBM Corp. 2006, 2020 + * Copyright IBM Corp. 2006, 2021 * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> * Martin Schwidefsky <schwidefsky@de.ibm.com> * Ralph Wuerthner <rwuerthn@de.ibm.com> @@ -77,6 +77,9 @@ EXPORT_SYMBOL(ap_perms_mutex); /* # of bus scans since init */ static atomic64_t ap_scan_bus_count; +/* # of bindings complete since init */ +static atomic64_t ap_bindings_complete_count = ATOMIC64_INIT(0); + /* completion for initial APQN bindings complete */ static DECLARE_COMPLETION(ap_init_apqn_bindings_complete); @@ -584,22 +587,47 @@ static int ap_bus_match(struct device *dev, struct device_driver *drv) */ static int ap_uevent(struct device *dev, struct kobj_uevent_env *env) { - int rc; + int rc = 0; struct ap_device *ap_dev = to_ap_dev(dev); /* Uevents from ap bus core don't need extensions to the env */ if (dev == ap_root_device) return 0; - /* Set up DEV_TYPE environment variable. */ - rc = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type); - if (rc) - return rc; + if (is_card_dev(dev)) { + struct ap_card *ac = to_ap_card(&ap_dev->device); - /* Add MODALIAS= */ - rc = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type); - if (rc) - return rc; + /* Set up DEV_TYPE environment variable. */ + rc = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type); + if (rc) + return rc; + /* Add MODALIAS= */ + rc = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type); + if (rc) + return rc; + + /* Add MODE=<accel|cca|ep11> */ + if (ap_test_bit(&ac->functions, AP_FUNC_ACCEL)) + rc = add_uevent_var(env, "MODE=accel"); + else if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) + rc = add_uevent_var(env, "MODE=cca"); + else if (ap_test_bit(&ac->functions, AP_FUNC_EP11)) + rc = add_uevent_var(env, "MODE=ep11"); + if (rc) + return rc; + } else { + struct ap_queue *aq = to_ap_queue(&ap_dev->device); + + /* Add MODE=<accel|cca|ep11> */ + if (ap_test_bit(&aq->card->functions, AP_FUNC_ACCEL)) + rc = add_uevent_var(env, "MODE=accel"); + else if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) + rc = add_uevent_var(env, "MODE=cca"); + else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11)) + rc = add_uevent_var(env, "MODE=ep11"); + if (rc) + return rc; + } return 0; } @@ -613,11 +641,36 @@ static void ap_send_init_scan_done_uevent(void) static void ap_send_bindings_complete_uevent(void) { - char *envp[] = { "BINDINGS=complete", NULL }; + char buf[32]; + char *envp[] = { "BINDINGS=complete", buf, NULL }; + snprintf(buf, sizeof(buf), "COMPLETECOUNT=%llu", + atomic64_inc_return(&ap_bindings_complete_count)); kobject_uevent_env(&ap_root_device->kobj, KOBJ_CHANGE, envp); } +void ap_send_config_uevent(struct ap_device *ap_dev, bool cfg) +{ + char buf[16]; + char *envp[] = { buf, NULL }; + + snprintf(buf, sizeof(buf), "CONFIG=%d", cfg ? 1 : 0); + + kobject_uevent_env(&ap_dev->device.kobj, KOBJ_CHANGE, envp); +} +EXPORT_SYMBOL(ap_send_config_uevent); + +void ap_send_online_uevent(struct ap_device *ap_dev, int online) +{ + char buf[16]; + char *envp[] = { buf, NULL }; + + snprintf(buf, sizeof(buf), "ONLINE=%d", online ? 1 : 0); + + kobject_uevent_env(&ap_dev->device.kobj, KOBJ_CHANGE, envp); +} +EXPORT_SYMBOL(ap_send_online_uevent); + /* * calc # of bound APQNs */ @@ -885,8 +938,6 @@ int ap_driver_register(struct ap_driver *ap_drv, struct module *owner, struct device_driver *drv = &ap_drv->driver; drv->bus = &ap_bus_type; - drv->probe = ap_device_probe; - drv->remove = ap_device_remove; drv->owner = owner; drv->name = name; return driver_register(drv); @@ -1319,6 +1370,8 @@ static struct bus_type ap_bus_type = { .bus_groups = ap_bus_groups, .match = &ap_bus_match, .uevent = &ap_uevent, + .probe = ap_device_probe, + .remove = ap_device_remove, }; /** @@ -1540,6 +1593,7 @@ static inline void ap_scan_domains(struct ap_card *ac) spin_unlock_bh(&aq->lock); AP_DBF_INFO("%s(%d,%d) queue device config off\n", __func__, ac->id, dom); + ap_send_config_uevent(&aq->ap_dev, aq->config); /* 'receive' pending messages with -EAGAIN */ ap_flush_queue(aq); goto put_dev_and_continue; @@ -1554,6 +1608,7 @@ static inline void ap_scan_domains(struct ap_card *ac) spin_unlock_bh(&aq->lock); AP_DBF_INFO("%s(%d,%d) queue device config on\n", __func__, ac->id, dom); + ap_send_config_uevent(&aq->ap_dev, aq->config); goto put_dev_and_continue; } /* handle other error states */ @@ -1663,12 +1718,13 @@ static inline void ap_scan_adapter(int ap) ac->config = false; AP_DBF_INFO("%s(%d) card device config off\n", __func__, ap); - + ap_send_config_uevent(&ac->ap_dev, ac->config); } if (!decfg && !ac->config) { ac->config = true; AP_DBF_INFO("%s(%d) card device config on\n", __func__, ap); + ap_send_config_uevent(&ac->ap_dev, ac->config); } } } diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 472efd3a755c..230fec6510e2 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -362,4 +362,7 @@ int ap_parse_mask_str(const char *str, */ int ap_wait_init_apqn_bindings_complete(unsigned long timeout); +void ap_send_config_uevent(struct ap_device *ap_dev, bool cfg); +void ap_send_online_uevent(struct ap_device *ap_dev, int online); + #endif /* _AP_BUS_H_ */ diff --git a/drivers/s390/crypto/ap_card.c b/drivers/s390/crypto/ap_card.c index d98bdd28d23e..ca9afc5fcaf7 100644 --- a/drivers/s390/crypto/ap_card.c +++ b/drivers/s390/crypto/ap_card.c @@ -167,6 +167,8 @@ static ssize_t config_store(struct device *dev, ac->config = cfg ? true : false; + ap_send_config_uevent(&ac->ap_dev, ac->config); + return count; } diff --git a/drivers/s390/crypto/vfio_ap_drv.c b/drivers/s390/crypto/vfio_ap_drv.c index 7dc72cb718b0..4d2556bc7fe5 100644 --- a/drivers/s390/crypto/vfio_ap_drv.c +++ b/drivers/s390/crypto/vfio_ap_drv.c @@ -22,8 +22,6 @@ MODULE_AUTHOR("IBM Corporation"); MODULE_DESCRIPTION("VFIO AP device driver, Copyright IBM Corp. 2018"); MODULE_LICENSE("GPL v2"); -static struct ap_driver vfio_ap_drv; - struct ap_matrix_dev *matrix_dev; /* Only type 10 adapters (CEX4 and later) are supported @@ -80,6 +78,12 @@ static void vfio_ap_queue_dev_remove(struct ap_device *apdev) mutex_unlock(&matrix_dev->lock); } +static struct ap_driver vfio_ap_drv = { + .probe = vfio_ap_queue_dev_probe, + .remove = vfio_ap_queue_dev_remove, + .ids = ap_queue_ids, +}; + static void vfio_ap_matrix_dev_release(struct device *dev) { struct ap_matrix_dev *matrix_dev = dev_get_drvdata(dev); @@ -181,11 +185,6 @@ static int __init vfio_ap_init(void) if (ret) return ret; - memset(&vfio_ap_drv, 0, sizeof(vfio_ap_drv)); - vfio_ap_drv.probe = vfio_ap_queue_dev_probe; - vfio_ap_drv.remove = vfio_ap_queue_dev_remove; - vfio_ap_drv.ids = ap_queue_ids; - ret = ap_driver_register(&vfio_ap_drv, THIS_MODULE, VFIO_AP_DRV_NAME); if (ret) { vfio_ap_matrix_dev_destroy(); diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 52eaf51c9bb6..5d726cd67314 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -59,7 +59,6 @@ MODULE_PARM_DESC(hwrng_seed, "Turn on/off hwrng auto seed, default is 1 (on)."); DEFINE_SPINLOCK(zcrypt_list_lock); LIST_HEAD(zcrypt_card_list); -int zcrypt_device_count; static atomic_t zcrypt_open_count = ATOMIC_INIT(0); static atomic_t zcrypt_rescan_count = ATOMIC_INIT(0); diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h index 16219efb2f61..93e77e83ad14 100644 --- a/drivers/s390/crypto/zcrypt_api.h +++ b/drivers/s390/crypto/zcrypt_api.h @@ -124,7 +124,6 @@ struct zcrypt_queue { extern atomic_t zcrypt_rescan_req; extern spinlock_t zcrypt_list_lock; -extern int zcrypt_device_count; extern struct list_head zcrypt_card_list; #define for_each_zcrypt_card(_zc) \ @@ -146,7 +145,7 @@ void zcrypt_queue_get(struct zcrypt_queue *); int zcrypt_queue_put(struct zcrypt_queue *); int zcrypt_queue_register(struct zcrypt_queue *); void zcrypt_queue_unregister(struct zcrypt_queue *); -void zcrypt_queue_force_online(struct zcrypt_queue *, int); +bool zcrypt_queue_force_online(struct zcrypt_queue *zq, int online); int zcrypt_rng_device_add(void); void zcrypt_rng_device_remove(void); diff --git a/drivers/s390/crypto/zcrypt_card.c b/drivers/s390/crypto/zcrypt_card.c index 09fe6bb8880b..40fd5d37d26a 100644 --- a/drivers/s390/crypto/zcrypt_card.c +++ b/drivers/s390/crypto/zcrypt_card.c @@ -64,7 +64,8 @@ static ssize_t online_store(struct device *dev, struct ap_card *ac = to_ap_card(dev); struct zcrypt_card *zc = ac->private; struct zcrypt_queue *zq; - int online, id; + int online, id, i = 0, maxzqs = 0; + struct zcrypt_queue **zq_uelist = NULL; if (sscanf(buf, "%d\n", &online) != 1 || online < 0 || online > 1) return -EINVAL; @@ -77,10 +78,35 @@ static ssize_t online_store(struct device *dev, ZCRYPT_DBF(DBF_INFO, "card=%02x online=%d\n", id, online); + ap_send_online_uevent(&ac->ap_dev, online); + spin_lock(&zcrypt_list_lock); + /* + * As we are in atomic context here, directly sending uevents + * does not work. So collect the zqueues in a dynamic array + * and process them after zcrypt_list_lock release. As we get/put + * the zqueue objects, we make sure they exist after lock release. + */ + list_for_each_entry(zq, &zc->zqueues, list) + maxzqs++; + if (maxzqs > 0) + zq_uelist = kcalloc(maxzqs + 1, sizeof(zq), GFP_ATOMIC); list_for_each_entry(zq, &zc->zqueues, list) - zcrypt_queue_force_online(zq, online); + if (zcrypt_queue_force_online(zq, online)) + if (zq_uelist) { + zcrypt_queue_get(zq); + zq_uelist[i++] = zq; + } spin_unlock(&zcrypt_list_lock); + if (zq_uelist) { + for (i = 0; zq_uelist[i]; i++) { + zq = zq_uelist[i]; + ap_send_online_uevent(&zq->queue->ap_dev, online); + zcrypt_queue_put(zq); + } + kfree(zq_uelist); + } + return count; } diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c index d68c0ed5e0dd..bc34bedf9db8 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.c +++ b/drivers/s390/crypto/zcrypt_ccamisc.c @@ -295,7 +295,7 @@ static inline void prep_xcrb(struct ica_xcRB *pxcrb, * Generate (random) CCA AES DATA secure key. */ int cca_genseckey(u16 cardnr, u16 domain, - u32 keybitsize, u8 seckey[SECKEYBLOBSIZE]) + u32 keybitsize, u8 *seckey) { int i, rc, keysize; int seckeysize; @@ -330,7 +330,7 @@ int cca_genseckey(u16 cardnr, u16 domain, struct { u16 toklen; u16 tokattr; - u8 tok[0]; + u8 tok[]; /* ... some more data ... */ } keyblock; } lv3; @@ -438,7 +438,7 @@ EXPORT_SYMBOL(cca_genseckey); * Generate an CCA AES DATA secure key with given key value. */ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize, - const u8 *clrkey, u8 seckey[SECKEYBLOBSIZE]) + const u8 *clrkey, u8 *seckey) { int rc, keysize, seckeysize; u8 *mem, *ptr; @@ -471,7 +471,7 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize, struct { u16 toklen; u16 tokattr; - u8 tok[0]; + u8 tok[]; /* ... some more data ... */ } keyblock; } lv3; @@ -577,8 +577,8 @@ EXPORT_SYMBOL(cca_clr2seckey); * Derive proteced key from an CCA AES DATA secure key. */ int cca_sec2protkey(u16 cardnr, u16 domain, - const u8 seckey[SECKEYBLOBSIZE], - u8 *protkey, u32 *protkeylen, u32 *protkeytype) + const u8 *seckey, u8 *protkey, u32 *protkeylen, + u32 *protkeytype) { int rc; u8 *mem, *ptr; @@ -596,7 +596,7 @@ int cca_sec2protkey(u16 cardnr, u16 domain, u16 len; u16 attr_len; u16 attr_flags; - u8 token[0]; /* cca secure key token */ + u8 token[]; /* cca secure key token */ } lv2; } __packed * preqparm; struct uskrepparm { diff --git a/drivers/s390/crypto/zcrypt_ccamisc.h b/drivers/s390/crypto/zcrypt_ccamisc.h index e7105443d5cb..3513cd8ab9bc 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.h +++ b/drivers/s390/crypto/zcrypt_ccamisc.h @@ -171,8 +171,8 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize, * Derive proteced key from an CCA AES DATA secure key. */ int cca_sec2protkey(u16 cardnr, u16 domain, - const u8 seckey[SECKEYBLOBSIZE], - u8 *protkey, u32 *protkeylen, u32 *protkeytype); + const u8 *seckey, u8 *protkey, u32 *protkeylen, + u32 *protkeytype); /* * Generate (random) CCA AES CIPHER secure key. diff --git a/drivers/s390/crypto/zcrypt_msgtype50.c b/drivers/s390/crypto/zcrypt_msgtype50.c index bf14ee445f89..6d1800cb21df 100644 --- a/drivers/s390/crypto/zcrypt_msgtype50.c +++ b/drivers/s390/crypto/zcrypt_msgtype50.c @@ -375,6 +375,7 @@ static int convert_type80(struct zcrypt_queue *zq, AP_QID_CARD(zq->queue->qid), AP_QID_QUEUE(zq->queue->qid), t80h->code); + ap_send_online_uevent(&zq->queue->ap_dev, zq->online); return -EAGAIN; } if (zq->zcard->user_space_type == ZCRYPT_CEX2A) @@ -412,6 +413,7 @@ static int convert_response_cex2a(struct zcrypt_queue *zq, AP_QID_CARD(zq->queue->qid), AP_QID_QUEUE(zq->queue->qid), (int) rtype); + ap_send_online_uevent(&zq->queue->ap_dev, zq->online); return -EAGAIN; } } diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c index 307f90657d1d..da6b2bf779a8 100644 --- a/drivers/s390/crypto/zcrypt_msgtype6.c +++ b/drivers/s390/crypto/zcrypt_msgtype6.c @@ -675,6 +675,7 @@ static int convert_type86_ica(struct zcrypt_queue *zq, AP_QID_CARD(zq->queue->qid), AP_QID_QUEUE(zq->queue->qid), (int) service_rc, (int) service_rs); + ap_send_online_uevent(&zq->queue->ap_dev, zq->online); return -EAGAIN; } data = msg->text; @@ -820,6 +821,7 @@ static int convert_response_ica(struct zcrypt_queue *zq, AP_QID_CARD(zq->queue->qid), AP_QID_QUEUE(zq->queue->qid), (int) msg->hdr.type); + ap_send_online_uevent(&zq->queue->ap_dev, zq->online); return -EAGAIN; } } @@ -854,6 +856,7 @@ static int convert_response_xcrb(bool userspace, struct zcrypt_queue *zq, AP_QID_CARD(zq->queue->qid), AP_QID_QUEUE(zq->queue->qid), (int) msg->hdr.type); + ap_send_online_uevent(&zq->queue->ap_dev, zq->online); return -EAGAIN; } } @@ -883,6 +886,7 @@ static int convert_response_ep11_xcrb(bool userspace, struct zcrypt_queue *zq, AP_QID_CARD(zq->queue->qid), AP_QID_QUEUE(zq->queue->qid), (int) msg->hdr.type); + ap_send_online_uevent(&zq->queue->ap_dev, zq->online); return -EAGAIN; } } @@ -913,6 +917,7 @@ static int convert_response_rng(struct zcrypt_queue *zq, AP_QID_CARD(zq->queue->qid), AP_QID_QUEUE(zq->queue->qid), (int) msg->hdr.type); + ap_send_online_uevent(&zq->queue->ap_dev, zq->online); return -EAGAIN; } } diff --git a/drivers/s390/crypto/zcrypt_queue.c b/drivers/s390/crypto/zcrypt_queue.c index c3ffbd26b73f..605904b86287 100644 --- a/drivers/s390/crypto/zcrypt_queue.c +++ b/drivers/s390/crypto/zcrypt_queue.c @@ -70,6 +70,8 @@ static ssize_t online_store(struct device *dev, AP_QID_QUEUE(zq->queue->qid), online); + ap_send_online_uevent(&aq->ap_dev, online); + if (!online) ap_flush_queue(zq->queue); return count; @@ -98,11 +100,15 @@ static const struct attribute_group zcrypt_queue_attr_group = { .attrs = zcrypt_queue_attrs, }; -void zcrypt_queue_force_online(struct zcrypt_queue *zq, int online) +bool zcrypt_queue_force_online(struct zcrypt_queue *zq, int online) { - zq->online = online; - if (!online) - ap_flush_queue(zq->queue); + if (!!zq->online != !!online) { + zq->online = online; + if (!online) + ap_flush_queue(zq->queue); + return true; + } + return false; } struct zcrypt_queue *zcrypt_queue_alloc(size_t max_response_size) @@ -173,7 +179,6 @@ int zcrypt_queue_register(struct zcrypt_queue *zq) AP_QID_CARD(zq->queue->qid), AP_QID_QUEUE(zq->queue->qid)); list_add_tail(&zq->list, &zc->zqueues); - zcrypt_device_count++; spin_unlock(&zcrypt_list_lock); rc = sysfs_create_group(&zq->queue->ap_dev.device.kobj, @@ -216,7 +221,6 @@ void zcrypt_queue_unregister(struct zcrypt_queue *zq) zc = zq->zcard; spin_lock(&zcrypt_list_lock); list_del_init(&zq->list); - zcrypt_device_count--; spin_unlock(&zcrypt_list_lock); if (zq->ops->rng) zcrypt_rng_device_remove(); diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c index 54e686dca6de..d35e7a3f7067 100644 --- a/drivers/s390/virtio/virtio_ccw.c +++ b/drivers/s390/virtio/virtio_ccw.c @@ -388,31 +388,6 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev, ccw_device_dma_free(vcdev->cdev, thinint_area, sizeof(*thinint_area)); } -static inline long __do_kvm_notify(struct subchannel_id schid, - unsigned long queue_index, - long cookie) -{ - register unsigned long __nr asm("1") = KVM_S390_VIRTIO_CCW_NOTIFY; - register struct subchannel_id __schid asm("2") = schid; - register unsigned long __index asm("3") = queue_index; - register long __rc asm("2"); - register long __cookie asm("4") = cookie; - - asm volatile ("diag 2,4,0x500\n" - : "=d" (__rc) : "d" (__nr), "d" (__schid), "d" (__index), - "d"(__cookie) - : "memory", "cc"); - return __rc; -} - -static inline long do_kvm_notify(struct subchannel_id schid, - unsigned long queue_index, - long cookie) -{ - diag_stat_inc(DIAG_STAT_X500); - return __do_kvm_notify(schid, queue_index, cookie); -} - static bool virtio_ccw_kvm_notify(struct virtqueue *vq) { struct virtio_ccw_vq_info *info = vq->priv; @@ -421,7 +396,10 @@ static bool virtio_ccw_kvm_notify(struct virtqueue *vq) vcdev = to_vc_device(info->vq->vdev); ccw_device_get_schid(vcdev->cdev, &schid); - info->cookie = do_kvm_notify(schid, vq->index, info->cookie); + BUILD_BUG_ON(sizeof(struct subchannel_id) != sizeof(unsigned int)); + info->cookie = kvm_hypercall3(KVM_S390_VIRTIO_CCW_NOTIFY, + *((unsigned int *)&schid), + vq->index, info->cookie); if (info->cookie < 0) return false; return true; diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 4dc42a8ff71a..8f44d433e06e 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -235,19 +235,6 @@ config SCSI_FC_ATTRS each attached FiberChannel device to sysfs, say Y. Otherwise, say N. -config FC_APPID - bool "Enable support to track FC I/O Traffic" - depends on BLOCK && BLK_CGROUP - depends on SCSI - select BLK_CGROUP_FC_APPID - default y - help - If you say Y here, it enables the support to track - FC I/O traffic over fabric. It enables the Fabric and the - storage targets to identify, monitor, and handle FC traffic - based on VM tags by inserting application specific - identification into the FC frame. - config SCSI_ISCSI_ATTRS tristate "iSCSI Transport Attributes" depends on SCSI && NET diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c index 297a66770260..46815e65f7a4 100644 --- a/drivers/scsi/aic94xx/aic94xx_sds.c +++ b/drivers/scsi/aic94xx/aic94xx_sds.c @@ -718,10 +718,12 @@ static void *asd_find_ll_by_id(void * const start, const u8 id0, const u8 id1) do { switch (id1) { default: - if (el->id1 == id1) + if (el->id1 == id1) { + fallthrough; case 0xFF: if (el->id0 == id0) return el; + } } el = start + le16_to_cpu(el->next); } while (el != start); diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index f3032e30c3e4..5983e05b648f 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -13146,7 +13146,7 @@ lpfc_sli4_request_firmware_update(struct lpfc_hba *phba, uint8_t fw_upgrade) snprintf(file_name, ELX_MODEL_NAME_SIZE, "%s.grp", phba->ModelName); if (fw_upgrade == INT_FW_UPGRADE) { - ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, + ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, file_name, &phba->pcidev->dev, GFP_KERNEL, (void *)phba, lpfc_write_firmware); diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index c6cd5a8e5c85..58a252c38992 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1997,7 +1997,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev) struct request *req; struct scsi_request *rq; - req = blk_get_request(sdev->request_queue, REQ_OP_SCSI_IN, 0); + req = blk_get_request(sdev->request_queue, REQ_OP_DRV_IN, 0); if (IS_ERR(req)) return; rq = scsi_req(req); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 6b994baf87c2..c9a91a52e637 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -215,7 +215,7 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, req = blk_get_request(sdev->request_queue, data_direction == DMA_TO_DEVICE ? - REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, + REQ_OP_DRV_OUT : REQ_OP_DRV_IN, rq_flags & RQF_PM ? BLK_MQ_REQ_PM : 0); if (IS_ERR(req)) return PTR_ERR(req); @@ -543,7 +543,7 @@ static bool scsi_end_request(struct request *req, blk_status_t error, if (blk_queue_add_random(q)) add_disk_randomness(req->rq_disk); - if (!blk_rq_is_scsi(req)) { + if (!blk_rq_is_passthrough(req)) { WARN_ON_ONCE(!(cmd->flags & SCMD_INITIALIZED)); cmd->flags &= ~SCMD_INITIALIZED; } @@ -1113,7 +1113,7 @@ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd) bool in_flight; int budget_token = cmd->budget_token; - if (!blk_rq_is_scsi(rq) && !(flags & SCMD_INITIALIZED)) { + if (!blk_rq_is_passthrough(rq) && !(flags & SCMD_INITIALIZED)) { flags |= SCMD_INITIALIZED; scsi_initialize_rq(rq); } @@ -1554,7 +1554,7 @@ static blk_status_t scsi_prepare_cmd(struct request *req) * Special handling for passthrough commands, which don't go to the ULP * at all: */ - if (blk_rq_is_scsi(req)) + if (blk_rq_is_passthrough(req)) return scsi_setup_scsi_cmnd(sdev, req); if (sdev->handler && sdev->handler->prep_fn) { diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 4e66994be190..91e2221bbb0d 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1759,7 +1759,7 @@ sg_start_req(Sg_request *srp, unsigned char *cmd) * not expect an EWOULDBLOCK from this condition. */ rq = blk_get_request(q, hp->dxfer_direction == SG_DXFER_TO_DEV ? - REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, 0); + REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0); if (IS_ERR(rq)) { kfree(long_cmdp); return PTR_ERR(rq); diff --git a/drivers/scsi/snic/snic_debugfs.c b/drivers/scsi/snic/snic_debugfs.c index 3aeee856d5c7..5e0faeba516e 100644 --- a/drivers/scsi/snic/snic_debugfs.c +++ b/drivers/scsi/snic/snic_debugfs.c @@ -430,21 +430,19 @@ static const struct seq_operations snic_trc_sops = { DEFINE_SEQ_ATTRIBUTE(snic_trc); +#define TRC_ENABLE_FILE "tracing_enable" +#define TRC_FILE "trace" /* * snic_trc_debugfs_init : creates trace/tracing_enable files for trace * under debugfs */ void snic_trc_debugfs_init(void) { - snic_glob->trc.trc_enable = debugfs_create_bool("tracing_enable", - S_IFREG | S_IRUGO | S_IWUSR, - snic_glob->trc_root, - &snic_glob->trc.enable); - - snic_glob->trc.trc_file = debugfs_create_file("trace", - S_IFREG | S_IRUGO | S_IWUSR, - snic_glob->trc_root, NULL, - &snic_trc_fops); + debugfs_create_bool(TRC_ENABLE_FILE, S_IFREG | S_IRUGO | S_IWUSR, + snic_glob->trc_root, &snic_glob->trc.enable); + + debugfs_create_file(TRC_FILE, S_IFREG | S_IRUGO | S_IWUSR, + snic_glob->trc_root, NULL, &snic_trc_fops); } /* @@ -453,9 +451,6 @@ void snic_trc_debugfs_init(void) void snic_trc_debugfs_term(void) { - debugfs_remove(snic_glob->trc.trc_file); - snic_glob->trc.trc_file = NULL; - - debugfs_remove(snic_glob->trc.trc_enable); - snic_glob->trc.trc_enable = NULL; + debugfs_remove(debugfs_lookup(TRC_FILE, snic_glob->trc_root)); + debugfs_remove(debugfs_lookup(TRC_ENABLE_FILE, snic_glob->trc_root)); } diff --git a/drivers/scsi/snic/snic_trc.h b/drivers/scsi/snic/snic_trc.h index 87dcc7457d15..ce305b4b8fa2 100644 --- a/drivers/scsi/snic/snic_trc.h +++ b/drivers/scsi/snic/snic_trc.h @@ -46,9 +46,6 @@ struct snic_trc { u32 rd_idx; u32 wr_idx; bool enable; /* Control Variable for Tracing */ - - struct dentry *trc_enable; /* debugfs file object */ - struct dentry *trc_file; }; int snic_trc_init(void); diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 66f48bd6da76..c6f14540ae03 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -549,7 +549,7 @@ static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd, req = blk_get_request(SRpnt->stp->device->request_queue, data_direction == DMA_TO_DEVICE ? - REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, 0); + REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0); if (IS_ERR(req)) return PTR_ERR(req); rq = scsi_req(req); diff --git a/drivers/siox/siox-bus-gpio.c b/drivers/siox/siox-bus-gpio.c index 46b4cda36bac..aeefeb725524 100644 --- a/drivers/siox/siox-bus-gpio.c +++ b/drivers/siox/siox-bus-gpio.c @@ -102,29 +102,29 @@ static int siox_gpio_probe(struct platform_device *pdev) ddata->din = devm_gpiod_get(dev, "din", GPIOD_IN); if (IS_ERR(ddata->din)) { - ret = PTR_ERR(ddata->din); - dev_err(dev, "Failed to get %s GPIO: %d\n", "din", ret); + ret = dev_err_probe(dev, PTR_ERR(ddata->din), + "Failed to get din GPIO\n"); goto err; } ddata->dout = devm_gpiod_get(dev, "dout", GPIOD_OUT_LOW); if (IS_ERR(ddata->dout)) { - ret = PTR_ERR(ddata->dout); - dev_err(dev, "Failed to get %s GPIO: %d\n", "dout", ret); + ret = dev_err_probe(dev, PTR_ERR(ddata->dout), + "Failed to get dout GPIO\n"); goto err; } ddata->dclk = devm_gpiod_get(dev, "dclk", GPIOD_OUT_LOW); if (IS_ERR(ddata->dclk)) { - ret = PTR_ERR(ddata->dclk); - dev_err(dev, "Failed to get %s GPIO: %d\n", "dclk", ret); + ret = dev_err_probe(dev, PTR_ERR(ddata->dclk), + "Failed to get dclk GPIO\n"); goto err; } ddata->dld = devm_gpiod_get(dev, "dld", GPIOD_OUT_LOW); if (IS_ERR(ddata->dld)) { - ret = PTR_ERR(ddata->dld); - dev_err(dev, "Failed to get %s GPIO: %d\n", "dld", ret); + ret = dev_err_probe(dev, PTR_ERR(ddata->dld), + "Failed to get dld GPIO\n"); goto err; } @@ -134,7 +134,8 @@ static int siox_gpio_probe(struct platform_device *pdev) ret = siox_master_register(smaster); if (ret) { - dev_err(dev, "Failed to register siox master: %d\n", ret); + dev_err_probe(dev, ret, + "Failed to register siox master\n"); err: siox_master_put(smaster); } diff --git a/drivers/soc/litex/Kconfig b/drivers/soc/litex/Kconfig index e7011d665b15..e6ba3573a772 100644 --- a/drivers/soc/litex/Kconfig +++ b/drivers/soc/litex/Kconfig @@ -17,16 +17,4 @@ config LITEX_SOC_CONTROLLER All drivers that use functions from litex.h must depend on LITEX. -config LITEX_SUBREG_SIZE - int "Size of a LiteX CSR subregister, in bytes" - depends on LITEX - range 1 4 - default 4 - help - LiteX MMIO registers (referred to as Configuration and Status - registers, or CSRs) are spread across adjacent 8- or 32-bit - subregisters, located at 32-bit aligned MMIO addresses. Use - this to select the appropriate size (1 or 4 bytes) matching - your particular LiteX build. - endmenu diff --git a/drivers/soc/litex/litex_soc_ctrl.c b/drivers/soc/litex/litex_soc_ctrl.c index c3e379a990f2..f75790091d38 100644 --- a/drivers/soc/litex/litex_soc_ctrl.c +++ b/drivers/soc/litex/litex_soc_ctrl.c @@ -62,8 +62,7 @@ static int litex_check_csr_access(void __iomem *reg_addr) /* restore original value of the SCRATCH register */ litex_write32(reg_addr + SCRATCH_REG_OFF, SCRATCH_REG_VALUE); - pr_info("LiteX SoC Controller driver initialized: subreg:%d, align:%d", - LITEX_SUBREG_SIZE, LITEX_SUBREG_ALIGN); + pr_info("LiteX SoC Controller driver initialized"); return 0; } diff --git a/drivers/soc/qcom/smem_state.c b/drivers/soc/qcom/smem_state.c index d2b558438deb..31faf4aa868e 100644 --- a/drivers/soc/qcom/smem_state.c +++ b/drivers/soc/qcom/smem_state.c @@ -151,6 +151,42 @@ void qcom_smem_state_put(struct qcom_smem_state *state) } EXPORT_SYMBOL_GPL(qcom_smem_state_put); +static void devm_qcom_smem_state_release(struct device *dev, void *res) +{ + qcom_smem_state_put(*(struct qcom_smem_state **)res); +} + +/** + * devm_qcom_smem_state_get() - acquire handle to a devres managed state + * @dev: client device pointer + * @con_id: name of the state to lookup + * @bit: flags from the state reference, indicating which bit's affected + * + * Returns handle to the state, or ERR_PTR(). qcom_smem_state_put() is called + * automatically when @dev is removed. + */ +struct qcom_smem_state *devm_qcom_smem_state_get(struct device *dev, + const char *con_id, + unsigned *bit) +{ + struct qcom_smem_state **ptr, *state; + + ptr = devres_alloc(devm_qcom_smem_state_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + state = qcom_smem_state_get(dev, con_id, bit); + if (!IS_ERR(state)) { + *ptr = state; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return state; +} +EXPORT_SYMBOL_GPL(devm_qcom_smem_state_get); + /** * qcom_smem_state_register() - register a new state * @of_node: of_node used for matching client lookups diff --git a/drivers/soundwire/Kconfig b/drivers/soundwire/Kconfig index 016e74230bb7..2b7795233282 100644 --- a/drivers/soundwire/Kconfig +++ b/drivers/soundwire/Kconfig @@ -25,6 +25,7 @@ config SOUNDWIRE_INTEL tristate "Intel SoundWire Master driver" select SOUNDWIRE_CADENCE select SOUNDWIRE_GENERIC_ALLOCATION + select AUXILIARY_BUS depends on ACPI && SND_SOC help SoundWire Intel Master driver. diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 5d5b0bd59ae3..3e6d4addac2f 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -394,13 +394,13 @@ sdw_nread_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) } static int -sdw_nwrite_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) +sdw_nwrite_no_pm(struct sdw_slave *slave, u32 addr, size_t count, const u8 *val) { struct sdw_msg msg; int ret; ret = sdw_fill_msg(&msg, slave, addr, count, - slave->dev_num, SDW_MSG_FLAG_WRITE, val); + slave->dev_num, SDW_MSG_FLAG_WRITE, (u8 *)val); if (ret < 0) return ret; @@ -550,9 +550,9 @@ EXPORT_SYMBOL(sdw_nread); * @slave: SDW Slave * @addr: Register address * @count: length - * @val: Buffer for values to be read + * @val: Buffer for values to be written */ -int sdw_nwrite(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) +int sdw_nwrite(struct sdw_slave *slave, u32 addr, size_t count, const u8 *val) { int ret; @@ -836,26 +836,6 @@ static void sdw_modify_slave_status(struct sdw_slave *slave, mutex_unlock(&bus->bus_lock); } -static enum sdw_clk_stop_mode sdw_get_clk_stop_mode(struct sdw_slave *slave) -{ - enum sdw_clk_stop_mode mode; - - /* - * Query for clock stop mode if Slave implements - * ops->get_clk_stop_mode, else read from property. - */ - if (slave->ops && slave->ops->get_clk_stop_mode) { - mode = slave->ops->get_clk_stop_mode(slave); - } else { - if (slave->prop.clk_stop_mode1) - mode = SDW_CLK_STOP_MODE1; - else - mode = SDW_CLK_STOP_MODE0; - } - - return mode; -} - static int sdw_slave_clk_stop_callback(struct sdw_slave *slave, enum sdw_clk_stop_mode mode, enum sdw_clk_stop_type type) @@ -864,11 +844,8 @@ static int sdw_slave_clk_stop_callback(struct sdw_slave *slave, if (slave->ops && slave->ops->clk_stop) { ret = slave->ops->clk_stop(slave, mode, type); - if (ret < 0) { - dev_err(&slave->dev, - "Clk Stop type =%d failed: %d\n", type, ret); + if (ret < 0) return ret; - } } return 0; @@ -895,7 +872,8 @@ static int sdw_slave_clk_stop_prepare(struct sdw_slave *slave, } else { ret = sdw_read_no_pm(slave, SDW_SCP_SYSTEMCTRL); if (ret < 0) { - dev_err(&slave->dev, "SDW_SCP_SYSTEMCTRL read failed:%d\n", ret); + if (ret != -ENODATA) + dev_err(&slave->dev, "SDW_SCP_SYSTEMCTRL read failed:%d\n", ret); return ret; } val = ret; @@ -904,9 +882,8 @@ static int sdw_slave_clk_stop_prepare(struct sdw_slave *slave, ret = sdw_write_no_pm(slave, SDW_SCP_SYSTEMCTRL, val); - if (ret < 0) - dev_err(&slave->dev, - "Clock Stop prepare failed for slave: %d", ret); + if (ret < 0 && ret != -ENODATA) + dev_err(&slave->dev, "SDW_SCP_SYSTEMCTRL write failed:%d\n", ret); return ret; } @@ -924,7 +901,7 @@ static int sdw_bus_wait_for_clk_prep_deprep(struct sdw_bus *bus, u16 dev_num) } val &= SDW_SCP_STAT_CLK_STP_NF; if (!val) { - dev_dbg(bus->dev, "clock stop prep/de-prep done slave:%d", + dev_dbg(bus->dev, "clock stop prep/de-prep done slave:%d\n", dev_num); return 0; } @@ -933,7 +910,7 @@ static int sdw_bus_wait_for_clk_prep_deprep(struct sdw_bus *bus, u16 dev_num) retry--; } while (retry); - dev_err(bus->dev, "clock stop prep/de-prep failed slave:%d", + dev_err(bus->dev, "clock stop prep/de-prep failed slave:%d\n", dev_num); return -ETIMEDOUT; @@ -948,7 +925,6 @@ static int sdw_bus_wait_for_clk_prep_deprep(struct sdw_bus *bus, u16 dev_num) */ int sdw_bus_prep_clk_stop(struct sdw_bus *bus) { - enum sdw_clk_stop_mode slave_mode; bool simple_clk_stop = true; struct sdw_slave *slave; bool is_slave = false; @@ -958,6 +934,9 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus) * In order to save on transition time, prepare * each Slave and then wait for all Slave(s) to be * prepared for clock stop. + * If one of the Slave devices has lost sync and + * replies with Command Ignored/-ENODATA, we continue + * the loop */ list_for_each_entry(slave, &bus->slaves, node) { if (!slave->dev_num) @@ -970,36 +949,45 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus) /* Identify if Slave(s) are available on Bus */ is_slave = true; - slave_mode = sdw_get_clk_stop_mode(slave); - slave->curr_clk_stop_mode = slave_mode; - - ret = sdw_slave_clk_stop_callback(slave, slave_mode, + ret = sdw_slave_clk_stop_callback(slave, + SDW_CLK_STOP_MODE0, SDW_CLK_PRE_PREPARE); - if (ret < 0) { - dev_err(&slave->dev, - "pre-prepare failed:%d", ret); - return ret; - } - - ret = sdw_slave_clk_stop_prepare(slave, - slave_mode, true); - if (ret < 0) { - dev_err(&slave->dev, - "pre-prepare failed:%d", ret); + if (ret < 0 && ret != -ENODATA) { + dev_err(&slave->dev, "clock stop pre-prepare cb failed:%d\n", ret); return ret; } - if (slave_mode == SDW_CLK_STOP_MODE1) + /* Only prepare a Slave device if needed */ + if (!slave->prop.simple_clk_stop_capable) { simple_clk_stop = false; + + ret = sdw_slave_clk_stop_prepare(slave, + SDW_CLK_STOP_MODE0, + true); + if (ret < 0 && ret != -ENODATA) { + dev_err(&slave->dev, "clock stop prepare failed:%d\n", ret); + return ret; + } + } } /* Skip remaining clock stop preparation if no Slave is attached */ if (!is_slave) - return ret; + return 0; + /* + * Don't wait for all Slaves to be ready if they follow the simple + * state machine + */ if (!simple_clk_stop) { ret = sdw_bus_wait_for_clk_prep_deprep(bus, SDW_BROADCAST_DEV_NUM); + /* + * if there are no Slave devices present and the reply is + * Command_Ignored/-ENODATA, we don't need to continue with the + * flow and can just return here. The error code is not modified + * and its handling left as an exercise for the caller. + */ if (ret < 0) return ret; } @@ -1013,21 +1001,17 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus) slave->status != SDW_SLAVE_ALERT) continue; - slave_mode = slave->curr_clk_stop_mode; - - if (slave_mode == SDW_CLK_STOP_MODE1) { - ret = sdw_slave_clk_stop_callback(slave, - slave_mode, - SDW_CLK_POST_PREPARE); + ret = sdw_slave_clk_stop_callback(slave, + SDW_CLK_STOP_MODE0, + SDW_CLK_POST_PREPARE); - if (ret < 0) { - dev_err(&slave->dev, - "post-prepare failed:%d", ret); - } + if (ret < 0 && ret != -ENODATA) { + dev_err(&slave->dev, "clock stop post-prepare cb failed:%d\n", ret); + return ret; } } - return ret; + return 0; } EXPORT_SYMBOL(sdw_bus_prep_clk_stop); @@ -1050,12 +1034,8 @@ int sdw_bus_clk_stop(struct sdw_bus *bus) ret = sdw_bwrite_no_pm(bus, SDW_BROADCAST_DEV_NUM, SDW_SCP_CTRL, SDW_SCP_CTRL_CLK_STP_NOW); if (ret < 0) { - if (ret == -ENODATA) - dev_dbg(bus->dev, - "ClockStopNow Broadcast msg ignored %d", ret); - else - dev_err(bus->dev, - "ClockStopNow Broadcast msg failed %d", ret); + if (ret != -ENODATA) + dev_err(bus->dev, "ClockStopNow Broadcast msg failed %d\n", ret); return ret; } @@ -1074,7 +1054,6 @@ EXPORT_SYMBOL(sdw_bus_clk_stop); */ int sdw_bus_exit_clk_stop(struct sdw_bus *bus) { - enum sdw_clk_stop_mode mode; bool simple_clk_stop = true; struct sdw_slave *slave; bool is_slave = false; @@ -1096,33 +1075,36 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus) /* Identify if Slave(s) are available on Bus */ is_slave = true; - mode = slave->curr_clk_stop_mode; - - if (mode == SDW_CLK_STOP_MODE1) { - simple_clk_stop = false; - continue; - } - - ret = sdw_slave_clk_stop_callback(slave, mode, + ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_STOP_MODE0, SDW_CLK_PRE_DEPREPARE); if (ret < 0) - dev_warn(&slave->dev, - "clk stop deprep failed:%d", ret); + dev_warn(&slave->dev, "clock stop pre-deprepare cb failed:%d\n", ret); - ret = sdw_slave_clk_stop_prepare(slave, mode, - false); + /* Only de-prepare a Slave device if needed */ + if (!slave->prop.simple_clk_stop_capable) { + simple_clk_stop = false; - if (ret < 0) - dev_warn(&slave->dev, - "clk stop deprep failed:%d", ret); + ret = sdw_slave_clk_stop_prepare(slave, SDW_CLK_STOP_MODE0, + false); + + if (ret < 0) + dev_warn(&slave->dev, "clock stop deprepare failed:%d\n", ret); + } } /* Skip remaining clock stop de-preparation if no Slave is attached */ if (!is_slave) return 0; - if (!simple_clk_stop) - sdw_bus_wait_for_clk_prep_deprep(bus, SDW_BROADCAST_DEV_NUM); + /* + * Don't wait for all Slaves to be ready if they follow the simple + * state machine + */ + if (!simple_clk_stop) { + ret = sdw_bus_wait_for_clk_prep_deprep(bus, SDW_BROADCAST_DEV_NUM); + if (ret < 0) + dev_warn(&slave->dev, "clock stop deprepare wait failed:%d\n", ret); + } list_for_each_entry(slave, &bus->slaves, node) { if (!slave->dev_num) @@ -1132,9 +1114,10 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus) slave->status != SDW_SLAVE_ALERT) continue; - mode = slave->curr_clk_stop_mode; - sdw_slave_clk_stop_callback(slave, mode, - SDW_CLK_POST_DEPREPARE); + ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_STOP_MODE0, + SDW_CLK_POST_DEPREPARE); + if (ret < 0) + dev_warn(&slave->dev, "clock stop post-deprepare cb failed:%d\n", ret); } return 0; diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c index 192dac10f0c2..25950422b085 100644 --- a/drivers/soundwire/cadence_master.c +++ b/drivers/soundwire/cadence_master.c @@ -1428,20 +1428,6 @@ int sdw_cdns_clock_stop(struct sdw_cdns *cdns, bool block_wake) } } - /* - * This CMD_ACCEPT should be used when there are no devices - * attached on the link when entering clock stop mode. If this is - * not set and there is a broadcast write then the command ignored - * will be treated as a failure - */ - if (!slave_present) - cdns_updatel(cdns, CDNS_MCP_CONTROL, - CDNS_MCP_CONTROL_CMD_ACCEPT, - CDNS_MCP_CONTROL_CMD_ACCEPT); - else - cdns_updatel(cdns, CDNS_MCP_CONTROL, - CDNS_MCP_CONTROL_CMD_ACCEPT, 0); - /* commit changes */ ret = cdns_config_update(cdns); if (ret < 0) { @@ -1508,11 +1494,8 @@ int sdw_cdns_clock_restart(struct sdw_cdns *cdns, bool bus_reset) cdns_updatel(cdns, CDNS_MCP_CONTROL, CDNS_MCP_CONTROL_BLOCK_WAKEUP, 0); - /* - * clear CMD_ACCEPT so that the command ignored - * will be treated as a failure during a broadcast write - */ - cdns_updatel(cdns, CDNS_MCP_CONTROL, CDNS_MCP_CONTROL_CMD_ACCEPT, 0); + cdns_updatel(cdns, CDNS_MCP_CONTROL, CDNS_MCP_CONTROL_CMD_ACCEPT, + CDNS_MCP_CONTROL_CMD_ACCEPT); if (!bus_reset) { diff --git a/drivers/soundwire/cadence_master.h b/drivers/soundwire/cadence_master.h index 4d1aab5b5ec2..0e7f8b35bb21 100644 --- a/drivers/soundwire/cadence_master.h +++ b/drivers/soundwire/cadence_master.h @@ -180,9 +180,6 @@ enum sdw_command_response cdns_xfer_msg_defer(struct sdw_bus *bus, struct sdw_msg *msg, struct sdw_defer *defer); -enum sdw_command_response -cdns_reset_page_addr(struct sdw_bus *bus, unsigned int dev_num); - int cdns_bus_conf(struct sdw_bus *bus, struct sdw_bus_params *params); int cdns_set_sdw_stream(struct snd_soc_dai *dai, diff --git a/drivers/soundwire/dmi-quirks.c b/drivers/soundwire/dmi-quirks.c index 82061c1d9835..5db0a2443a1d 100644 --- a/drivers/soundwire/dmi-quirks.c +++ b/drivers/soundwire/dmi-quirks.c @@ -80,7 +80,7 @@ u64 sdw_dmi_override_adr(struct sdw_bus *bus, u64 addr) /* check if any address remap quirk applies */ dmi_id = dmi_first_match(adr_remap_quirk_table); if (dmi_id) { - struct adr_remap *map = dmi_id->driver_data; + struct adr_remap *map; for (map = dmi_id->driver_data; map->adr; map++) { if (map->adr == addr) { diff --git a/drivers/soundwire/generic_bandwidth_allocation.c b/drivers/soundwire/generic_bandwidth_allocation.c index 84d129587084..f7c66083a4dd 100644 --- a/drivers/soundwire/generic_bandwidth_allocation.c +++ b/drivers/soundwire/generic_bandwidth_allocation.c @@ -382,12 +382,18 @@ static int sdw_compute_bus_params(struct sdw_bus *bus) */ } - if (i == clk_values) + if (i == clk_values) { + dev_err(bus->dev, "%s: could not find clock value for bandwidth %d\n", + __func__, bus->params.bandwidth); return -EINVAL; + } ret = sdw_select_row_col(bus, curr_dr_freq); - if (ret < 0) + if (ret < 0) { + dev_err(bus->dev, "%s: could not find frame configuration for bus dr_freq %d\n", + __func__, curr_dr_freq); return -EINVAL; + } bus->params.curr_dr_freq = curr_dr_freq; return 0; @@ -404,10 +410,8 @@ int sdw_compute_params(struct sdw_bus *bus) /* Computes clock frequency, frame shape and frame frequency */ ret = sdw_compute_bus_params(bus); - if (ret < 0) { - dev_err(bus->dev, "Compute bus params failed: %d\n", ret); + if (ret < 0) return ret; - } /* Compute transport and port params */ ret = sdw_compute_port_params(bus); diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c index fd95f94630b1..c11e3d8cd308 100644 --- a/drivers/soundwire/intel.c +++ b/drivers/soundwire/intel.c @@ -11,7 +11,7 @@ #include <linux/module.h> #include <linux/interrupt.h> #include <linux/io.h> -#include <linux/platform_device.h> +#include <linux/auxiliary_bus.h> #include <sound/pcm_params.h> #include <linux/pm_runtime.h> #include <sound/soc.h> @@ -1327,11 +1327,14 @@ static int intel_init(struct sdw_intel *sdw) } /* - * probe and init + * probe and init (aux_dev_id argument is required by function prototype but not used) */ -static int intel_master_probe(struct platform_device *pdev) +static int intel_link_probe(struct auxiliary_device *auxdev, + const struct auxiliary_device_id *aux_dev_id) + { - struct device *dev = &pdev->dev; + struct device *dev = &auxdev->dev; + struct sdw_intel_link_dev *ldev = auxiliary_dev_to_sdw_intel_link_dev(auxdev); struct sdw_intel *sdw; struct sdw_cdns *cdns; struct sdw_bus *bus; @@ -1344,14 +1347,14 @@ static int intel_master_probe(struct platform_device *pdev) cdns = &sdw->cdns; bus = &cdns->bus; - sdw->instance = pdev->id; - sdw->link_res = dev_get_platdata(dev); + sdw->instance = auxdev->id; + sdw->link_res = &ldev->link_res; cdns->dev = dev; cdns->registers = sdw->link_res->registers; cdns->instance = sdw->instance; cdns->msg_count = 0; - bus->link_id = pdev->id; + bus->link_id = auxdev->id; sdw_cdns_probe(cdns); @@ -1384,10 +1387,10 @@ static int intel_master_probe(struct platform_device *pdev) return 0; } -int intel_master_startup(struct platform_device *pdev) +int intel_link_startup(struct auxiliary_device *auxdev) { struct sdw_cdns_stream_config config; - struct device *dev = &pdev->dev; + struct device *dev = &auxdev->dev; struct sdw_cdns *cdns = dev_get_drvdata(dev); struct sdw_intel *sdw = cdns_to_intel(cdns); struct sdw_bus *bus = &cdns->bus; @@ -1524,9 +1527,9 @@ err_init: return ret; } -static int intel_master_remove(struct platform_device *pdev) +static void intel_link_remove(struct auxiliary_device *auxdev) { - struct device *dev = &pdev->dev; + struct device *dev = &auxdev->dev; struct sdw_cdns *cdns = dev_get_drvdata(dev); struct sdw_intel *sdw = cdns_to_intel(cdns); struct sdw_bus *bus = &cdns->bus; @@ -1542,19 +1545,17 @@ static int intel_master_remove(struct platform_device *pdev) snd_soc_unregister_component(dev); } sdw_bus_master_delete(bus); - - return 0; } -int intel_master_process_wakeen_event(struct platform_device *pdev) +int intel_link_process_wakeen_event(struct auxiliary_device *auxdev) { - struct device *dev = &pdev->dev; + struct device *dev = &auxdev->dev; struct sdw_intel *sdw; struct sdw_bus *bus; void __iomem *shim; u16 wake_sts; - sdw = platform_get_drvdata(pdev); + sdw = dev_get_drvdata(dev); bus = &sdw->cdns.bus; if (bus->prop.hw_disabled) { @@ -1976,17 +1977,22 @@ static const struct dev_pm_ops intel_pm = { SET_RUNTIME_PM_OPS(intel_suspend_runtime, intel_resume_runtime, NULL) }; -static struct platform_driver sdw_intel_drv = { - .probe = intel_master_probe, - .remove = intel_master_remove, +static const struct auxiliary_device_id intel_link_id_table[] = { + { .name = "soundwire_intel.link" }, + {}, +}; +MODULE_DEVICE_TABLE(auxiliary, intel_link_id_table); + +static struct auxiliary_driver sdw_intel_drv = { + .probe = intel_link_probe, + .remove = intel_link_remove, .driver = { - .name = "intel-sdw", + /* auxiliary_driver_register() sets .name to be the modname */ .pm = &intel_pm, - } + }, + .id_table = intel_link_id_table }; - -module_platform_driver(sdw_intel_drv); +module_auxiliary_driver(sdw_intel_drv); MODULE_LICENSE("Dual BSD/GPL"); -MODULE_ALIAS("platform:intel-sdw"); -MODULE_DESCRIPTION("Intel Soundwire Master Driver"); +MODULE_DESCRIPTION("Intel Soundwire Link Driver"); diff --git a/drivers/soundwire/intel.h b/drivers/soundwire/intel.h index 06bac8ba14e9..0b47b148da3f 100644 --- a/drivers/soundwire/intel.h +++ b/drivers/soundwire/intel.h @@ -7,7 +7,6 @@ /** * struct sdw_intel_link_res - Soundwire Intel link resource structure, * typically populated by the controller driver. - * @pdev: platform_device * @mmio_base: mmio base of SoundWire registers * @registers: Link IO registers base * @shim: Audio shim pointer @@ -23,7 +22,6 @@ * @list: used to walk-through all masters exposed by the same controller */ struct sdw_intel_link_res { - struct platform_device *pdev; void __iomem *mmio_base; /* not strictly needed, useful for debug */ void __iomem *registers; void __iomem *shim; @@ -48,7 +46,15 @@ struct sdw_intel { #endif }; -int intel_master_startup(struct platform_device *pdev); -int intel_master_process_wakeen_event(struct platform_device *pdev); +int intel_link_startup(struct auxiliary_device *auxdev); +int intel_link_process_wakeen_event(struct auxiliary_device *auxdev); + +struct sdw_intel_link_dev { + struct auxiliary_device auxdev; + struct sdw_intel_link_res link_res; +}; + +#define auxiliary_dev_to_sdw_intel_link_dev(auxiliary_dev) \ + container_of(auxiliary_dev, struct sdw_intel_link_dev, auxdev) #endif /* __SDW_INTEL_LOCAL_H */ diff --git a/drivers/soundwire/intel_init.c b/drivers/soundwire/intel_init.c index 30ce95ec2d70..9e283bef53d2 100644 --- a/drivers/soundwire/intel_init.c +++ b/drivers/soundwire/intel_init.c @@ -12,7 +12,7 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> -#include <linux/platform_device.h> +#include <linux/auxiliary_bus.h> #include <linux/pm_runtime.h> #include <linux/soundwire/sdw_intel.h> #include "cadence_master.h" @@ -24,28 +24,108 @@ #define SDW_LINK_BASE 0x30000 #define SDW_LINK_SIZE 0x10000 +static void intel_link_dev_release(struct device *dev) +{ + struct auxiliary_device *auxdev = to_auxiliary_dev(dev); + struct sdw_intel_link_dev *ldev = auxiliary_dev_to_sdw_intel_link_dev(auxdev); + + kfree(ldev); +} + +/* alloc, init and add link devices */ +static struct sdw_intel_link_dev *intel_link_dev_register(struct sdw_intel_res *res, + struct sdw_intel_ctx *ctx, + struct fwnode_handle *fwnode, + const char *name, + int link_id) +{ + struct sdw_intel_link_dev *ldev; + struct sdw_intel_link_res *link; + struct auxiliary_device *auxdev; + int ret; + + ldev = kzalloc(sizeof(*ldev), GFP_KERNEL); + if (!ldev) + return ERR_PTR(-ENOMEM); + + auxdev = &ldev->auxdev; + auxdev->name = name; + auxdev->dev.parent = res->parent; + auxdev->dev.fwnode = fwnode; + auxdev->dev.release = intel_link_dev_release; + + /* we don't use an IDA since we already have a link ID */ + auxdev->id = link_id; + + /* + * keep a handle on the allocated memory, to be used in all other functions. + * Since the same pattern is used to skip links that are not enabled, there is + * no need to check if ctx->ldev[i] is NULL later on. + */ + ctx->ldev[link_id] = ldev; + + /* Add link information used in the driver probe */ + link = &ldev->link_res; + link->mmio_base = res->mmio_base; + link->registers = res->mmio_base + SDW_LINK_BASE + + (SDW_LINK_SIZE * link_id); + link->shim = res->mmio_base + SDW_SHIM_BASE; + link->alh = res->mmio_base + SDW_ALH_BASE; + + link->ops = res->ops; + link->dev = res->dev; + + link->clock_stop_quirks = res->clock_stop_quirks; + link->shim_lock = &ctx->shim_lock; + link->shim_mask = &ctx->shim_mask; + link->link_mask = ctx->link_mask; + + /* now follow the two-step init/add sequence */ + ret = auxiliary_device_init(auxdev); + if (ret < 0) { + dev_err(res->parent, "failed to initialize link dev %s link_id %d\n", + name, link_id); + kfree(ldev); + return ERR_PTR(ret); + } + + ret = auxiliary_device_add(&ldev->auxdev); + if (ret < 0) { + dev_err(res->parent, "failed to add link dev %s link_id %d\n", + ldev->auxdev.name, link_id); + /* ldev will be freed with the put_device() and .release sequence */ + auxiliary_device_uninit(&ldev->auxdev); + return ERR_PTR(ret); + } + + return ldev; +} + +static void intel_link_dev_unregister(struct sdw_intel_link_dev *ldev) +{ + auxiliary_device_delete(&ldev->auxdev); + auxiliary_device_uninit(&ldev->auxdev); +} + static int sdw_intel_cleanup(struct sdw_intel_ctx *ctx) { - struct sdw_intel_link_res *link = ctx->links; + struct sdw_intel_link_dev *ldev; u32 link_mask; int i; - if (!link) - return 0; - link_mask = ctx->link_mask; - for (i = 0; i < ctx->count; i++, link++) { + for (i = 0; i < ctx->count; i++) { if (!(link_mask & BIT(i))) continue; - if (link->pdev) { - pm_runtime_disable(&link->pdev->dev); - platform_device_unregister(link->pdev); - } + ldev = ctx->ldev[i]; - if (!link->clock_stop_quirks) - pm_runtime_put_noidle(link->dev); + pm_runtime_disable(&ldev->auxdev.dev); + if (!ldev->link_res.clock_stop_quirks) + pm_runtime_put_noidle(ldev->link_res.dev); + + intel_link_dev_unregister(ldev); } return 0; @@ -91,9 +171,8 @@ EXPORT_SYMBOL_NS(sdw_intel_thread, SOUNDWIRE_INTEL_INIT); static struct sdw_intel_ctx *sdw_intel_probe_controller(struct sdw_intel_res *res) { - struct platform_device_info pdevinfo; - struct platform_device *pdev; struct sdw_intel_link_res *link; + struct sdw_intel_link_dev *ldev; struct sdw_intel_ctx *ctx; struct acpi_device *adev; struct sdw_slave *slave; @@ -116,67 +195,60 @@ static struct sdw_intel_ctx count = res->count; dev_dbg(&adev->dev, "Creating %d SDW Link devices\n", count); - ctx = devm_kzalloc(&adev->dev, sizeof(*ctx), GFP_KERNEL); + /* + * we need to alloc/free memory manually and can't use devm: + * this routine may be called from a workqueue, and not from + * the parent .probe. + * If devm_ was used, the memory might never be freed on errors. + */ + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return NULL; ctx->count = count; - ctx->links = devm_kcalloc(&adev->dev, ctx->count, - sizeof(*ctx->links), GFP_KERNEL); - if (!ctx->links) + + /* + * allocate the array of pointers. The link-specific data is allocated + * as part of the first loop below and released with the auxiliary_device_uninit(). + * If some links are disabled, the link pointer will remain NULL. Given that the + * number of links is small, this is simpler than using a list to keep track of links. + */ + ctx->ldev = kcalloc(ctx->count, sizeof(*ctx->ldev), GFP_KERNEL); + if (!ctx->ldev) { + kfree(ctx); return NULL; + } - ctx->count = count; ctx->mmio_base = res->mmio_base; ctx->link_mask = res->link_mask; ctx->handle = res->handle; mutex_init(&ctx->shim_lock); - link = ctx->links; link_mask = ctx->link_mask; INIT_LIST_HEAD(&ctx->link_list); - /* Create SDW Master devices */ - for (i = 0; i < count; i++, link++) { - if (!(link_mask & BIT(i))) { - dev_dbg(&adev->dev, - "Link %d masked, will not be enabled\n", i); + for (i = 0; i < count; i++) { + if (!(link_mask & BIT(i))) continue; - } - link->mmio_base = res->mmio_base; - link->registers = res->mmio_base + SDW_LINK_BASE - + (SDW_LINK_SIZE * i); - link->shim = res->mmio_base + SDW_SHIM_BASE; - link->alh = res->mmio_base + SDW_ALH_BASE; - - link->ops = res->ops; - link->dev = res->dev; - - link->clock_stop_quirks = res->clock_stop_quirks; - link->shim_lock = &ctx->shim_lock; - link->shim_mask = &ctx->shim_mask; - link->link_mask = link_mask; - - memset(&pdevinfo, 0, sizeof(pdevinfo)); - - pdevinfo.parent = res->parent; - pdevinfo.name = "intel-sdw"; - pdevinfo.id = i; - pdevinfo.fwnode = acpi_fwnode_handle(adev); - pdevinfo.data = link; - pdevinfo.size_data = sizeof(*link); - - pdev = platform_device_register_full(&pdevinfo); - if (IS_ERR(pdev)) { - dev_err(&adev->dev, - "platform device creation failed: %ld\n", - PTR_ERR(pdev)); + /* + * init and add a device for each link + * + * The name of the device will be soundwire_intel.link.[i], + * with the "soundwire_intel" module prefix automatically added + * by the auxiliary bus core. + */ + ldev = intel_link_dev_register(res, + ctx, + acpi_fwnode_handle(adev), + "link", + i); + if (IS_ERR(ldev)) goto err; - } - link->pdev = pdev; - link->cdns = platform_get_drvdata(pdev); + + link = &ldev->link_res; + link->cdns = dev_get_drvdata(&ldev->auxdev.dev); if (!link->cdns) { dev_err(&adev->dev, "failed to get link->cdns\n"); @@ -194,8 +266,7 @@ static struct sdw_intel_ctx num_slaves++; } - ctx->ids = devm_kcalloc(&adev->dev, num_slaves, - sizeof(*ctx->ids), GFP_KERNEL); + ctx->ids = kcalloc(num_slaves, sizeof(*ctx->ids), GFP_KERNEL); if (!ctx->ids) goto err; @@ -213,8 +284,14 @@ static struct sdw_intel_ctx return ctx; err: - ctx->count = i; - sdw_intel_cleanup(ctx); + while (i--) { + if (!(link_mask & BIT(i))) + continue; + ldev = ctx->ldev[i]; + intel_link_dev_unregister(ldev); + } + kfree(ctx->ldev); + kfree(ctx); return NULL; } @@ -222,7 +299,7 @@ static int sdw_intel_startup_controller(struct sdw_intel_ctx *ctx) { struct acpi_device *adev; - struct sdw_intel_link_res *link; + struct sdw_intel_link_dev *ldev; u32 caps; u32 link_mask; int i; @@ -241,27 +318,28 @@ sdw_intel_startup_controller(struct sdw_intel_ctx *ctx) return -EINVAL; } - if (!ctx->links) + if (!ctx->ldev) return -EINVAL; - link = ctx->links; link_mask = ctx->link_mask; /* Startup SDW Master devices */ - for (i = 0; i < ctx->count; i++, link++) { + for (i = 0; i < ctx->count; i++) { if (!(link_mask & BIT(i))) continue; - intel_master_startup(link->pdev); + ldev = ctx->ldev[i]; + + intel_link_startup(&ldev->auxdev); - if (!link->clock_stop_quirks) { + if (!ldev->link_res.clock_stop_quirks) { /* * we need to prevent the parent PCI device * from entering pm_runtime suspend, so that * power rails to the SoundWire IP are not * turned off. */ - pm_runtime_get_noresume(link->dev); + pm_runtime_get_noresume(ldev->link_res.dev); } } @@ -272,8 +350,8 @@ sdw_intel_startup_controller(struct sdw_intel_ctx *ctx) * sdw_intel_probe() - SoundWire Intel probe routine * @res: resource data * - * This registers a platform device for each Master handled by the controller, - * and SoundWire Master and Slave devices will be created by the platform + * This registers an auxiliary device for each Master handled by the controller, + * and SoundWire Master and Slave devices will be created by the auxiliary * device probe. All the information necessary is stored in the context, and * the res argument pointer can be freed after this step. * This function will be called after sdw_intel_acpi_scan() by SOF probe. @@ -306,27 +384,31 @@ EXPORT_SYMBOL_NS(sdw_intel_startup, SOUNDWIRE_INTEL_INIT); void sdw_intel_exit(struct sdw_intel_ctx *ctx) { sdw_intel_cleanup(ctx); + kfree(ctx->ids); + kfree(ctx->ldev); + kfree(ctx); } EXPORT_SYMBOL_NS(sdw_intel_exit, SOUNDWIRE_INTEL_INIT); void sdw_intel_process_wakeen_event(struct sdw_intel_ctx *ctx) { - struct sdw_intel_link_res *link; + struct sdw_intel_link_dev *ldev; u32 link_mask; int i; - if (!ctx->links) + if (!ctx->ldev) return; - link = ctx->links; link_mask = ctx->link_mask; /* Startup SDW Master devices */ - for (i = 0; i < ctx->count; i++, link++) { + for (i = 0; i < ctx->count; i++) { if (!(link_mask & BIT(i))) continue; - intel_master_process_wakeen_event(link->pdev); + ldev = ctx->ldev[i]; + + intel_link_process_wakeen_event(&ldev->auxdev); } } EXPORT_SYMBOL_NS(sdw_intel_process_wakeen_event, SOUNDWIRE_INTEL_INIT); diff --git a/drivers/soundwire/slave.c b/drivers/soundwire/slave.c index 0eed38a79c6d..669d7573320b 100644 --- a/drivers/soundwire/slave.c +++ b/drivers/soundwire/slave.c @@ -39,12 +39,12 @@ int sdw_slave_add(struct sdw_bus *bus, if (id->unique_id == SDW_IGNORED_UNIQUE_ID) { /* name shall be sdw:link:mfg:part:class */ - dev_set_name(&slave->dev, "sdw:%x:%x:%x:%x", + dev_set_name(&slave->dev, "sdw:%01x:%04x:%04x:%02x", bus->link_id, id->mfg_id, id->part_id, id->class_id); } else { /* name shall be sdw:link:mfg:part:class:unique */ - dev_set_name(&slave->dev, "sdw:%x:%x:%x:%x:%x", + dev_set_name(&slave->dev, "sdw:%01x:%04x:%04x:%02x:%01x", bus->link_id, id->mfg_id, id->part_id, id->class_id, id->unique_id); } diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index 1eaedaaba094..1a18308f4ef4 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -422,7 +422,6 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus, struct completion *port_ready; struct sdw_dpn_prop *dpn_prop; struct sdw_prepare_ch prep_ch; - unsigned int time_left; bool intr = false; int ret = 0, val; u32 addr; @@ -479,15 +478,15 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus, /* Wait for completion on port ready */ port_ready = &s_rt->slave->port_ready[prep_ch.num]; - time_left = wait_for_completion_timeout(port_ready, - msecs_to_jiffies(dpn_prop->ch_prep_timeout)); + wait_for_completion_timeout(port_ready, + msecs_to_jiffies(dpn_prop->ch_prep_timeout)); val = sdw_read(s_rt->slave, SDW_DPN_PREPARESTATUS(p_rt->num)); - val &= p_rt->ch_mask; - if (!time_left || val) { + if ((val < 0) || (val & p_rt->ch_mask)) { + ret = (val < 0) ? val : -ETIMEDOUT; dev_err(&s_rt->slave->dev, - "Chn prep failed for port:%d\n", prep_ch.num); - return -ETIMEDOUT; + "Chn prep failed for port %d: %d\n", prep_ch.num, ret); + return ret; } } diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig index a53bad541f1a..2874b6c26028 100644 --- a/drivers/spmi/Kconfig +++ b/drivers/spmi/Kconfig @@ -11,6 +11,15 @@ menuconfig SPMI if SPMI +config SPMI_HISI3670 + tristate "Hisilicon 3670 SPMI Controller" + select IRQ_DOMAIN_HIERARCHY + depends on HAS_IOMEM + help + If you say yes to this option, support will be included for the + built-in SPMI PMIC Arbiter interface on Hisilicon 3670 + processors. + config SPMI_MSM_PMIC_ARB tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)" select IRQ_DOMAIN_HIERARCHY diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile index 55a94cadeffe..6e092e6f290c 100644 --- a/drivers/spmi/Makefile +++ b/drivers/spmi/Makefile @@ -4,4 +4,5 @@ # obj-$(CONFIG_SPMI) += spmi.o +obj-$(CONFIG_SPMI_HISI3670) += hisi-spmi-controller.o obj-$(CONFIG_SPMI_MSM_PMIC_ARB) += spmi-pmic-arb.o diff --git a/drivers/staging/hikey9xx/hisi-spmi-controller.c b/drivers/spmi/hisi-spmi-controller.c index 0d42bc65f39b..5bd23262abd6 100644 --- a/drivers/staging/hikey9xx/hisi-spmi-controller.c +++ b/drivers/spmi/hisi-spmi-controller.c @@ -290,7 +290,7 @@ static int spmi_controller_probe(struct platform_device *pdev) goto err_put_controller; } - ret = of_property_read_u32(pdev->dev.of_node, "spmi-channel", + ret = of_property_read_u32(pdev->dev.of_node, "hisilicon,spmi-channel", &spmi_controller->channel); if (ret) { dev_err(&pdev->dev, "can not get channel\n"); diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index b7ae5bdc4eb5..c8eaae6412bb 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -98,8 +98,6 @@ source "drivers/staging/axis-fifo/Kconfig" source "drivers/staging/fieldbus/Kconfig" -source "drivers/staging/kpc2000/Kconfig" - source "drivers/staging/qlge/Kconfig" source "drivers/staging/wfx/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 075c979bfe7c..818b6f964369 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -39,7 +39,6 @@ obj-$(CONFIG_DMA_RALINK) += ralink-gdma/ obj-$(CONFIG_SOC_MT7621) += mt7621-dts/ obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/ obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ -obj-$(CONFIG_KPC2000) += kpc2000/ obj-$(CONFIG_QLGE) += qlge/ obj-$(CONFIG_WFX) += wfx/ obj-y += hikey9xx/ diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index d66a64e42273..ddbde3f8430e 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -179,6 +179,7 @@ static inline void lru_del(struct ashmem_range *range) * @purged: Initial purge status (ASMEM_NOT_PURGED or ASHMEM_WAS_PURGED) * @start: The starting page (inclusive) * @end: The ending page (inclusive) + * @new_range: The placeholder for the new range * * This function is protected by ashmem_mutex. */ @@ -894,6 +895,8 @@ static void ashmem_show_fdinfo(struct seq_file *m, struct file *file) seq_printf(m, "name:\t%s\n", asma->name + ASHMEM_NAME_PREFIX_LEN); + seq_printf(m, "size:\t%zu\n", asma->size); + mutex_unlock(&ashmem_mutex); } #endif diff --git a/drivers/staging/axis-fifo/axis-fifo.c b/drivers/staging/axis-fifo/axis-fifo.c index ed9281089738..b23eabb863d1 100644 --- a/drivers/staging/axis-fifo/axis-fifo.c +++ b/drivers/staging/axis-fifo/axis-fifo.c @@ -337,11 +337,11 @@ static void reset_ip_core(struct axis_fifo *fifo) } /** - * axis_fifo_write() - Read a packet from AXIS-FIFO character device. - * @f Open file. - * @buf User space buffer to read to. - * @len User space buffer length. - * @off Buffer offset. + * axis_fifo_read() - Read a packet from AXIS-FIFO character device. + * @f: Open file. + * @buf: User space buffer to read to. + * @len: User space buffer length. + * @off: Buffer offset. * * As defined by the device's documentation, we need to check the device's * occupancy before reading the length register and then the data. All these @@ -460,10 +460,10 @@ end_unlock: /** * axis_fifo_write() - Write buffer to AXIS-FIFO character device. - * @f Open file. - * @buf User space buffer to write to the device. - * @len User space buffer length. - * @off Buffer offset. + * @f: Open file. + * @buf: User space buffer to write to the device. + * @len: User space buffer length. + * @off: Buffer offset. * * As defined by the device's documentation, we need to write to the device's * data buffer then to the device's packet length register atomically. Also, diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index ecc5c9da9027..b6abd3770e81 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -1073,9 +1073,8 @@ static int _nbu2ss_epn_in_pio(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep, i_word_length = length / sizeof(u32); if (i_word_length > 0) { for (i = 0; i < i_word_length; i++) { - _nbu2ss_writel( - &preg->EP_REGS[ep->epnum - 1].EP_WRITE, - p_buf_32->dw); + _nbu2ss_writel(&preg->EP_REGS[ep->epnum - 1].EP_WRITE, + p_buf_32->dw); p_buf_32++; } @@ -1225,8 +1224,7 @@ static void _nbu2ss_restert_transfer(struct nbu2ss_ep *ep) return; if (ep->epnum > 0) { - length = _nbu2ss_readl( - &ep->udc->p_regs->EP_REGS[ep->epnum - 1].EP_LEN_DCNT); + length = _nbu2ss_readl(&ep->udc->p_regs->EP_REGS[ep->epnum - 1].EP_LEN_DCNT); length &= EPN_LDATA; if (length < ep->ep.maxpacket) @@ -1462,8 +1460,7 @@ static void _nbu2ss_epn_set_stall(struct nbu2ss_udc *udc, for (limit_cnt = 0 ; limit_cnt < IN_DATA_EMPTY_COUNT ; limit_cnt++) { - regdata = _nbu2ss_readl( - &preg->EP_REGS[ep->epnum - 1].EP_STATUS); + regdata = _nbu2ss_readl(&preg->EP_REGS[ep->epnum - 1].EP_STATUS); if ((regdata & EPN_IN_DATA) == 0) break; diff --git a/drivers/staging/fbtft/TODO b/drivers/staging/fbtft/TODO index a9f4802bb6be..e72a08bf221c 100644 --- a/drivers/staging/fbtft/TODO +++ b/drivers/staging/fbtft/TODO @@ -1,8 +1,3 @@ -* convert all uses of the old GPIO API from <linux/gpio.h> to the - GPIO descriptor API in <linux/gpio/consumer.h> and look up GPIO - lines from device tree, ACPI or board files, board files should - use <linux/gpio/machine.h> - * convert all these over to drm_simple_display_pipe and submit for inclusion into the DRM subsystem under drivers/gpu/drm - fbdev doesn't take any new drivers anymore. diff --git a/drivers/staging/fbtft/fb_agm1264k-fl.c b/drivers/staging/fbtft/fb_agm1264k-fl.c index eeeeec97ad27..207d578547cd 100644 --- a/drivers/staging/fbtft/fb_agm1264k-fl.c +++ b/drivers/staging/fbtft/fb_agm1264k-fl.c @@ -77,19 +77,6 @@ static int init_display(struct fbtft_par *par) return 0; } -static void reset(struct fbtft_par *par) -{ - if (!par->gpio.reset) - return; - - dev_dbg(par->info->device, "%s()\n", __func__); - - gpiod_set_value(par->gpio.reset, 0); - udelay(20); - gpiod_set_value(par->gpio.reset, 1); - mdelay(120); -} - /* Check if all necessary GPIOS defined */ static int verify_gpios(struct fbtft_par *par) { @@ -194,12 +181,12 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...) /* select chip */ if (*buf) { /* cs1 */ - gpiod_set_value(par->CS0, 1); - gpiod_set_value(par->CS1, 0); - } else { - /* cs0 */ gpiod_set_value(par->CS0, 0); gpiod_set_value(par->CS1, 1); + } else { + /* cs0 */ + gpiod_set_value(par->CS0, 1); + gpiod_set_value(par->CS1, 0); } gpiod_set_value(par->RS, 0); /* RS->0 (command mode) */ @@ -397,8 +384,8 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) } kfree(convert_buf); - gpiod_set_value(par->CS0, 1); - gpiod_set_value(par->CS1, 1); + gpiod_set_value(par->CS0, 0); + gpiod_set_value(par->CS1, 0); return ret; } @@ -419,10 +406,10 @@ static int write(struct fbtft_par *par, void *buf, size_t len) for (i = 0; i < 8; ++i) gpiod_set_value(par->gpio.db[i], data & (1 << i)); /* set E */ - gpiod_set_value(par->EPIN, 1); + gpiod_set_value(par->EPIN, 0); udelay(5); /* unset E - write */ - gpiod_set_value(par->EPIN, 0); + gpiod_set_value(par->EPIN, 1); udelay(1); } @@ -439,7 +426,6 @@ static struct fbtft_display display = { .set_addr_win = set_addr_win, .verify_gpios = verify_gpios, .request_gpios_match = request_gpios_match, - .reset = reset, .write = write, .write_register = write_reg8_bus8, .write_vmem = write_vmem, diff --git a/drivers/staging/fbtft/fb_bd663474.c b/drivers/staging/fbtft/fb_bd663474.c index e2c7646588f8..1629c2c440a9 100644 --- a/drivers/staging/fbtft/fb_bd663474.c +++ b/drivers/staging/fbtft/fb_bd663474.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/delay.h> #include "fbtft.h" @@ -24,9 +23,6 @@ static int init_display(struct fbtft_par *par) { - if (par->gpio.cs) - gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ - par->fbtftops.reset(par); /* Initialization sequence from Lib_UTFT */ diff --git a/drivers/staging/fbtft/fb_hx8347d.c b/drivers/staging/fbtft/fb_hx8347d.c index 37eaf0862c5b..a9b72a8b42b5 100644 --- a/drivers/staging/fbtft/fb_hx8347d.c +++ b/drivers/staging/fbtft/fb_hx8347d.c @@ -68,9 +68,6 @@ static int init_display(struct fbtft_par *par) mdelay(40); write_reg(par, 0x28, 0x3C); - /* orientation */ - write_reg(par, 0x16, 0x60 | (par->bgr << 3)); - return 0; } @@ -87,6 +84,31 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) write_reg(par, 0x22); } +#define MEM_Y BIT(7) /* MY row address order */ +#define MEM_X BIT(6) /* MX column address order */ +#define MEM_V BIT(5) /* MV row / column exchange */ +#define MEM_L BIT(4) /* ML vertical refresh order */ +#define MEM_BGR (3) /* RGB-BGR Order */ +static int set_var(struct fbtft_par *par) +{ + switch (par->info->var.rotate) { + case 0: + write_reg(par, 0x16, MEM_V | MEM_X | (par->bgr << MEM_BGR)); + break; + case 270: + write_reg(par, 0x16, par->bgr << MEM_BGR); + break; + case 180: + write_reg(par, 0x16, MEM_V | MEM_Y | (par->bgr << MEM_BGR)); + break; + case 90: + write_reg(par, 0x16, MEM_X | MEM_Y | (par->bgr << MEM_BGR)); + break; + } + + return 0; +} + /* * Gamma string format: * VRP0 VRP1 VRP2 VRP3 VRP4 VRP5 PRP0 PRP1 PKP0 PKP1 PKP2 PKP3 PKP4 CGM @@ -144,6 +166,7 @@ static struct fbtft_display display = { .fbtftops = { .init_display = init_display, .set_addr_win = set_addr_win, + .set_var = set_var, .set_gamma = set_gamma, }, }; diff --git a/drivers/staging/fbtft/fb_ili9163.c b/drivers/staging/fbtft/fb_ili9163.c index 05648c3ffe47..6582a2c90aaf 100644 --- a/drivers/staging/fbtft/fb_ili9163.c +++ b/drivers/staging/fbtft/fb_ili9163.c @@ -11,7 +11,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/delay.h> #include <video/mipi_display.h> @@ -77,9 +76,6 @@ static int init_display(struct fbtft_par *par) { par->fbtftops.reset(par); - if (par->gpio.cs) - gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ - write_reg(par, MIPI_DCS_SOFT_RESET); /* software reset */ mdelay(500); write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE); /* exit sleep */ diff --git a/drivers/staging/fbtft/fb_ili9320.c b/drivers/staging/fbtft/fb_ili9320.c index f2e72d14431d..0be7c2d51548 100644 --- a/drivers/staging/fbtft/fb_ili9320.c +++ b/drivers/staging/fbtft/fb_ili9320.c @@ -8,7 +8,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/spi/spi.h> #include <linux/delay.h> @@ -22,11 +21,10 @@ static unsigned int read_devicecode(struct fbtft_par *par) { - int ret; u8 rxbuf[8] = {0, }; write_reg(par, 0x0000); - ret = par->fbtftops.read(par, rxbuf, 4); + par->fbtftops.read(par, rxbuf, 4); return (rxbuf[2] << 8) | rxbuf[3]; } diff --git a/drivers/staging/fbtft/fb_ili9325.c b/drivers/staging/fbtft/fb_ili9325.c index c9aa4cb43123..16d3b17ca279 100644 --- a/drivers/staging/fbtft/fb_ili9325.c +++ b/drivers/staging/fbtft/fb_ili9325.c @@ -10,7 +10,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/delay.h> #include "fbtft.h" @@ -85,9 +84,6 @@ static int init_display(struct fbtft_par *par) { par->fbtftops.reset(par); - if (par->gpio.cs) - gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ - bt &= 0x07; vc &= 0x07; vrh &= 0x0f; diff --git a/drivers/staging/fbtft/fb_ili9340.c b/drivers/staging/fbtft/fb_ili9340.c index 415183c7054a..704236bcaf3f 100644 --- a/drivers/staging/fbtft/fb_ili9340.c +++ b/drivers/staging/fbtft/fb_ili9340.c @@ -8,7 +8,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/delay.h> #include <video/mipi_display.h> diff --git a/drivers/staging/fbtft/fb_s6d1121.c b/drivers/staging/fbtft/fb_s6d1121.c index 8c7de3290343..62f27172f844 100644 --- a/drivers/staging/fbtft/fb_s6d1121.c +++ b/drivers/staging/fbtft/fb_s6d1121.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/delay.h> #include "fbtft.h" @@ -29,9 +28,6 @@ static int init_display(struct fbtft_par *par) { par->fbtftops.reset(par); - if (par->gpio.cs) - gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ - /* Initialization sequence from Lib_UTFT */ write_reg(par, 0x0011, 0x2004); diff --git a/drivers/staging/fbtft/fb_sh1106.c b/drivers/staging/fbtft/fb_sh1106.c index 6f7249493ea3..7b9ab39e1c1a 100644 --- a/drivers/staging/fbtft/fb_sh1106.c +++ b/drivers/staging/fbtft/fb_sh1106.c @@ -9,7 +9,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/delay.h> #include "fbtft.h" diff --git a/drivers/staging/fbtft/fb_ssd1289.c b/drivers/staging/fbtft/fb_ssd1289.c index 7a3fe022cc69..f27bab38b3ec 100644 --- a/drivers/staging/fbtft/fb_ssd1289.c +++ b/drivers/staging/fbtft/fb_ssd1289.c @@ -10,7 +10,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include "fbtft.h" @@ -28,9 +27,6 @@ static int init_display(struct fbtft_par *par) { par->fbtftops.reset(par); - if (par->gpio.cs) - gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ - write_reg(par, 0x00, 0x0001); write_reg(par, 0x03, 0xA8A4); write_reg(par, 0x0C, 0x0000); diff --git a/drivers/staging/fbtft/fb_ssd1325.c b/drivers/staging/fbtft/fb_ssd1325.c index 8a3140d41d8b..796a2ac3e194 100644 --- a/drivers/staging/fbtft/fb_ssd1325.c +++ b/drivers/staging/fbtft/fb_ssd1325.c @@ -35,8 +35,6 @@ static int init_display(struct fbtft_par *par) { par->fbtftops.reset(par); - gpiod_set_value(par->gpio.cs, 0); - write_reg(par, 0xb3); write_reg(par, 0xf0); write_reg(par, 0xae); diff --git a/drivers/staging/fbtft/fb_ssd1331.c b/drivers/staging/fbtft/fb_ssd1331.c index 37622c9462aa..ec5eced7f8cb 100644 --- a/drivers/staging/fbtft/fb_ssd1331.c +++ b/drivers/staging/fbtft/fb_ssd1331.c @@ -81,8 +81,7 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...) va_start(args, len); *buf = (u8)va_arg(args, unsigned int); - if (par->gpio.dc) - gpiod_set_value(par->gpio.dc, 0); + gpiod_set_value(par->gpio.dc, 0); ret = par->fbtftops.write(par, par->buf, sizeof(u8)); if (ret < 0) { va_end(args); @@ -104,8 +103,7 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...) return; } } - if (par->gpio.dc) - gpiod_set_value(par->gpio.dc, 1); + gpiod_set_value(par->gpio.dc, 1); va_end(args); } diff --git a/drivers/staging/fbtft/fb_ssd1351.c b/drivers/staging/fbtft/fb_ssd1351.c index 900b28d826b2..cf263a58a148 100644 --- a/drivers/staging/fbtft/fb_ssd1351.c +++ b/drivers/staging/fbtft/fb_ssd1351.c @@ -2,7 +2,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/spi/spi.h> #include <linux/delay.h> diff --git a/drivers/staging/fbtft/fb_upd161704.c b/drivers/staging/fbtft/fb_upd161704.c index c77832ae5e5b..c680160d6380 100644 --- a/drivers/staging/fbtft/fb_upd161704.c +++ b/drivers/staging/fbtft/fb_upd161704.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/delay.h> #include "fbtft.h" @@ -26,9 +25,6 @@ static int init_display(struct fbtft_par *par) { par->fbtftops.reset(par); - if (par->gpio.cs) - gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ - /* Initialization sequence from Lib_UTFT */ /* register reset */ diff --git a/drivers/staging/fbtft/fb_watterott.c b/drivers/staging/fbtft/fb_watterott.c index 76b25df376b8..a57e1f4feef3 100644 --- a/drivers/staging/fbtft/fb_watterott.c +++ b/drivers/staging/fbtft/fb_watterott.c @@ -8,7 +8,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/delay.h> #include "fbtft.h" diff --git a/drivers/staging/fbtft/fbtft-bus.c b/drivers/staging/fbtft/fbtft-bus.c index 63c65dd67b17..3d422bc11641 100644 --- a/drivers/staging/fbtft/fbtft-bus.c +++ b/drivers/staging/fbtft/fbtft-bus.c @@ -135,8 +135,7 @@ int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len) remain = len / 2; vmem16 = (u16 *)(par->info->screen_buffer + offset); - if (par->gpio.dc) - gpiod_set_value(par->gpio.dc, 1); + gpiod_set_value(par->gpio.dc, 1); /* non buffered write */ if (!par->txbuf.buf) diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index 4f362dad4436..3723269890d5 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -38,8 +38,7 @@ int fbtft_write_buf_dc(struct fbtft_par *par, void *buf, size_t len, int dc) { int ret; - if (par->gpio.dc) - gpiod_set_value(par->gpio.dc, dc); + gpiod_set_value(par->gpio.dc, dc); ret = par->fbtftops.write(par, buf, len); if (ret < 0) @@ -76,20 +75,16 @@ static int fbtft_request_one_gpio(struct fbtft_par *par, struct gpio_desc **gpiop) { struct device *dev = par->info->device; - int ret = 0; *gpiop = devm_gpiod_get_index_optional(dev, name, index, - GPIOD_OUT_HIGH); - if (IS_ERR(*gpiop)) { - ret = PTR_ERR(*gpiop); - dev_err(dev, - "Failed to request %s GPIO: %d\n", name, ret); - return ret; - } + GPIOD_OUT_LOW); + if (IS_ERR(*gpiop)) + return dev_err_probe(dev, PTR_ERR(*gpiop), "Failed to request %s GPIO\n", name); + fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' GPIO\n", __func__, name); - return ret; + return 0; } static int fbtft_request_gpios(struct fbtft_par *par) @@ -226,11 +221,15 @@ static void fbtft_reset(struct fbtft_par *par) { if (!par->gpio.reset) return; + fbtft_par_dbg(DEBUG_RESET, par, "%s()\n", __func__); + gpiod_set_value_cansleep(par->gpio.reset, 1); usleep_range(20, 40); gpiod_set_value_cansleep(par->gpio.reset, 0); msleep(120); + + gpiod_set_value_cansleep(par->gpio.cs, 1); /* Activate chip */ } static void fbtft_update_display(struct fbtft_par *par, unsigned int start_line, @@ -922,8 +921,6 @@ static int fbtft_init_display_from_property(struct fbtft_par *par) goto out_free; par->fbtftops.reset(par); - if (par->gpio.cs) - gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ index = -1; val = values[++index]; @@ -1018,8 +1015,6 @@ int fbtft_init_display(struct fbtft_par *par) } par->fbtftops.reset(par); - if (par->gpio.cs) - gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ i = 0; while (i < FBTFT_MAX_INIT_SEQUENCE) { diff --git a/drivers/staging/fbtft/fbtft-io.c b/drivers/staging/fbtft/fbtft-io.c index 0863d257d762..de1904a443c2 100644 --- a/drivers/staging/fbtft/fbtft-io.c +++ b/drivers/staging/fbtft/fbtft-io.c @@ -142,12 +142,12 @@ int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len) data = *(u8 *)buf; /* Start writing by pulling down /WR */ - gpiod_set_value(par->gpio.wr, 0); + gpiod_set_value(par->gpio.wr, 1); /* Set data */ #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO if (data == prev_data) { - gpiod_set_value(par->gpio.wr, 0); /* used as delay */ + gpiod_set_value(par->gpio.wr, 1); /* used as delay */ } else { for (i = 0; i < 8; i++) { if ((data & 1) != (prev_data & 1)) @@ -165,7 +165,7 @@ int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len) #endif /* Pullup /WR */ - gpiod_set_value(par->gpio.wr, 1); + gpiod_set_value(par->gpio.wr, 0); #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO prev_data = *(u8 *)buf; @@ -192,12 +192,12 @@ int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len) data = *(u16 *)buf; /* Start writing by pulling down /WR */ - gpiod_set_value(par->gpio.wr, 0); + gpiod_set_value(par->gpio.wr, 1); /* Set data */ #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO if (data == prev_data) { - gpiod_set_value(par->gpio.wr, 0); /* used as delay */ + gpiod_set_value(par->gpio.wr, 1); /* used as delay */ } else { for (i = 0; i < 16; i++) { if ((data & 1) != (prev_data & 1)) @@ -215,7 +215,7 @@ int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len) #endif /* Pullup /WR */ - gpiod_set_value(par->gpio.wr, 1); + gpiod_set_value(par->gpio.wr, 0); #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO prev_data = *(u16 *)buf; diff --git a/drivers/staging/fieldbus/anybuss/anybuss-client.h b/drivers/staging/fieldbus/anybuss/anybuss-client.h index 8ee1f1baccf1..a219688006fe 100644 --- a/drivers/staging/fieldbus/anybuss/anybuss-client.h +++ b/drivers/staging/fieldbus/anybuss/anybuss-client.h @@ -32,7 +32,7 @@ struct anybuss_client { struct anybuss_client_driver { struct device_driver driver; int (*probe)(struct anybuss_client *adev); - int (*remove)(struct anybuss_client *adev); + void (*remove)(struct anybuss_client *adev); u16 anybus_id; }; diff --git a/drivers/staging/fieldbus/anybuss/hms-profinet.c b/drivers/staging/fieldbus/anybuss/hms-profinet.c index eca7d97b8e85..e691736a53f1 100644 --- a/drivers/staging/fieldbus/anybuss/hms-profinet.c +++ b/drivers/staging/fieldbus/anybuss/hms-profinet.c @@ -190,12 +190,11 @@ static int profinet_probe(struct anybuss_client *client) return 0; } -static int profinet_remove(struct anybuss_client *client) +static void profinet_remove(struct anybuss_client *client) { struct profi_priv *priv = anybuss_get_drvdata(client); fieldbus_dev_unregister(&priv->fbdev); - return 0; } static struct anybuss_client_driver profinet_driver = { diff --git a/drivers/staging/fieldbus/anybuss/host.c b/drivers/staging/fieldbus/anybuss/host.c index c97df91124a4..0f730efe9a6d 100644 --- a/drivers/staging/fieldbus/anybuss/host.c +++ b/drivers/staging/fieldbus/anybuss/host.c @@ -1183,8 +1183,6 @@ static int anybus_bus_probe(struct device *dev) struct anybuss_client *adev = to_anybuss_client(dev); - if (!adrv->probe) - return -ENODEV; return adrv->probe(adev); } @@ -1194,7 +1192,8 @@ static int anybus_bus_remove(struct device *dev) to_anybuss_client_driver(dev->driver); if (adrv->remove) - return adrv->remove(to_anybuss_client(dev)); + adrv->remove(to_anybuss_client(dev)); + return 0; } @@ -1207,6 +1206,9 @@ static struct bus_type anybus_bus = { int anybuss_client_driver_register(struct anybuss_client_driver *drv) { + if (!drv->probe) + return -ENODEV; + drv->driver.bus = &anybus_bus; return driver_register(&drv->driver); } diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c index 1ee6382cafc4..38a280e876c2 100644 --- a/drivers/staging/fwserial/fwserial.c +++ b/drivers/staging/fwserial/fwserial.c @@ -45,14 +45,14 @@ module_param_named(loop, create_loop_dev, bool, 0644); */ #define WAKEUP_CHARS 256 -/** +/* * fwserial_list: list of every fw_serial created for each fw_card * See discussion in fwserial_probe. */ static LIST_HEAD(fwserial_list); static DEFINE_MUTEX(fwserial_list_mutex); -/** +/* * port_table: array of tty ports allocated to each fw_card * * tty ports are allocated during probe when an fw_serial is first @@ -284,7 +284,7 @@ static void fwtty_restart_tx(struct fwtty_port *port) spin_unlock_bh(&port->lock); } -/** +/* * fwtty_update_port_status - decodes & dispatches line status changes * * Note: in loopback, the port->lock is being held. Only use functions that @@ -375,7 +375,7 @@ static void fwtty_update_port_status(struct fwtty_port *port, wake_up_interruptible(&port->port.delta_msr_wait); } -/** +/* * __fwtty_port_line_status - generate 'line status' for indicated port * * This function returns a remote 'MSR' state based on the local 'MCR' state, @@ -403,7 +403,7 @@ static unsigned int __fwtty_port_line_status(struct fwtty_port *port) return status; } -/** +/* * __fwtty_write_port_status - send the port line status to peer * * Note: caller must be holding the port lock. @@ -426,7 +426,7 @@ static int __fwtty_write_port_status(struct fwtty_port *port) return err; } -/** +/* * fwtty_write_port_status - same as above but locked by port lock */ static int fwtty_write_port_status(struct fwtty_port *port) @@ -462,7 +462,7 @@ static void fwtty_throttle_port(struct fwtty_port *port) tty_kref_put(tty); } -/** +/* * fwtty_do_hangup - wait for ldisc to deliver all pending rx; only then hangup * * When the remote has finished tx, and all in-flight rx has been received and @@ -589,9 +589,8 @@ out: return err; } -/** +/* * fwtty_port_handler - bus address handler for port reads/writes - * @parameters: fw_address_callback_t as specified by firewire core interface * * This handler is responsible for handling inbound read/write dma from remotes. */ @@ -656,7 +655,7 @@ respond: fw_send_response(card, request, rcode); } -/** +/* * fwtty_tx_complete - callback for tx dma * @data: ignored, has no meaning for write txns * @length: ignored, has no meaning for write txns @@ -722,7 +721,7 @@ static int fwtty_tx(struct fwtty_port *port, bool drain) /* try to write as many dma transactions out as possible */ n = -EAGAIN; - while (!tty->stopped && !tty->hw_stopped && + while (!tty->flow.stopped && !tty->hw_stopped && !test_bit(STOP_TX, &port->flags)) { txn = kmem_cache_alloc(fwtty_txn_cache, GFP_ATOMIC); if (!txn) { @@ -904,7 +903,7 @@ static void fwtty_port_dtr_rts(struct tty_port *tty_port, int on) spin_unlock_bh(&port->lock); } -/** +/* * fwtty_port_carrier_raised: required tty_port operation * * This port operation is polled after a tty has been opened and is waiting for @@ -1011,7 +1010,7 @@ static int fwtty_port_activate(struct tty_port *tty_port, return 0; } -/** +/* * fwtty_port_shutdown * * Note: the tty port core ensures this is not the console and @@ -1113,30 +1112,30 @@ static int fwtty_write(struct tty_struct *tty, const unsigned char *buf, int c) return (n < 0) ? 0 : n; } -static int fwtty_write_room(struct tty_struct *tty) +static unsigned int fwtty_write_room(struct tty_struct *tty) { struct fwtty_port *port = tty->driver_data; - int n; + unsigned int n; spin_lock_bh(&port->lock); n = dma_fifo_avail(&port->tx_fifo); spin_unlock_bh(&port->lock); - fwtty_dbg(port, "%d\n", n); + fwtty_dbg(port, "%u\n", n); return n; } -static int fwtty_chars_in_buffer(struct tty_struct *tty) +static unsigned int fwtty_chars_in_buffer(struct tty_struct *tty) { struct fwtty_port *port = tty->driver_data; - int n; + unsigned int n; spin_lock_bh(&port->lock); n = dma_fifo_level(&port->tx_fifo); spin_unlock_bh(&port->lock); - fwtty_dbg(port, "%d\n", n); + fwtty_dbg(port, "%u\n", n); return n; } @@ -1297,7 +1296,7 @@ static void fwtty_set_termios(struct tty_struct *tty, struct ktermios *old) } } -/** +/* * fwtty_break_ctl - start/stop sending breaks * * Signals the remote to start or stop generating simulated breaks. @@ -1669,7 +1668,7 @@ static inline int fwserial_send_mgmt_sync(struct fwtty_peer *peer, return rcode; } -/** +/* * fwserial_claim_port - attempt to claim port @ index for peer * * Returns ptr to claimed port or error code (as ERR_PTR()) @@ -1697,7 +1696,7 @@ static struct fwtty_port *fwserial_claim_port(struct fwtty_peer *peer, return port; } -/** +/* * fwserial_find_port - find avail port and claim for peer * * Returns ptr to claimed port or NULL if none avail @@ -1764,7 +1763,7 @@ static void fwserial_plug_timeout(struct timer_list *t) fwserial_release_port(port, false); } -/** +/* * fwserial_connect_peer - initiate virtual cable with peer * * Returns 0 if VIRT_CABLE_PLUG request was successfully sent, @@ -1829,7 +1828,7 @@ free_pkt: return err; } -/** +/* * fwserial_close_port - * HUP the tty (if the tty exists) and unregister the tty device. * Only used by the unit driver upon unit removal to disconnect and @@ -1893,7 +1892,7 @@ static struct fw_serial *__fwserial_lookup_rcu(struct fw_card *card) return NULL; } -/** +/* * __fwserial_peer_by_node_id - finds a peer matching the given generation + id * * If a matching peer could not be found for the specified generation/node id, @@ -2076,7 +2075,7 @@ static int fwserial_add_peer(struct fw_serial *serial, struct fw_unit *unit) return 0; } -/** +/* * fwserial_remove_peer - remove a 'serial' unit device as a 'peer' * * Remove a 'peer' from its list of peers. This function is only @@ -2279,7 +2278,7 @@ free_ports: return err; } -/** +/* * fwserial_probe: bus probe function for firewire 'serial' unit devices * * A 'serial' unit device is created and probed as a result of: @@ -2331,7 +2330,7 @@ static int fwserial_probe(struct fw_unit *unit, return err; } -/** +/* * fwserial_remove: bus removal function for firewire 'serial' unit devices * * The corresponding 'peer' for this unit device is removed from the list of @@ -2363,7 +2362,7 @@ static void fwserial_remove(struct fw_unit *unit) mutex_unlock(&fwserial_list_mutex); } -/** +/* * fwserial_update: bus update function for 'firewire' serial unit devices * * Updates the new node_id and bus generation for this peer. Note that locking @@ -2699,9 +2698,8 @@ static int fwserial_parse_mgmt_write(struct fwtty_peer *peer, return rcode; } -/** +/* * fwserial_mgmt_handler: bus address handler for mgmt requests - * @parameters: fw_address_callback_t as specified by firewire core interface * * This handler is responsible for handling virtual cable requests from remotes * for all cards. diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c index 571f47d39484..e390c924ec1c 100644 --- a/drivers/staging/gdm724x/gdm_lte.c +++ b/drivers/staging/gdm724x/gdm_lte.c @@ -611,10 +611,12 @@ static void gdm_lte_netif_rx(struct net_device *dev, char *buf, * bytes (99,130,83,99 dec) */ } __packed; - void *addr = buf + sizeof(struct iphdr) + - sizeof(struct udphdr) + - offsetof(struct dhcp_packet, chaddr); - ether_addr_copy(nic->dest_mac_addr, addr); + int offset = sizeof(struct iphdr) + + sizeof(struct udphdr) + + offsetof(struct dhcp_packet, chaddr); + if (offset + ETH_ALEN > len) + return; + ether_addr_copy(nic->dest_mac_addr, buf + offset); } } @@ -677,6 +679,7 @@ static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len) struct sdu *sdu = NULL; u8 endian = phy_dev->get_endian(phy_dev->priv_dev); u8 *data = (u8 *)multi_sdu->data; + int copied; u16 i = 0; u16 num_packet; u16 hci_len; @@ -684,10 +687,15 @@ static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len) u32 nic_type; int index; - hci_len = gdm_dev16_to_cpu(endian, multi_sdu->len); num_packet = gdm_dev16_to_cpu(endian, multi_sdu->num_packet); for (i = 0; i < num_packet; i++) { + copied = data - multi_sdu->data; + if (len < copied + sizeof(*sdu)) { + pr_err("rx prevent buffer overflow"); + return; + } + sdu = (struct sdu *)data; cmd_evt = gdm_dev16_to_cpu(endian, sdu->cmd_evt); @@ -698,7 +706,8 @@ static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len) pr_err("rx sdu wrong hci %04x\n", cmd_evt); return; } - if (hci_len < 12) { + if (hci_len < 12 || + len < copied + sizeof(*sdu) + (hci_len - 12)) { pr_err("rx sdu invalid len %d\n", hci_len); return; } diff --git a/drivers/staging/gdm724x/gdm_tty.c b/drivers/staging/gdm724x/gdm_tty.c index 0ccc8c24e754..279de2cd9c4a 100644 --- a/drivers/staging/gdm724x/gdm_tty.c +++ b/drivers/staging/gdm724x/gdm_tty.c @@ -183,7 +183,7 @@ static int gdm_tty_write(struct tty_struct *tty, const unsigned char *buf, return len; } -static int gdm_tty_write_room(struct tty_struct *tty) +static unsigned int gdm_tty_write_room(struct tty_struct *tty) { struct gdm *gdm = tty->driver_data; diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 1fc7727ab7be..1e613d42d823 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -676,7 +676,7 @@ static int gbaudio_tplg_create_kcontrol(struct gbaudio_module_info *gb, struct gbaudio_ctl_pvt *ctldata; switch (ctl->iface) { - case SNDRV_CTL_ELEM_IFACE_MIXER: + case (__force int)SNDRV_CTL_ELEM_IFACE_MIXER: switch (ctl->info.type) { case GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED: ret = gbaudio_tplg_create_enum_kctl(gb, kctl, ctl); @@ -903,7 +903,7 @@ static int gbaudio_tplg_create_wcontrol(struct gbaudio_module_info *gb, int ret; switch (ctl->iface) { - case SNDRV_CTL_ELEM_IFACE_MIXER: + case (__force int)SNDRV_CTL_ELEM_IFACE_MIXER: switch (ctl->info.type) { case GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED: ret = gbaudio_tplg_create_enum_ctl(gb, kctl, ctl); diff --git a/drivers/staging/greybus/gbphy.c b/drivers/staging/greybus/gbphy.c index 9fc5c47be9bd..13d319860da5 100644 --- a/drivers/staging/greybus/gbphy.c +++ b/drivers/staging/greybus/gbphy.c @@ -27,7 +27,7 @@ struct gbphy_host { static DEFINE_IDA(gbphy_id); static ssize_t protocol_id_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); @@ -221,7 +221,7 @@ void gb_gbphy_deregister_driver(struct gbphy_driver *driver) EXPORT_SYMBOL_GPL(gb_gbphy_deregister_driver); static struct gbphy_device *gb_gbphy_create_dev(struct gb_bundle *bundle, - struct greybus_descriptor_cport *cport_desc) + struct greybus_descriptor_cport *cport_desc) { struct gbphy_device *gbphy_dev; int retval; diff --git a/drivers/staging/greybus/spilib.c b/drivers/staging/greybus/spilib.c index 30655153df6a..ad0700a0bb81 100644 --- a/drivers/staging/greybus/spilib.c +++ b/drivers/staging/greybus/spilib.c @@ -246,6 +246,7 @@ static struct gb_operation *gb_spi_operation_create(struct gb_spilib *spi, xfer = spi->first_xfer; while (msg->state != GB_SPI_STATE_OP_DONE) { int xfer_delay; + if (xfer == spi->last_xfer) xfer_len = spi->last_xfer_size; else diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index b1e63f7798b0..73f01ed1e5b7 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -440,7 +440,7 @@ static int gb_tty_write(struct tty_struct *tty, const unsigned char *buf, return count; } -static int gb_tty_write_room(struct tty_struct *tty) +static unsigned int gb_tty_write_room(struct tty_struct *tty) { struct gb_tty *gb_tty = tty->driver_data; unsigned long flags; @@ -457,11 +457,11 @@ static int gb_tty_write_room(struct tty_struct *tty) return room; } -static int gb_tty_chars_in_buffer(struct tty_struct *tty) +static unsigned int gb_tty_chars_in_buffer(struct tty_struct *tty) { struct gb_tty *gb_tty = tty->driver_data; unsigned long flags; - int chars; + unsigned int chars; spin_lock_irqsave(&gb_tty->write_lock, flags); chars = kfifo_len(&gb_tty->write_fifo); @@ -494,21 +494,7 @@ static void gb_tty_set_termios(struct tty_struct *tty, (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0; - switch (termios->c_cflag & CSIZE) { - case CS5: - newline.data_bits = 5; - break; - case CS6: - newline.data_bits = 6; - break; - case CS7: - newline.data_bits = 7; - break; - case CS8: - default: - newline.data_bits = 8; - break; - } + newline.data_bits = tty_get_char_size(termios->c_cflag); /* FIXME: needs to clear unsupported bits in the termios */ gb_tty->clocal = ((termios->c_cflag & CLOCAL) != 0); diff --git a/drivers/staging/gs_fpgaboot/README b/drivers/staging/gs_fpgaboot/README index b85a76849fc4..ec1235a21bcc 100644 --- a/drivers/staging/gs_fpgaboot/README +++ b/drivers/staging/gs_fpgaboot/README @@ -39,7 +39,7 @@ TABLE OF CONTENTS. 5. USE CASE (from a mailing list discussion with Greg) - a. As a FPGA development support tool, + a. As an FPGA development support tool, During FPGA firmware development, you need to download a new FPGA image frequently. You would do that with a dedicated JTAG, which usually a limited diff --git a/drivers/staging/hikey9xx/Kconfig b/drivers/staging/hikey9xx/Kconfig index c4dc1016edf2..9f53df9068fe 100644 --- a/drivers/staging/hikey9xx/Kconfig +++ b/drivers/staging/hikey9xx/Kconfig @@ -1,27 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -# to be placed at drivers/phy -config PHY_HI3670_USB - tristate "hi3670 USB PHY support" - depends on (ARCH_HISI && ARM64) || COMPILE_TEST - select GENERIC_PHY - select MFD_SYSCON - help - Enable this to support the HISILICON HI3670 USB PHY. - - To compile this driver as a module, choose M here. - -# to be placed at drivers/spmi -config SPMI_HISI3670 - tristate "Hisilicon 3670 SPMI Controller" - select IRQ_DOMAIN_HIERARCHY - depends on HAS_IOMEM - depends on SPMI - help - If you say yes to this option, support will be included for the - built-in SPMI PMIC Arbiter interface on Hisilicon 3670 - processors. - # to be placed at drivers/mfd config MFD_HI6421_SPMI tristate "HiSilicon Hi6421v600 SPMI PMU/Codec IC" diff --git a/drivers/staging/hikey9xx/Makefile b/drivers/staging/hikey9xx/Makefile index 9103735d8377..e3108d7dd849 100644 --- a/drivers/staging/hikey9xx/Makefile +++ b/drivers/staging/hikey9xx/Makefile @@ -1,6 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_PHY_HI3670_USB) += phy-hi3670-usb3.o - -obj-$(CONFIG_SPMI_HISI3670) += hisi-spmi-controller.o obj-$(CONFIG_MFD_HI6421_SPMI) += hi6421-spmi-pmic.o diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c index 626140cb96f2..35ef3d4c760b 100644 --- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c +++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c @@ -33,17 +33,27 @@ enum hi6421_spmi_pmic_irq_list { SIM0_HPD_F, SIM1_HPD_R, SIM1_HPD_F, - PMIC_IRQ_LIST_MAX, + + PMIC_IRQ_LIST_MAX }; -#define HISI_IRQ_ARRAY 2 -#define HISI_IRQ_NUM (HISI_IRQ_ARRAY * 8) +#define HISI_IRQ_BANK_SIZE 2 -#define HISI_IRQ_KEY_NUM 0 +/* + * IRQ number for the power key button and mask for both UP and DOWN IRQs + */ +#define HISI_POWERKEY_IRQ_NUM 0 +#define HISI_IRQ_POWERKEY_UP_DOWN (BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP)) -#define HISI_BITS 8 -#define HISI_IRQ_KEY_VALUE (BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP)) -#define HISI_MASK GENMASK(HISI_BITS - 1, 0) +/* + * Registers for IRQ address and IRQ mask bits + * + * Please notice that we need to regmap a larger region, as other + * registers are used by the regulators. + * See drivers/regulator/hi6421-regulator.c. + */ +#define SOC_PMIC_IRQ_MASK_0_ADDR 0x0202 +#define SOC_PMIC_IRQ0_ADDR 0x0212 /* * The IRQs are mapped as: @@ -67,13 +77,14 @@ enum hi6421_spmi_pmic_irq_list { * SIM1_HPD_R 0x0203 0x213 bit 4 * SIM1_HPD_F 0x0203 0x213 bit 5 * ====================== ============= ============ ===== + * + * Each mask register contains 8 bits. The ancillary macros below + * convert a number from 0 to 14 into a register address and a bit mask */ -#define SOC_PMIC_IRQ_MASK_0_ADDR 0x0202 -#define SOC_PMIC_IRQ0_ADDR 0x0212 - -#define IRQ_MASK_REGISTER(irq_data) (SOC_PMIC_IRQ_MASK_0_ADDR + \ - (irqd_to_hwirq(irq_data) >> 3)) -#define IRQ_MASK_BIT(irq_data) BIT(irqd_to_hwirq(irq_data) & 0x07) +#define HISI_IRQ_MASK_REG(irq_data) (SOC_PMIC_IRQ_MASK_0_ADDR + \ + (irqd_to_hwirq(irq_data) / BITS_PER_BYTE)) +#define HISI_IRQ_MASK_BIT(irq_data) BIT(irqd_to_hwirq(irq_data) & (BITS_PER_BYTE - 1)) +#define HISI_8BITS_MASK 0xff static const struct mfd_cell hi6421v600_devs[] = { { .name = "hi6421v600-regulator", }, @@ -86,23 +97,31 @@ static irqreturn_t hi6421_spmi_irq_handler(int irq, void *priv) unsigned int in; int i, offset; - for (i = 0; i < HISI_IRQ_ARRAY; i++) { + for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) { regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &in); - pending = HISI_MASK & in; - regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, pending); - if (i == HISI_IRQ_KEY_NUM && - (pending & HISI_IRQ_KEY_VALUE) == HISI_IRQ_KEY_VALUE) { + /* Mark pending IRQs as handled */ + regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, in); + + pending = in & HISI_8BITS_MASK; + + if (i == HISI_POWERKEY_IRQ_NUM && + (pending & HISI_IRQ_POWERKEY_UP_DOWN) == HISI_IRQ_POWERKEY_UP_DOWN) { + /* + * If both powerkey down and up IRQs are received, + * handle them at the right order + */ generic_handle_irq(ddata->irqs[POWERKEY_DOWN]); generic_handle_irq(ddata->irqs[POWERKEY_UP]); - pending &= (~HISI_IRQ_KEY_VALUE); + pending &= ~HISI_IRQ_POWERKEY_UP_DOWN; } if (!pending) continue; - for_each_set_bit(offset, &pending, HISI_BITS) - generic_handle_irq(ddata->irqs[offset + i * HISI_BITS]); + for_each_set_bit(offset, &pending, BITS_PER_BYTE) { + generic_handle_irq(ddata->irqs[offset + i * BITS_PER_BYTE]); + } } return IRQ_HANDLED; @@ -115,12 +134,12 @@ static void hi6421_spmi_irq_mask(struct irq_data *d) unsigned int data; u32 offset; - offset = IRQ_MASK_REGISTER(d); + offset = HISI_IRQ_MASK_REG(d); spin_lock_irqsave(&ddata->lock, flags); regmap_read(ddata->regmap, offset, &data); - data |= IRQ_MASK_BIT(d); + data |= HISI_IRQ_MASK_BIT(d); regmap_write(ddata->regmap, offset, data); spin_unlock_irqrestore(&ddata->lock, flags); @@ -132,20 +151,19 @@ static void hi6421_spmi_irq_unmask(struct irq_data *d) u32 data, offset; unsigned long flags; - offset = (irqd_to_hwirq(d) >> 3); - offset += SOC_PMIC_IRQ_MASK_0_ADDR; + offset = HISI_IRQ_MASK_REG(d); spin_lock_irqsave(&ddata->lock, flags); regmap_read(ddata->regmap, offset, &data); - data &= ~(1 << (irqd_to_hwirq(d) & 0x07)); + data &= ~HISI_IRQ_MASK_BIT(d); regmap_write(ddata->regmap, offset, data); spin_unlock_irqrestore(&ddata->lock, flags); } static struct irq_chip hi6421_spmi_pmu_irqchip = { - .name = "hisi-irq", + .name = "hi6421v600-irq", .irq_mask = hi6421_spmi_irq_mask, .irq_unmask = hi6421_spmi_irq_unmask, .irq_disable = hi6421_spmi_irq_mask, @@ -158,7 +176,7 @@ static int hi6421_spmi_irq_map(struct irq_domain *d, unsigned int virq, struct hi6421_spmi_pmic *ddata = d->host_data; irq_set_chip_and_handler_name(virq, &hi6421_spmi_pmu_irqchip, - handle_simple_irq, "hisi"); + handle_simple_irq, "hi6421v600"); irq_set_chip_data(virq, ddata); irq_set_irq_type(virq, IRQ_TYPE_NONE); @@ -175,22 +193,24 @@ static void hi6421_spmi_pmic_irq_init(struct hi6421_spmi_pmic *ddata) int i; unsigned int pending; - for (i = 0; i < HISI_IRQ_ARRAY; i++) + /* Mask all IRQs */ + for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) regmap_write(ddata->regmap, SOC_PMIC_IRQ_MASK_0_ADDR + i, - HISI_MASK); + HISI_8BITS_MASK); - for (i = 0; i < HISI_IRQ_ARRAY; i++) { + /* Mark all IRQs as handled */ + for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) { regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &pending); regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, - HISI_MASK); + HISI_8BITS_MASK); } } static const struct regmap_config regmap_config = { - .reg_bits = 16, - .val_bits = HISI_BITS, - .max_register = 0xffff, - .fast_io = true + .reg_bits = 16, + .val_bits = BITS_PER_BYTE, + .max_register = 0xffff, + .fast_io = true }; static int hi6421_spmi_pmic_probe(struct spmi_device *pdev) @@ -230,29 +250,31 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev) hi6421_spmi_pmic_irq_init(ddata); - ddata->irqs = devm_kzalloc(dev, HISI_IRQ_NUM * sizeof(int), GFP_KERNEL); + ddata->irqs = devm_kzalloc(dev, PMIC_IRQ_LIST_MAX * sizeof(int), GFP_KERNEL); if (!ddata->irqs) return -ENOMEM; - ddata->domain = irq_domain_add_simple(np, HISI_IRQ_NUM, 0, + ddata->domain = irq_domain_add_simple(np, PMIC_IRQ_LIST_MAX, 0, &hi6421_spmi_domain_ops, ddata); if (!ddata->domain) { dev_err(dev, "Failed to create IRQ domain\n"); return -ENODEV; } - for (i = 0; i < HISI_IRQ_NUM; i++) { + for (i = 0; i < PMIC_IRQ_LIST_MAX; i++) { virq = irq_create_mapping(ddata->domain, i); if (!virq) { dev_err(dev, "Failed to map H/W IRQ\n"); - return -ENOSPC; + return -ENODEV; } ddata->irqs[i] = virq; } - ret = request_threaded_irq(ddata->irq, hi6421_spmi_irq_handler, NULL, - IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND, - "pmic", ddata); + ret = devm_request_threaded_irq(dev, + ddata->irq, hi6421_spmi_irq_handler, + NULL, + IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND, + "pmic", ddata); if (ret < 0) { dev_err(dev, "Failed to start IRQ handling thread: error %d\n", ret); @@ -270,13 +292,6 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev) return ret; } -static void hi6421_spmi_pmic_remove(struct spmi_device *pdev) -{ - struct hi6421_spmi_pmic *ddata = dev_get_drvdata(&pdev->dev); - - free_irq(ddata->irq, ddata); -} - static const struct of_device_id pmic_spmi_id_table[] = { { .compatible = "hisilicon,hi6421-spmi" }, { } @@ -289,7 +304,6 @@ static struct spmi_driver hi6421_spmi_pmic_driver = { .of_match_table = pmic_spmi_id_table, }, .probe = hi6421_spmi_pmic_probe, - .remove = hi6421_spmi_pmic_remove, }; module_spmi_driver(hi6421_spmi_pmic_driver); diff --git a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml b/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml index 3b23ad56b31a..8e355cddd437 100644 --- a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml +++ b/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml @@ -17,7 +17,7 @@ description: | node. The SPMI controller part is provided by - drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml. + Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml properties: $nodename: @@ -32,12 +32,11 @@ properties: '#interrupt-cells': const: 2 - interrupt-controller: - description: - Identify that the PMIC is capable of behaving as an interrupt controller. + interrupt-controller: true gpios: maxItems: 1 + description: GPIO used for IRQs regulators: type: object diff --git a/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml b/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml deleted file mode 100644 index 6b755039a74c..000000000000 --- a/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml +++ /dev/null @@ -1,71 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/spmi/hisilicon,hisi-spmi-controller.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: HiSilicon SPMI controller - -maintainers: - - Mauro Carvalho Chehab <mchehab+huawei@kernel.org> - -description: | - The HiSilicon SPMI BUS controller is found on some Kirin-based designs. - It is a MIPI System Power Management (SPMI) controller. - - The PMIC part is provided by - drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml. - -allOf: - - $ref: spmi.yaml# - -properties: - - $nodename: - pattern: "spmi@[0-9a-f]" - - compatible: - const: hisilicon,kirin970-spmi-controller - - reg: - maxItems: 1 - - spmi-channel: - $ref: /schemas/types.yaml#/definitions/uint32 - description: | - number of the Kirin 970 SPMI channel where the SPMI devices are connected. - -required: - - compatible - - reg - - spmi-channel - -patternProperties: - "@[0-9a-f]$": - description: | - PMIC properties, which are specific to the used SPMI PMIC device(s). - When used in combination with HiSilicon 6421v600, the properties - are documented at - drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml. - -unevaluatedProperties: false - -examples: - - | - bus { - #address-cells = <2>; - #size-cells = <2>; - - spmi: spmi@fff24000 { - compatible = "hisilicon,kirin970-spmi-controller"; - #address-cells = <2>; - #size-cells = <0>; - reg = <0x0 0xfff24000 0x0 0x1000>; - spmi-channel = <2>; - - pmic@0 { - reg = <0 0>; - /* pmic properties */ - }; - }; - }; diff --git a/drivers/staging/hikey9xx/phy-hi3670-usb3.yaml b/drivers/staging/hikey9xx/phy-hi3670-usb3.yaml deleted file mode 100644 index ebd78acfe2de..000000000000 --- a/drivers/staging/hikey9xx/phy-hi3670-usb3.yaml +++ /dev/null @@ -1,73 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/phy/hisilicon,hi3670-usb3.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Hisilicon Kirin970 USB PHY - -maintainers: - - Mauro Carvalho Chehab <mchehab+huawei@kernel.org> - -description: |+ - Bindings for USB3 PHY on HiSilicon Kirin 970. - -properties: - compatible: - const: hisilicon,hi3670-usb-phy - - "#phy-cells": - const: 0 - - hisilicon,pericrg-syscon: - $ref: '/schemas/types.yaml#/definitions/phandle' - description: phandle of syscon used to control iso refclk. - - hisilicon,pctrl-syscon: - $ref: '/schemas/types.yaml#/definitions/phandle' - description: phandle of syscon used to control usb tcxo. - - hisilicon,sctrl-syscon: - $ref: '/schemas/types.yaml#/definitions/phandle' - description: phandle of syscon used to control phy deep sleep. - - hisilicon,eye-diagram-param: - $ref: /schemas/types.yaml#/definitions/uint32 - description: Eye diagram for phy. - - hisilicon,tx-vboost-lvl: - $ref: /schemas/types.yaml#/definitions/uint32 - description: TX level vboost for phy. - -required: - - compatible - - hisilicon,pericrg-syscon - - hisilicon,pctrl-syscon - - hisilicon,sctrl-syscon - - hisilicon,eye-diagram-param - - hisilicon,tx-vboost-lvl - - "#phy-cells" - -additionalProperties: false - -examples: - - | - bus { - #address-cells = <2>; - #size-cells = <2>; - - usb3_otg_bc: usb3_otg_bc@ff200000 { - compatible = "syscon", "simple-mfd"; - reg = <0x0 0xff200000 0x0 0x1000>; - - usb_phy { - compatible = "hisilicon,hi3670-usb-phy"; - #phy-cells = <0>; - hisilicon,pericrg-syscon = <&crg_ctrl>; - hisilicon,pctrl-syscon = <&pctrl>; - hisilicon,sctrl-syscon = <&sctrl>; - hisilicon,eye-diagram-param = <0xfdfee4>; - hisilicon,tx-vboost-lvl = <0x5>; - }; - }; - }; diff --git a/drivers/staging/iio/accel/adis16203.c b/drivers/staging/iio/accel/adis16203.c index b68304da288b..1d3026dae827 100644 --- a/drivers/staging/iio/accel/adis16203.c +++ b/drivers/staging/iio/accel/adis16203.c @@ -5,20 +5,14 @@ * Copyright 2010 Analog Devices Inc. */ -#include <linux/delay.h> #include <linux/device.h> -#include <linux/iio/buffer.h> #include <linux/iio/iio.h> #include <linux/iio/imu/adis.h> -#include <linux/iio/sysfs.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/mutex.h> -#include <linux/slab.h> #include <linux/spi/spi.h> -#include <linux/sysfs.h> #define ADIS16203_STARTUP_DELAY 220 /* ms */ diff --git a/drivers/staging/iio/accel/adis16240.c b/drivers/staging/iio/accel/adis16240.c index 8d3afc6dc755..2a8aa83b8d9e 100644 --- a/drivers/staging/iio/accel/adis16240.c +++ b/drivers/staging/iio/accel/adis16240.c @@ -5,20 +5,14 @@ * Copyright 2010 Analog Devices Inc. */ -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/delay.h> #include <linux/device.h> #include <linux/kernel.h> #include <linux/spi/spi.h> -#include <linux/slab.h> #include <linux/sysfs.h> -#include <linux/list.h> #include <linux/module.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> -#include <linux/iio/buffer.h> #include <linux/iio/imu/adis.h> #define ADIS16240_STARTUP_DELAY 220 /* ms */ diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index ccbafcaaf27e..79467f056a05 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -1348,9 +1348,9 @@ static ssize_t adt7316_show_in_analog_temp_offset(struct device *dev, } static ssize_t adt7316_store_in_analog_temp_offset(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, + size_t len) { struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); @@ -1375,9 +1375,9 @@ static ssize_t adt7316_show_ex_analog_temp_offset(struct device *dev, } static ssize_t adt7316_store_ex_analog_temp_offset(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, + size_t len) { struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index eab534dc4bcc..78ac720266e6 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -18,8 +18,6 @@ #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> -#include "ad7746.h" - /* * AD7746 Register Definition */ @@ -84,10 +82,6 @@ #define AD7746_CAPDAC_DACEN BIT(7) #define AD7746_CAPDAC_DACP(x) ((x) & 0x7F) -/* - * struct ad7746_chip_info - chip specific information - */ - struct ad7746_chip_info { struct i2c_client *client; struct mutex lock; /* protect sensor state */ @@ -215,6 +209,19 @@ static const unsigned char ad7746_cap_filter_rate_table[][2] = { {16, 62 + 1}, {13, 77 + 1}, {11, 92 + 1}, {9, 110 + 1}, }; +static int ad7746_set_capdac(struct ad7746_chip_info *chip, int channel) +{ + int ret = i2c_smbus_write_byte_data(chip->client, + AD7746_REG_CAPDACA, + chip->capdac[channel][0]); + if (ret < 0) + return ret; + + return i2c_smbus_write_byte_data(chip->client, + AD7746_REG_CAPDACB, + chip->capdac[channel][1]); +} + static int ad7746_select_channel(struct iio_dev *indio_dev, struct iio_chan_spec const *chan) { @@ -230,17 +237,11 @@ static int ad7746_select_channel(struct iio_dev *indio_dev, AD7746_CONF_CAPFS_SHIFT; delay = ad7746_cap_filter_rate_table[idx][1]; + ret = ad7746_set_capdac(chip, chan->channel); + if (ret < 0) + return ret; + if (chip->capdac_set != chan->channel) { - ret = i2c_smbus_write_byte_data(chip->client, - AD7746_REG_CAPDACA, - chip->capdac[chan->channel][0]); - if (ret < 0) - return ret; - ret = i2c_smbus_write_byte_data(chip->client, - AD7746_REG_CAPDACB, - chip->capdac[chan->channel][1]); - if (ret < 0) - return ret; chip->capdac_set = chan->channel; } @@ -484,14 +485,7 @@ static int ad7746_write_raw(struct iio_dev *indio_dev, chip->capdac[chan->channel][chan->differential] = val > 0 ? AD7746_CAPDAC_DACP(val) | AD7746_CAPDAC_DACEN : 0; - ret = i2c_smbus_write_byte_data(chip->client, - AD7746_REG_CAPDACA, - chip->capdac[chan->channel][0]); - if (ret < 0) - goto out; - ret = i2c_smbus_write_byte_data(chip->client, - AD7746_REG_CAPDACB, - chip->capdac[chan->channel][1]); + ret = ad7746_set_capdac(chip, chan->channel); if (ret < 0) goto out; @@ -564,10 +558,10 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, switch (chan->type) { case IIO_TEMP: - /* - * temperature in milli degrees Celsius - * T = ((*val / 2048) - 4096) * 1000 - */ + /* + * temperature in milli degrees Celsius + * T = ((*val / 2048) - 4096) * 1000 + */ *val = (*val * 125) / 256; break; case IIO_VOLTAGE: @@ -669,18 +663,15 @@ static const struct iio_info ad7746_info = { .write_raw = ad7746_write_raw, }; -/* - * device probe and remove - */ - static int ad7746_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct ad7746_platform_data *pdata = client->dev.platform_data; + struct device *dev = &client->dev; struct ad7746_chip_info *chip; struct iio_dev *indio_dev; unsigned char regval = 0; - int ret = 0; + unsigned int vdd_permille; + int ret; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); if (!indio_dev) @@ -702,26 +693,39 @@ static int ad7746_probe(struct i2c_client *client, indio_dev->num_channels = ARRAY_SIZE(ad7746_channels) - 2; indio_dev->modes = INDIO_DIRECT_MODE; - if (pdata) { - if (pdata->exca_en) { - if (pdata->exca_inv_en) - regval |= AD7746_EXCSETUP_NEXCA; - else - regval |= AD7746_EXCSETUP_EXCA; - } + if (device_property_read_bool(dev, "adi,exca-output-en")) { + if (device_property_read_bool(dev, "adi,exca-output-invert")) + regval |= AD7746_EXCSETUP_NEXCA; + else + regval |= AD7746_EXCSETUP_EXCA; + } - if (pdata->excb_en) { - if (pdata->excb_inv_en) - regval |= AD7746_EXCSETUP_NEXCB; - else - regval |= AD7746_EXCSETUP_EXCB; - } + if (device_property_read_bool(dev, "adi,excb-output-en")) { + if (device_property_read_bool(dev, "adi,excb-output-invert")) + regval |= AD7746_EXCSETUP_NEXCB; + else + regval |= AD7746_EXCSETUP_EXCB; + } - regval |= AD7746_EXCSETUP_EXCLVL(pdata->exclvl); - } else { - dev_warn(&client->dev, "No platform data? using default\n"); - regval = AD7746_EXCSETUP_EXCA | AD7746_EXCSETUP_EXCB | - AD7746_EXCSETUP_EXCLVL(3); + ret = device_property_read_u32(dev, "adi,excitation-vdd-permille", + &vdd_permille); + if (!ret) { + switch (vdd_permille) { + case 125: + regval |= AD7746_EXCSETUP_EXCLVL(0); + break; + case 250: + regval |= AD7746_EXCSETUP_EXCLVL(1); + break; + case 375: + regval |= AD7746_EXCSETUP_EXCLVL(2); + break; + case 500: + regval |= AD7746_EXCSETUP_EXCLVL(3); + break; + default: + break; + } } ret = i2c_smbus_write_byte_data(chip->client, @@ -729,11 +733,7 @@ static int ad7746_probe(struct i2c_client *client, if (ret < 0) return ret; - ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev); - if (ret) - return ret; - - return 0; + return devm_iio_device_register(indio_dev->dev.parent, indio_dev); } static const struct i2c_device_id ad7746_id[] = { diff --git a/drivers/staging/iio/cdc/ad7746.h b/drivers/staging/iio/cdc/ad7746.h deleted file mode 100644 index 8bdbd732dbbd..000000000000 --- a/drivers/staging/iio/cdc/ad7746.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * AD7746 capacitive sensor driver supporting AD7745, AD7746 and AD7747 - * - * Copyright 2011 Analog Devices Inc. - */ - -#ifndef IIO_CDC_AD7746_H_ -#define IIO_CDC_AD7746_H_ - -/* - * TODO: struct ad7746_platform_data needs to go into include/linux/iio - */ - -#define AD7466_EXCLVL_0 0 /* +-VDD/8 */ -#define AD7466_EXCLVL_1 1 /* +-VDD/4 */ -#define AD7466_EXCLVL_2 2 /* +-VDD * 3/8 */ -#define AD7466_EXCLVL_3 3 /* +-VDD/2 */ - -struct ad7746_platform_data { - unsigned char exclvl; /*Excitation Voltage Level */ - bool exca_en; /* enables EXCA pin as the excitation output */ - bool exca_inv_en; /* enables /EXCA pin as the excitation output */ - bool excb_en; /* enables EXCB pin as the excitation output */ - bool excb_inv_en; /* enables /EXCB pin as the excitation output */ -}; - -#endif /* IIO_CDC_AD7746_H_ */ diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c index 60a3ae5587b9..94b131ef8a22 100644 --- a/drivers/staging/iio/frequency/ad9834.c +++ b/drivers/staging/iio/frequency/ad9834.c @@ -58,6 +58,7 @@ * @spi: spi_device * @mclk: external master clock * @control: cached control word + * @devid: device id * @xfer: default spi transfer * @msg: default spi message * @freq_xfer: tuning word spi transfer @@ -86,7 +87,7 @@ struct ad9834_state { __be16 freq_data[2]; }; -/** +/* * ad9834_supported_device_ids: */ @@ -316,7 +317,7 @@ ssize_t ad9834_show_out1_wavetype_available(struct device *dev, static IIO_DEVICE_ATTR(out_altvoltage0_out1_wavetype_available, 0444, ad9834_show_out1_wavetype_available, NULL, 0); -/** +/* * see dds.h for further information */ diff --git a/drivers/staging/kpc2000/Kconfig b/drivers/staging/kpc2000/Kconfig deleted file mode 100644 index 897965359fcb..000000000000 --- a/drivers/staging/kpc2000/Kconfig +++ /dev/null @@ -1,59 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -config KPC2000 - bool "Daktronics KPC Device support" - select MFD_CORE - depends on PCI - depends on UIO - help - Select this if you wish to use the Daktronics KPC PCI devices - - If unsure, say N. - -config KPC2000_CORE - tristate "Daktronics KPC PCI UIO device" - depends on KPC2000 - help - Say Y here if you wish to support the Daktronics KPC PCI - device in UIO mode. - - To compile this driver as a module, choose M here: the module - will be called kpc2000 - - If unsure, say N. - -config KPC2000_SPI - tristate "Daktronics KPC SPI device" - depends on KPC2000 && SPI - help - Say Y here if you wish to support the Daktronics KPC PCI - device in SPI mode. - - To compile this driver as a module, choose M here: the module - will be called kpc2000_spi - - If unsure, say N. - -config KPC2000_I2C - tristate "Daktronics KPC I2C device" - depends on KPC2000 && I2C - help - Say Y here if you wish to support the Daktronics KPC PCI - device in I2C mode. - - To compile this driver as a module, choose M here: the module - will be called kpc2000_i2c - - If unsure, say N. - -config KPC2000_DMA - tristate "Daktronics KPC DMA controller" - depends on KPC2000 - help - Say Y here if you wish to support the Daktronics DMA controller. - - To compile this driver as a module, choose M here: the module - will be called kpc2000_dma - - If unsure, say N. - diff --git a/drivers/staging/kpc2000/Makefile b/drivers/staging/kpc2000/Makefile deleted file mode 100644 index d15ed49807d5..000000000000 --- a/drivers/staging/kpc2000/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -obj-$(CONFIG_KPC2000) += kpc2000/ -obj-$(CONFIG_KPC2000_I2C) += kpc2000_i2c.o -obj-$(CONFIG_KPC2000_SPI) += kpc2000_spi.o -obj-$(CONFIG_KPC2000_DMA) += kpc_dma/ diff --git a/drivers/staging/kpc2000/TODO b/drivers/staging/kpc2000/TODO deleted file mode 100644 index 9b5ab37fb3a0..000000000000 --- a/drivers/staging/kpc2000/TODO +++ /dev/null @@ -1,2 +0,0 @@ -- the kpc_spi driver doesn't seem to let multiple transactions (to different instances of the core) happen in parallel... -- The kpc_i2c driver is a hot mess, it should probably be cleaned up a ton. It functions against current hardware though. diff --git a/drivers/staging/kpc2000/kpc.h b/drivers/staging/kpc2000/kpc.h deleted file mode 100644 index a3fc9c9221aa..000000000000 --- a/drivers/staging/kpc2000/kpc.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -#ifndef KPC_H_ -#define KPC_H_ - -/* ***** Driver Names ***** */ -#define KP_DRIVER_NAME_KP2000 "kp2000" -#define KP_DRIVER_NAME_INVALID "kpc_invalid" -#define KP_DRIVER_NAME_DMA_CONTROLLER "kpc_nwl_dma" -#define KP_DRIVER_NAME_UIO "uio_pdrv_genirq" -#define KP_DRIVER_NAME_I2C "kpc_i2c" -#define KP_DRIVER_NAME_SPI "kpc_spi" - -struct kpc_core_device_platdata { - u32 card_id; - u32 build_version; - u32 hardware_revision; - u64 ssid; - u64 ddna; -}; - -#define PCI_DEVICE_ID_DAKTRONICS_KADOKA_P2KR0 0x4b03 - -#endif /* KPC_H_ */ diff --git a/drivers/staging/kpc2000/kpc2000/Makefile b/drivers/staging/kpc2000/kpc2000/Makefile deleted file mode 100644 index c274ad083db6..000000000000 --- a/drivers/staging/kpc2000/kpc2000/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -obj-m := kpc2000.o -kpc2000-objs += core.o cell_probe.o diff --git a/drivers/staging/kpc2000/kpc2000/cell_probe.c b/drivers/staging/kpc2000/kpc2000/cell_probe.c deleted file mode 100644 index e7e963d62699..000000000000 --- a/drivers/staging/kpc2000/kpc2000/cell_probe.c +++ /dev/null @@ -1,548 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/types.h> -#include <linux/export.h> -#include <linux/slab.h> -#include <linux/io.h> -#include <linux/io-64-nonatomic-lo-hi.h> -#include <linux/mfd/core.h> -#include <linux/platform_device.h> -#include <linux/ioport.h> -#include <linux/uio_driver.h> -#include "pcie.h" - -/* Core (Resource) Table Layout: - * one Resource per record (8 bytes) - * 6 5 4 3 2 1 0 - * 3210987654321098765432109876543210987654321098765432109876543210 - * IIIIIIIIIIII Core Type [up to 4095 types] - * D S2C DMA Present - * DDD S2C DMA Channel Number [up to 8 channels] - * LLLLLLLLLLLLLLLL Register Count (64-bit registers) [up to 65535 registers] - * OOOOOOOOOOOOOOOO Core Offset (in 4kB blocks) [up to 65535 cores] - * D C2S DMA Present - * DDD C2S DMA Channel Number [up to 8 channels] - * II IRQ Count [0 to 3 IRQs per core] - * 1111111000 - * IIIIIII IRQ Base Number [up to 128 IRQs per card] - * ___ Spare - * - */ - -#define KPC_OLD_DMA_CH_NUM(present, channel) \ - ((present) ? (0x8 | ((channel) & 0x7)) : 0) -#define KPC_OLD_S2C_DMA_CH_NUM(cte) \ - KPC_OLD_DMA_CH_NUM(cte.s2c_dma_present, cte.s2c_dma_channel_num) -#define KPC_OLD_C2S_DMA_CH_NUM(cte) \ - KPC_OLD_DMA_CH_NUM(cte.c2s_dma_present, cte.c2s_dma_channel_num) - -#define KP_CORE_ID_INVALID 0 -#define KP_CORE_ID_I2C 3 -#define KP_CORE_ID_SPI 5 - -struct core_table_entry { - u16 type; - u32 offset; - u32 length; - bool s2c_dma_present; - u8 s2c_dma_channel_num; - bool c2s_dma_present; - u8 c2s_dma_channel_num; - u8 irq_count; - u8 irq_base_num; -}; - -static -void parse_core_table_entry_v0(struct core_table_entry *cte, const u64 read_val) -{ - cte->type = ((read_val & 0xFFF0000000000000UL) >> 52); - cte->offset = ((read_val & 0x00000000FFFF0000UL) >> 16) * 4096; - cte->length = ((read_val & 0x0000FFFF00000000UL) >> 32) * 8; - cte->s2c_dma_present = ((read_val & 0x0008000000000000UL) >> 51); - cte->s2c_dma_channel_num = ((read_val & 0x0007000000000000UL) >> 48); - cte->c2s_dma_present = ((read_val & 0x0000000000008000UL) >> 15); - cte->c2s_dma_channel_num = ((read_val & 0x0000000000007000UL) >> 12); - cte->irq_count = ((read_val & 0x0000000000000C00UL) >> 10); - cte->irq_base_num = ((read_val & 0x00000000000003F8UL) >> 3); -} - -static -void dbg_cte(struct kp2000_device *pcard, struct core_table_entry *cte) -{ - dev_dbg(&pcard->pdev->dev, - "CTE: type:%3d offset:%3d (%3d) length:%3d (%3d) s2c:%d c2s:%d irq_count:%d base_irq:%d\n", - cte->type, - cte->offset, - cte->offset / 4096, - cte->length, - cte->length / 8, - (cte->s2c_dma_present ? cte->s2c_dma_channel_num : -1), - (cte->c2s_dma_present ? cte->c2s_dma_channel_num : -1), - cte->irq_count, - cte->irq_base_num - ); -} - -static -void parse_core_table_entry(struct core_table_entry *cte, const u64 read_val, const u8 entry_rev) -{ - switch (entry_rev) { - case 0: - parse_core_table_entry_v0(cte, read_val); - break; - default: - cte->type = 0; - break; - } -} - -static int probe_core_basic(unsigned int core_num, struct kp2000_device *pcard, - char *name, const struct core_table_entry cte) -{ - struct mfd_cell cell = { .id = core_num, .name = name }; - struct resource resources[2]; - - struct kpc_core_device_platdata core_pdata = { - .card_id = pcard->card_id, - .build_version = pcard->build_version, - .hardware_revision = pcard->hardware_revision, - .ssid = pcard->ssid, - .ddna = pcard->ddna, - }; - - dev_dbg(&pcard->pdev->dev, - "Found Basic core: type = %02d dma = %02x / %02x offset = 0x%x length = 0x%x (%d regs)\n", - cte.type, - KPC_OLD_S2C_DMA_CH_NUM(cte), - KPC_OLD_C2S_DMA_CH_NUM(cte), - cte.offset, - cte.length, - cte.length / 8); - - cell.platform_data = &core_pdata; - cell.pdata_size = sizeof(struct kpc_core_device_platdata); - cell.num_resources = 2; - - memset(&resources, 0, sizeof(resources)); - - resources[0].start = cte.offset; - resources[0].end = cte.offset + (cte.length - 1); - resources[0].flags = IORESOURCE_MEM; - - resources[1].start = pcard->pdev->irq; - resources[1].end = pcard->pdev->irq; - resources[1].flags = IORESOURCE_IRQ; - - cell.resources = resources; - - return mfd_add_devices(PCARD_TO_DEV(pcard), // parent - pcard->card_num * 100, // id - &cell, // struct mfd_cell * - 1, // ndevs - &pcard->regs_base_resource, - 0, // irq_base - NULL); // struct irq_domain * -} - -struct kpc_uio_device { - struct list_head list; - struct kp2000_device *pcard; - struct device *dev; - struct uio_info uioinfo; - struct core_table_entry cte; - u16 core_num; -}; - -static ssize_t offset_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kpc_uio_device *kudev = dev_get_drvdata(dev); - - return sprintf(buf, "%u\n", kudev->cte.offset); -} -static DEVICE_ATTR_RO(offset); - -static ssize_t size_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kpc_uio_device *kudev = dev_get_drvdata(dev); - - return sprintf(buf, "%u\n", kudev->cte.length); -} -static DEVICE_ATTR_RO(size); - -static ssize_t type_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kpc_uio_device *kudev = dev_get_drvdata(dev); - - return sprintf(buf, "%u\n", kudev->cte.type); -} -static DEVICE_ATTR_RO(type); - -static ssize_t s2c_dma_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kpc_uio_device *kudev = dev_get_drvdata(dev); - - if (!kudev->cte.s2c_dma_present) - return sprintf(buf, "%s", "not present\n"); - - return sprintf(buf, "%u\n", kudev->cte.s2c_dma_channel_num); -} -static DEVICE_ATTR_RO(s2c_dma); - -static ssize_t c2s_dma_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kpc_uio_device *kudev = dev_get_drvdata(dev); - - if (!kudev->cte.c2s_dma_present) - return sprintf(buf, "%s", "not present\n"); - - return sprintf(buf, "%u\n", kudev->cte.c2s_dma_channel_num); -} -static DEVICE_ATTR_RO(c2s_dma); - -static ssize_t irq_count_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kpc_uio_device *kudev = dev_get_drvdata(dev); - - return sprintf(buf, "%u\n", kudev->cte.irq_count); -} -static DEVICE_ATTR_RO(irq_count); - -static ssize_t irq_base_num_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kpc_uio_device *kudev = dev_get_drvdata(dev); - - return sprintf(buf, "%u\n", kudev->cte.irq_base_num); -} -static DEVICE_ATTR_RO(irq_base_num); - -static ssize_t core_num_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kpc_uio_device *kudev = dev_get_drvdata(dev); - - return sprintf(buf, "%u\n", kudev->core_num); -} -static DEVICE_ATTR_RO(core_num); - -struct attribute *kpc_uio_class_attrs[] = { - &dev_attr_offset.attr, - &dev_attr_size.attr, - &dev_attr_type.attr, - &dev_attr_s2c_dma.attr, - &dev_attr_c2s_dma.attr, - &dev_attr_irq_count.attr, - &dev_attr_irq_base_num.attr, - &dev_attr_core_num.attr, - NULL, -}; - -static -int kp2000_check_uio_irq(struct kp2000_device *pcard, u32 irq_num) -{ - u64 interrupt_active = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE); - u64 interrupt_mask_inv = ~readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); - u64 irq_check_mask = BIT_ULL(irq_num); - - if (interrupt_active & irq_check_mask) { // if it's active (interrupt pending) - if (interrupt_mask_inv & irq_check_mask) { // and if it's not masked off - return 1; - } - } - return 0; -} - -static -irqreturn_t kuio_handler(int irq, struct uio_info *uioinfo) -{ - struct kpc_uio_device *kudev = uioinfo->priv; - - if (irq != kudev->pcard->pdev->irq) - return IRQ_NONE; - - if (kp2000_check_uio_irq(kudev->pcard, kudev->cte.irq_base_num)) { - /* Clear the active flag */ - writeq(BIT_ULL(kudev->cte.irq_base_num), - kudev->pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE); - return IRQ_HANDLED; - } - return IRQ_NONE; -} - -static -int kuio_irqcontrol(struct uio_info *uioinfo, s32 irq_on) -{ - struct kpc_uio_device *kudev = uioinfo->priv; - struct kp2000_device *pcard = kudev->pcard; - u64 mask; - - mutex_lock(&pcard->sem); - mask = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); - if (irq_on) - mask &= ~(BIT_ULL(kudev->cte.irq_base_num)); - else - mask |= BIT_ULL(kudev->cte.irq_base_num); - writeq(mask, pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); - mutex_unlock(&pcard->sem); - - return 0; -} - -static int probe_core_uio(unsigned int core_num, struct kp2000_device *pcard, - char *name, const struct core_table_entry cte) -{ - struct kpc_uio_device *kudev; - int rv; - - dev_dbg(&pcard->pdev->dev, - "Found UIO core: type = %02d dma = %02x / %02x offset = 0x%x length = 0x%x (%d regs)\n", - cte.type, - KPC_OLD_S2C_DMA_CH_NUM(cte), - KPC_OLD_C2S_DMA_CH_NUM(cte), - cte.offset, - cte.length, - cte.length / 8); - - kudev = kzalloc(sizeof(*kudev), GFP_KERNEL); - if (!kudev) - return -ENOMEM; - - INIT_LIST_HEAD(&kudev->list); - kudev->pcard = pcard; - kudev->cte = cte; - kudev->core_num = core_num; - - kudev->uioinfo.priv = kudev; - kudev->uioinfo.name = name; - kudev->uioinfo.version = "0.0"; - if (cte.irq_count > 0) { - kudev->uioinfo.irq_flags = IRQF_SHARED; - kudev->uioinfo.irq = pcard->pdev->irq; - kudev->uioinfo.handler = kuio_handler; - kudev->uioinfo.irqcontrol = kuio_irqcontrol; - } else { - kudev->uioinfo.irq = 0; - } - - kudev->uioinfo.mem[0].name = "uiomap"; - kudev->uioinfo.mem[0].addr = pci_resource_start(pcard->pdev, REG_BAR) + cte.offset; - - // Round up to nearest PAGE_SIZE boundary - kudev->uioinfo.mem[0].size = (cte.length + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); - kudev->uioinfo.mem[0].memtype = UIO_MEM_PHYS; - - kudev->dev = device_create(kpc_uio_class, - &pcard->pdev->dev, MKDEV(0, 0), kudev, "%s.%d.%d.%d", - kudev->uioinfo.name, pcard->card_num, cte.type, kudev->core_num); - if (IS_ERR(kudev->dev)) { - dev_err(&pcard->pdev->dev, "%s: device_create failed!\n", - __func__); - kfree(kudev); - return -ENODEV; - } - dev_set_drvdata(kudev->dev, kudev); - - rv = uio_register_device(kudev->dev, &kudev->uioinfo); - if (rv) { - dev_err(&pcard->pdev->dev, "%s: failed uio_register_device: %d\n", - __func__, rv); - put_device(kudev->dev); - kfree(kudev); - return rv; - } - - list_add_tail(&kudev->list, &pcard->uio_devices_list); - - return 0; -} - -static int create_dma_engine_core(struct kp2000_device *pcard, - size_t engine_regs_offset, - int engine_num, int irq_num) -{ - struct mfd_cell cell = { .id = engine_num }; - struct resource resources[2]; - - cell.platform_data = NULL; - cell.pdata_size = 0; - cell.name = KP_DRIVER_NAME_DMA_CONTROLLER; - cell.num_resources = 2; - - memset(&resources, 0, sizeof(resources)); - - resources[0].start = engine_regs_offset; - resources[0].end = engine_regs_offset + (KPC_DMA_ENGINE_SIZE - 1); - resources[0].flags = IORESOURCE_MEM; - - resources[1].start = irq_num; - resources[1].end = irq_num; - resources[1].flags = IORESOURCE_IRQ; - - cell.resources = resources; - - return mfd_add_devices(PCARD_TO_DEV(pcard), // parent - pcard->card_num * 100, // id - &cell, // struct mfd_cell * - 1, // ndevs - &pcard->dma_base_resource, - 0, // irq_base - NULL); // struct irq_domain * -} - -static int kp2000_setup_dma_controller(struct kp2000_device *pcard) -{ - int err; - unsigned int i; - u64 capabilities_reg; - - // S2C Engines - for (i = 0 ; i < 32 ; i++) { - capabilities_reg = readq(pcard->dma_bar_base + - KPC_DMA_S2C_BASE_OFFSET + - (KPC_DMA_ENGINE_SIZE * i)); - - if (capabilities_reg & ENGINE_CAP_PRESENT_MASK) { - err = create_dma_engine_core(pcard, (KPC_DMA_S2C_BASE_OFFSET + - (KPC_DMA_ENGINE_SIZE * i)), - i, pcard->pdev->irq); - if (err) - goto err_out; - } - } - // C2S Engines - for (i = 0 ; i < 32 ; i++) { - capabilities_reg = readq(pcard->dma_bar_base + - KPC_DMA_C2S_BASE_OFFSET + - (KPC_DMA_ENGINE_SIZE * i)); - - if (capabilities_reg & ENGINE_CAP_PRESENT_MASK) { - err = create_dma_engine_core(pcard, (KPC_DMA_C2S_BASE_OFFSET + - (KPC_DMA_ENGINE_SIZE * i)), - 32 + i, pcard->pdev->irq); - if (err) - goto err_out; - } - } - - return 0; - -err_out: - dev_err(&pcard->pdev->dev, "%s: failed to add a DMA Engine: %d\n", - __func__, err); - return err; -} - -int kp2000_probe_cores(struct kp2000_device *pcard) -{ - int err = 0; - int i; - int current_type_id; - u64 read_val; - unsigned int highest_core_id = 0; - struct core_table_entry cte; - - err = kp2000_setup_dma_controller(pcard); - if (err) - return err; - - INIT_LIST_HEAD(&pcard->uio_devices_list); - - // First, iterate the core table looking for the highest CORE_ID - for (i = 0 ; i < pcard->core_table_length ; i++) { - read_val = readq(pcard->sysinfo_regs_base + ((pcard->core_table_offset + i) * 8)); - parse_core_table_entry(&cte, read_val, pcard->core_table_rev); - dbg_cte(pcard, &cte); - if (cte.type > highest_core_id) - highest_core_id = cte.type; - if (cte.type == KP_CORE_ID_INVALID) - dev_info(&pcard->pdev->dev, "Found Invalid core: %016llx\n", read_val); - } - // Then, iterate over the possible core types. - for (current_type_id = 1 ; current_type_id <= highest_core_id ; current_type_id++) { - unsigned int core_num = 0; - /* - * Foreach core type, iterate the whole table and instantiate - * subdevices for each core. - * Yes, this is O(n*m) but the actual runtime is small enough - * that it's an acceptable tradeoff. - */ - for (i = 0 ; i < pcard->core_table_length ; i++) { - read_val = readq(pcard->sysinfo_regs_base + - ((pcard->core_table_offset + i) * 8)); - parse_core_table_entry(&cte, read_val, pcard->core_table_rev); - - if (cte.type != current_type_id) - continue; - - switch (cte.type) { - case KP_CORE_ID_I2C: - err = probe_core_basic(core_num, pcard, - KP_DRIVER_NAME_I2C, cte); - break; - - case KP_CORE_ID_SPI: - err = probe_core_basic(core_num, pcard, - KP_DRIVER_NAME_SPI, cte); - break; - - default: - err = probe_core_uio(core_num, pcard, "kpc_uio", cte); - break; - } - if (err) { - dev_err(&pcard->pdev->dev, - "%s: failed to add core %d: %d\n", - __func__, i, err); - goto error; - } - core_num++; - } - } - - // Finally, instantiate a UIO device for the core_table. - cte.type = 0; // CORE_ID_BOARD_INFO - cte.offset = 0; // board info is always at the beginning - cte.length = 512 * 8; - cte.s2c_dma_present = false; - cte.s2c_dma_channel_num = 0; - cte.c2s_dma_present = false; - cte.c2s_dma_channel_num = 0; - cte.irq_count = 0; - cte.irq_base_num = 0; - err = probe_core_uio(0, pcard, "kpc_uio", cte); - if (err) { - dev_err(&pcard->pdev->dev, "%s: failed to add board_info core: %d\n", - __func__, err); - goto error; - } - - return 0; - -error: - kp2000_remove_cores(pcard); - mfd_remove_devices(PCARD_TO_DEV(pcard)); - return err; -} - -void kp2000_remove_cores(struct kp2000_device *pcard) -{ - struct list_head *ptr; - struct list_head *next; - - list_for_each_safe(ptr, next, &pcard->uio_devices_list) { - struct kpc_uio_device *kudev = list_entry(ptr, struct kpc_uio_device, list); - - uio_unregister_device(&kudev->uioinfo); - device_unregister(kudev->dev); - list_del(&kudev->list); - kfree(kudev); - } -} - diff --git a/drivers/staging/kpc2000/kpc2000/core.c b/drivers/staging/kpc2000/kpc2000/core.c deleted file mode 100644 index 6462a3059fb0..000000000000 --- a/drivers/staging/kpc2000/kpc2000/core.c +++ /dev/null @@ -1,565 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -#include <linux/kernel.h> -#include <linux/idr.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/types.h> -#include <linux/export.h> -#include <linux/slab.h> -#include <linux/fs.h> -#include <linux/errno.h> -#include <linux/cdev.h> -#include <linux/rwsem.h> -#include <linux/uaccess.h> -#include <linux/io.h> -#include <linux/mfd/core.h> -#include <linux/platform_device.h> -#include <linux/ioport.h> -#include <linux/io-64-nonatomic-lo-hi.h> -#include <linux/interrupt.h> -#include <linux/workqueue.h> -#include <linux/device.h> -#include <linux/sched.h> -#include <linux/jiffies.h> -#include "pcie.h" -#include "uapi.h" - -static DEFINE_IDA(card_num_ida); - -/******************************************************* - * SysFS Attributes - ******************************************************/ - -static ssize_t ssid_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%016llx\n", pcard->ssid); -} -static DEVICE_ATTR_RO(ssid); - -static ssize_t ddna_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%016llx\n", pcard->ddna); -} -static DEVICE_ATTR_RO(ddna); - -static ssize_t card_id_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%08x\n", pcard->card_id); -} -static DEVICE_ATTR_RO(card_id); - -static ssize_t hw_rev_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%08x\n", pcard->hardware_revision); -} -static DEVICE_ATTR_RO(hw_rev); - -static ssize_t build_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%08x\n", pcard->build_version); -} -static DEVICE_ATTR_RO(build); - -static ssize_t build_date_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%08x\n", pcard->build_datestamp); -} -static DEVICE_ATTR_RO(build_date); - -static ssize_t build_time_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%08x\n", pcard->build_timestamp); -} -static DEVICE_ATTR_RO(build_time); - -static ssize_t cpld_reg_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - u64 val; - - val = readq(pcard->sysinfo_regs_base + REG_CPLD_CONFIG); - return sprintf(buf, "%016llx\n", val); -} -static DEVICE_ATTR_RO(cpld_reg); - -static ssize_t cpld_reconfigure(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - unsigned long wr_val; - int rv; - - rv = kstrtoul(buf, 0, &wr_val); - if (rv < 0) - return rv; - if (wr_val > 7) - return -EINVAL; - - wr_val = wr_val << 8; - wr_val |= 0x1; // Set the "Configure Go" bit - writeq(wr_val, pcard->sysinfo_regs_base + REG_CPLD_CONFIG); - return count; -} - -static DEVICE_ATTR(cpld_reconfigure, 0220, NULL, cpld_reconfigure); - -static ssize_t irq_mask_reg_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - u64 val; - - val = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); - return sprintf(buf, "%016llx\n", val); -} -static DEVICE_ATTR_RO(irq_mask_reg); - -static ssize_t irq_active_reg_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - u64 val; - - val = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE); - return sprintf(buf, "%016llx\n", val); -} -static DEVICE_ATTR_RO(irq_active_reg); - -static ssize_t pcie_error_count_reg_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - u64 val; - - val = readq(pcard->sysinfo_regs_base + REG_PCIE_ERROR_COUNT); - return sprintf(buf, "%016llx\n", val); -} -static DEVICE_ATTR_RO(pcie_error_count_reg); - -static ssize_t core_table_offset_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%08x\n", pcard->core_table_offset); -} -static DEVICE_ATTR_RO(core_table_offset); - -static ssize_t core_table_length_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%08x\n", pcard->core_table_length); -} -static DEVICE_ATTR_RO(core_table_length); - -static const struct attribute *kp_attr_list[] = { - &dev_attr_ssid.attr, - &dev_attr_ddna.attr, - &dev_attr_card_id.attr, - &dev_attr_hw_rev.attr, - &dev_attr_build.attr, - &dev_attr_build_date.attr, - &dev_attr_build_time.attr, - &dev_attr_cpld_reg.attr, - &dev_attr_cpld_reconfigure.attr, - &dev_attr_irq_mask_reg.attr, - &dev_attr_irq_active_reg.attr, - &dev_attr_pcie_error_count_reg.attr, - &dev_attr_core_table_offset.attr, - &dev_attr_core_table_length.attr, - NULL, -}; - -/******************************************************* - * Functions - ******************************************************/ - -static void wait_and_read_ssid(struct kp2000_device *pcard) -{ - u64 read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID); - unsigned long timeout; - - if (read_val & 0x8000000000000000UL) { - pcard->ssid = read_val; - return; - } - - timeout = jiffies + (HZ * 2); - do { - read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID); - if (read_val & 0x8000000000000000UL) { - pcard->ssid = read_val; - return; - } - cpu_relax(); - //schedule(); - } while (time_before(jiffies, timeout)); - - dev_notice(&pcard->pdev->dev, "SSID didn't show up!\n"); - - // Timed out waiting for the SSID to show up, stick all zeros in the - // value - pcard->ssid = 0; -} - -static int read_system_regs(struct kp2000_device *pcard) -{ - u64 read_val; - - read_val = readq(pcard->sysinfo_regs_base + REG_MAGIC_NUMBER); - if (read_val != KP2000_MAGIC_VALUE) { - dev_err(&pcard->pdev->dev, - "Invalid magic! Got: 0x%016llx Want: 0x%016llx\n", - read_val, KP2000_MAGIC_VALUE); - return -EILSEQ; - } - - read_val = readq(pcard->sysinfo_regs_base + REG_CARD_ID_AND_BUILD); - pcard->card_id = (read_val & 0xFFFFFFFF00000000UL) >> 32; - pcard->build_version = (read_val & 0x00000000FFFFFFFFUL) >> 0; - - read_val = readq(pcard->sysinfo_regs_base + REG_DATE_AND_TIME_STAMPS); - pcard->build_datestamp = (read_val & 0xFFFFFFFF00000000UL) >> 32; - pcard->build_timestamp = (read_val & 0x00000000FFFFFFFFUL) >> 0; - - read_val = readq(pcard->sysinfo_regs_base + REG_CORE_TABLE_OFFSET); - pcard->core_table_length = (read_val & 0xFFFFFFFF00000000UL) >> 32; - pcard->core_table_offset = (read_val & 0x00000000FFFFFFFFUL) >> 0; - - wait_and_read_ssid(pcard); - - read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_HW_ID); - pcard->core_table_rev = (read_val & 0x0000000000000F00) >> 8; - pcard->hardware_revision = (read_val & 0x000000000000001F); - - read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_DDNA); - pcard->ddna = read_val; - - dev_info(&pcard->pdev->dev, - "system_regs: %08x %08x %08x %08x %02x %d %d %016llx %016llx\n", - pcard->card_id, - pcard->build_version, - pcard->build_datestamp, - pcard->build_timestamp, - pcard->hardware_revision, - pcard->core_table_rev, - pcard->core_table_length, - pcard->ssid, - pcard->ddna); - - if (pcard->core_table_rev > 1) { - dev_err(&pcard->pdev->dev, - "core table entry revision is higher than we can deal with, cannot continue with this card!\n"); - return 1; - } - - return 0; -} - -static irqreturn_t kp2000_irq_handler(int irq, void *dev_id) -{ - struct kp2000_device *pcard = dev_id; - - writel(KPC_DMA_CARD_IRQ_ENABLE | - KPC_DMA_CARD_USER_INTERRUPT_MODE | - KPC_DMA_CARD_USER_INTERRUPT_ACTIVE, - pcard->dma_common_regs); - return IRQ_HANDLED; -} - -static int kp2000_pcie_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - int err = 0; - struct kp2000_device *pcard; - unsigned long reg_bar_phys_addr; - unsigned long reg_bar_phys_len; - unsigned long dma_bar_phys_addr; - unsigned long dma_bar_phys_len; - u16 regval; - - pcard = kzalloc(sizeof(*pcard), GFP_KERNEL); - if (!pcard) - return -ENOMEM; - dev_dbg(&pdev->dev, "probe: allocated struct kp2000_device @ %p\n", - pcard); - - err = ida_simple_get(&card_num_ida, 1, INT_MAX, GFP_KERNEL); - if (err < 0) { - dev_err(&pdev->dev, "probe: failed to get card number (%d)\n", - err); - goto err_free_pcard; - } - pcard->card_num = err; - scnprintf(pcard->name, 16, "kpcard%u", pcard->card_num); - - mutex_init(&pcard->sem); - mutex_lock(&pcard->sem); - - pcard->pdev = pdev; - pci_set_drvdata(pdev, pcard); - - err = pci_enable_device(pcard->pdev); - if (err) { - dev_err(&pcard->pdev->dev, - "probe: failed to enable PCIE2000 PCIe device (%d)\n", - err); - goto err_remove_ida; - } - - /* Setup the Register BAR */ - reg_bar_phys_addr = pci_resource_start(pcard->pdev, REG_BAR); - reg_bar_phys_len = pci_resource_len(pcard->pdev, REG_BAR); - - pcard->regs_bar_base = ioremap(reg_bar_phys_addr, PAGE_SIZE); - if (!pcard->regs_bar_base) { - dev_err(&pcard->pdev->dev, - "probe: REG_BAR could not remap memory to virtual space\n"); - err = -ENODEV; - goto err_disable_device; - } - dev_dbg(&pcard->pdev->dev, - "probe: REG_BAR virt hardware address start [%p]\n", - pcard->regs_bar_base); - - err = pci_request_region(pcard->pdev, REG_BAR, KP_DRIVER_NAME_KP2000); - if (err) { - dev_err(&pcard->pdev->dev, - "probe: failed to acquire PCI region (%d)\n", - err); - err = -ENODEV; - goto err_unmap_regs; - } - - pcard->regs_base_resource.start = reg_bar_phys_addr; - pcard->regs_base_resource.end = reg_bar_phys_addr + - reg_bar_phys_len - 1; - pcard->regs_base_resource.flags = IORESOURCE_MEM; - - /* Setup the DMA BAR */ - dma_bar_phys_addr = pci_resource_start(pcard->pdev, DMA_BAR); - dma_bar_phys_len = pci_resource_len(pcard->pdev, DMA_BAR); - - pcard->dma_bar_base = ioremap(dma_bar_phys_addr, - dma_bar_phys_len); - if (!pcard->dma_bar_base) { - dev_err(&pcard->pdev->dev, - "probe: DMA_BAR could not remap memory to virtual space\n"); - err = -ENODEV; - goto err_release_regs; - } - dev_dbg(&pcard->pdev->dev, - "probe: DMA_BAR virt hardware address start [%p]\n", - pcard->dma_bar_base); - - pcard->dma_common_regs = pcard->dma_bar_base + KPC_DMA_COMMON_OFFSET; - - err = pci_request_region(pcard->pdev, DMA_BAR, "kp2000_pcie"); - if (err) { - dev_err(&pcard->pdev->dev, - "probe: failed to acquire PCI region (%d)\n", err); - err = -ENODEV; - goto err_unmap_dma; - } - - pcard->dma_base_resource.start = dma_bar_phys_addr; - pcard->dma_base_resource.end = dma_bar_phys_addr + - dma_bar_phys_len - 1; - pcard->dma_base_resource.flags = IORESOURCE_MEM; - - /* Read System Regs */ - pcard->sysinfo_regs_base = pcard->regs_bar_base; - err = read_system_regs(pcard); - if (err) - goto err_release_dma; - - // Disable all "user" interrupts because they're not used yet. - writeq(0xFFFFFFFFFFFFFFFFUL, - pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); - - // let the card master PCIe - pci_set_master(pcard->pdev); - - // enable IO and mem if not already done - pci_read_config_word(pcard->pdev, PCI_COMMAND, ®val); - regval |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY); - pci_write_config_word(pcard->pdev, PCI_COMMAND, regval); - - // Clear relaxed ordering bit - pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_RELAX_EN, 0); - - // Set Max_Payload_Size and Max_Read_Request_Size - regval = (0x0) << 5; // Max_Payload_Size = 128 B - pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_PAYLOAD, regval); - regval = (0x0) << 12; // Max_Read_Request_Size = 128 B - pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_READRQ, regval); - - // Enable error reporting for: Correctable Errors, Non-Fatal Errors, - // Fatal Errors, Unsupported Requests - pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, 0, - PCI_EXP_DEVCTL_CERE | - PCI_EXP_DEVCTL_NFERE | - PCI_EXP_DEVCTL_FERE | - PCI_EXP_DEVCTL_URRE); - - err = dma_set_mask(PCARD_TO_DEV(pcard), DMA_BIT_MASK(64)); - if (err) { - dev_err(&pcard->pdev->dev, - "CANNOT use DMA mask %0llx\n", DMA_BIT_MASK(64)); - goto err_release_dma; - } - dev_dbg(&pcard->pdev->dev, - "Using DMA mask %0llx\n", dma_get_mask(PCARD_TO_DEV(pcard))); - - err = pci_enable_msi(pcard->pdev); - if (err < 0) - goto err_release_dma; - - err = request_irq(pcard->pdev->irq, kp2000_irq_handler, IRQF_SHARED, - pcard->name, pcard); - if (err) { - dev_err(&pcard->pdev->dev, - "%s: failed to request_irq: %d\n", __func__, err); - goto err_disable_msi; - } - - err = sysfs_create_files(&pdev->dev.kobj, kp_attr_list); - if (err) { - dev_err(&pdev->dev, "Failed to add sysfs files: %d\n", err); - goto err_free_irq; - } - - err = kp2000_probe_cores(pcard); - if (err) - goto err_remove_sysfs; - - /* Enable IRQs in HW */ - writel(KPC_DMA_CARD_IRQ_ENABLE | KPC_DMA_CARD_USER_INTERRUPT_MODE, - pcard->dma_common_regs); - - mutex_unlock(&pcard->sem); - return 0; - -err_remove_sysfs: - sysfs_remove_files(&pdev->dev.kobj, kp_attr_list); -err_free_irq: - free_irq(pcard->pdev->irq, pcard); -err_disable_msi: - pci_disable_msi(pcard->pdev); -err_release_dma: - pci_release_region(pdev, DMA_BAR); -err_unmap_dma: - iounmap(pcard->dma_bar_base); -err_release_regs: - pci_release_region(pdev, REG_BAR); -err_unmap_regs: - iounmap(pcard->regs_bar_base); -err_disable_device: - pci_disable_device(pcard->pdev); -err_remove_ida: - mutex_unlock(&pcard->sem); - ida_simple_remove(&card_num_ida, pcard->card_num); -err_free_pcard: - kfree(pcard); - return err; -} - -static void kp2000_pcie_remove(struct pci_dev *pdev) -{ - struct kp2000_device *pcard = pci_get_drvdata(pdev); - - if (!pcard) - return; - - mutex_lock(&pcard->sem); - kp2000_remove_cores(pcard); - mfd_remove_devices(PCARD_TO_DEV(pcard)); - sysfs_remove_files(&pdev->dev.kobj, kp_attr_list); - free_irq(pcard->pdev->irq, pcard); - pci_disable_msi(pcard->pdev); - if (pcard->dma_bar_base) { - iounmap(pcard->dma_bar_base); - pci_release_region(pdev, DMA_BAR); - pcard->dma_bar_base = NULL; - } - if (pcard->regs_bar_base) { - iounmap(pcard->regs_bar_base); - pci_release_region(pdev, REG_BAR); - pcard->regs_bar_base = NULL; - } - pci_disable_device(pcard->pdev); - pci_set_drvdata(pdev, NULL); - mutex_unlock(&pcard->sem); - ida_simple_remove(&card_num_ida, pcard->card_num); - kfree(pcard); -} - -struct class *kpc_uio_class; -ATTRIBUTE_GROUPS(kpc_uio_class); - -static const struct pci_device_id kp2000_pci_device_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_DAKTRONICS, PCI_DEVICE_ID_DAKTRONICS) }, - { PCI_DEVICE(PCI_VENDOR_ID_DAKTRONICS, PCI_DEVICE_ID_DAKTRONICS_KADOKA_P2KR0) }, - { 0, } -}; -MODULE_DEVICE_TABLE(pci, kp2000_pci_device_ids); - -static struct pci_driver kp2000_driver_inst = { - .name = "kp2000_pcie", - .id_table = kp2000_pci_device_ids, - .probe = kp2000_pcie_probe, - .remove = kp2000_pcie_remove, -}; - -static int __init kp2000_pcie_init(void) -{ - kpc_uio_class = class_create(THIS_MODULE, "kpc_uio"); - if (IS_ERR(kpc_uio_class)) - return PTR_ERR(kpc_uio_class); - - kpc_uio_class->dev_groups = kpc_uio_class_groups; - return pci_register_driver(&kp2000_driver_inst); -} -module_init(kp2000_pcie_init); - -static void __exit kp2000_pcie_exit(void) -{ - pci_unregister_driver(&kp2000_driver_inst); - class_destroy(kpc_uio_class); - ida_destroy(&card_num_ida); -} -module_exit(kp2000_pcie_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Lee.Brooke@Daktronics.com, Matt.Sickler@Daktronics.com"); -MODULE_SOFTDEP("pre: uio post: kpc_nwl_dma kpc_i2c kpc_spi"); diff --git a/drivers/staging/kpc2000/kpc2000/dma_common_defs.h b/drivers/staging/kpc2000/kpc2000/dma_common_defs.h deleted file mode 100644 index 613c4898f65e..000000000000 --- a/drivers/staging/kpc2000/kpc2000/dma_common_defs.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -#ifndef KPC_DMA_COMMON_DEFS_H_ -#define KPC_DMA_COMMON_DEFS_H_ - -#define KPC_DMA_COMMON_OFFSET 0x4000 -#define KPC_DMA_S2C_BASE_OFFSET 0x0000 -#define KPC_DMA_C2S_BASE_OFFSET 0x2000 -#define KPC_DMA_ENGINE_SIZE 0x0100 -#define ENGINE_CAP_PRESENT_MASK 0x1 - -#define KPC_DMA_CARD_IRQ_ENABLE BIT(0) -#define KPC_DMA_CARD_IRQ_ACTIVE BIT(1) -#define KPC_DMA_CARD_IRQ_PENDING BIT(2) -#define KPC_DMA_CARD_IRQ_MSI BIT(3) -#define KPC_DMA_CARD_USER_INTERRUPT_MODE BIT(4) -#define KPC_DMA_CARD_USER_INTERRUPT_ACTIVE BIT(5) -#define KPC_DMA_CARD_IRQ_MSIX_MODE BIT(6) -#define KPC_DMA_CARD_MAX_PAYLOAD_SIZE_MASK 0x0700 -#define KPC_DMA_CARD_MAX_READ_REQUEST_SIZE_MASK 0x7000 -#define KPC_DMA_CARD_S2C_INTERRUPT_STATUS_MASK 0x00FF0000 -#define KPC_DMA_CARD_C2S_INTERRUPT_STATUS_MASK 0xFF000000 - -#endif /* KPC_DMA_COMMON_DEFS_H_ */ diff --git a/drivers/staging/kpc2000/kpc2000/pcie.h b/drivers/staging/kpc2000/kpc2000/pcie.h deleted file mode 100644 index f1fc91b4c704..000000000000 --- a/drivers/staging/kpc2000/kpc2000/pcie.h +++ /dev/null @@ -1,90 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -#ifndef KP2000_PCIE_H -#define KP2000_PCIE_H -#include <linux/types.h> -#include <linux/pci.h> -#include "../kpc.h" -#include "dma_common_defs.h" - -/* System Register Map (BAR 1, Start Addr 0) - * - * BAR Size: - * 1048576 (0x100000) bytes = 131072 (0x20000) registers = 256 pages (4K) - * - * 6 5 4 3 2 1 0 - * 3210987654321098765432109876543210987654321098765432109876543210 - * 0 <--------------------------- MAGIC ----------------------------> - * 1 <----------- Card ID ---------><----------- Revision ----------> - * 2 <--------- Date Stamp --------><--------- Time Stamp ----------> - * 3 <-------- Core Tbl Len -------><-------- Core Tbl Offset ------> - * 4 <---------------------------- SSID ----------------------------> - * 5 < HWID > - * 6 <------------------------- FPGA DDNA --------------------------> - * 7 <------------------------ CPLD Config -------------------------> - * 8 <----------------------- IRQ Mask Flags -----------------------> - * 9 <---------------------- IRQ Active Flags ----------------------> - */ - -#define REG_WIDTH 8 -#define REG_MAGIC_NUMBER (0 * REG_WIDTH) -#define REG_CARD_ID_AND_BUILD (1 * REG_WIDTH) -#define REG_DATE_AND_TIME_STAMPS (2 * REG_WIDTH) -#define REG_CORE_TABLE_OFFSET (3 * REG_WIDTH) -#define REG_FPGA_SSID (4 * REG_WIDTH) -#define REG_FPGA_HW_ID (5 * REG_WIDTH) -#define REG_FPGA_DDNA (6 * REG_WIDTH) -#define REG_CPLD_CONFIG (7 * REG_WIDTH) -#define REG_INTERRUPT_MASK (8 * REG_WIDTH) -#define REG_INTERRUPT_ACTIVE (9 * REG_WIDTH) -#define REG_PCIE_ERROR_COUNT (10 * REG_WIDTH) - -#define KP2000_MAGIC_VALUE 0x196C61482231894DULL - -#define PCI_VENDOR_ID_DAKTRONICS 0x1c33 -#define PCI_DEVICE_ID_DAKTRONICS 0x6021 - -#define DMA_BAR 0 -#define REG_BAR 1 - -struct kp2000_device { - struct pci_dev *pdev; - char name[16]; - - unsigned int card_num; - struct mutex sem; - - void __iomem *sysinfo_regs_base; - void __iomem *regs_bar_base; - struct resource regs_base_resource; - void __iomem *dma_bar_base; - void __iomem *dma_common_regs; - struct resource dma_base_resource; - - // "System Registers" - u32 card_id; - u32 build_version; - u32 build_datestamp; - u32 build_timestamp; - u32 core_table_offset; - u32 core_table_length; - u8 core_table_rev; - u8 hardware_revision; - u64 ssid; - u64 ddna; - - // IRQ stuff - unsigned int irq; - - struct list_head uio_devices_list; -}; - -extern struct class *kpc_uio_class; -extern struct attribute *kpc_uio_class_attrs[]; - -int kp2000_probe_cores(struct kp2000_device *pcard); -void kp2000_remove_cores(struct kp2000_device *pcard); - -// Define this quick little macro because the expression is used frequently -#define PCARD_TO_DEV(pcard) (&(pcard->pdev->dev)) - -#endif /* KP2000_PCIE_H */ diff --git a/drivers/staging/kpc2000/kpc2000/uapi.h b/drivers/staging/kpc2000/kpc2000/uapi.h deleted file mode 100644 index 16f37f002dc6..000000000000 --- a/drivers/staging/kpc2000/kpc2000/uapi.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -#ifndef KP2000_CDEV_UAPI_H_ -#define KP2000_CDEV_UAPI_H_ -#include <linux/types.h> -#include <linux/ioctl.h> - -struct kp2000_regs { - __u32 card_id; - __u32 build_version; - __u32 build_datestamp; - __u32 build_timestamp; - __u32 hw_rev; - __u64 ssid; - __u64 ddna; - __u64 cpld_reg; -}; - -#define KP2000_IOCTL_GET_CPLD_REG _IOR('k', 9, __u32) -#define KP2000_IOCTL_GET_PCIE_ERROR_REG _IOR('k', 11, __u32) -#define KP2000_IOCTL_GET_EVERYTHING _IOR('k', 8, struct kp2000_regs*) - -#endif /* KP2000_CDEV_UAPI_H_ */ diff --git a/drivers/staging/kpc2000/kpc2000_i2c.c b/drivers/staging/kpc2000/kpc2000_i2c.c deleted file mode 100644 index 14f7940fa4fb..000000000000 --- a/drivers/staging/kpc2000/kpc2000_i2c.c +++ /dev/null @@ -1,731 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * KPC2000 i2c driver - * - * Adapted i2c-i801.c for use with Kadoka hardware. - * - * Copyright (C) 1998 - 2002 - * Frodo Looijaard <frodol@dds.nl>, - * Philip Edelbrock <phil@netroedge.com>, - * Mark D. Studebaker <mdsxyz123@yahoo.com> - * Copyright (C) 2007 - 2012 - * Jean Delvare <khali@linux-fr.org> - * Copyright (C) 2010 Intel Corporation - * David Woodhouse <dwmw2@infradead.org> - * Copyright (C) 2014-2018 Daktronics - * Matt Sickler <matt.sickler@daktronics.com>, - * Jordon Hofer <jordon.hofer@daktronics.com> - */ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/io.h> -#include <linux/io-64-nonatomic-lo-hi.h> -#include <linux/export.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <linux/fs.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include "kpc.h" - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Matt.Sickler@Daktronics.com"); - -struct kpc_i2c { - unsigned long smba; - struct i2c_adapter adapter; - unsigned int features; -}; - -/***************************** - *** Part 1 - i2c Handlers *** - *****************************/ - -#define REG_SIZE 8 - -/* I801 SMBus address offsets */ -#define SMBHSTSTS(p) ((0 * REG_SIZE) + (p)->smba) -#define SMBHSTCNT(p) ((2 * REG_SIZE) + (p)->smba) -#define SMBHSTCMD(p) ((3 * REG_SIZE) + (p)->smba) -#define SMBHSTADD(p) ((4 * REG_SIZE) + (p)->smba) -#define SMBHSTDAT0(p) ((5 * REG_SIZE) + (p)->smba) -#define SMBHSTDAT1(p) ((6 * REG_SIZE) + (p)->smba) -#define SMBBLKDAT(p) ((7 * REG_SIZE) + (p)->smba) -#define SMBPEC(p) ((8 * REG_SIZE) + (p)->smba) /* ICH3 and later */ -#define SMBAUXSTS(p) ((12 * REG_SIZE) + (p)->smba) /* ICH4 and later */ -#define SMBAUXCTL(p) ((13 * REG_SIZE) + (p)->smba) /* ICH4 and later */ - -/* PCI Address Constants */ -#define SMBBAR 4 -#define SMBHSTCFG 0x040 - -/* Host configuration bits for SMBHSTCFG */ -#define SMBHSTCFG_HST_EN 1 -#define SMBHSTCFG_SMB_SMI_EN 2 -#define SMBHSTCFG_I2C_EN 4 - -/* Auxiliary control register bits, ICH4+ only */ -#define SMBAUXCTL_CRC 1 -#define SMBAUXCTL_E32B 2 - -/* kill bit for SMBHSTCNT */ -#define SMBHSTCNT_KILL 2 - -/* Other settings */ -#define MAX_RETRIES 400 -#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */ - -/* I801 command constants */ -#define I801_QUICK 0x00 -#define I801_BYTE 0x04 -#define I801_BYTE_DATA 0x08 -#define I801_WORD_DATA 0x0C -#define I801_PROC_CALL 0x10 /* unimplemented */ -#define I801_BLOCK_DATA 0x14 -#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */ -#define I801_BLOCK_LAST 0x34 -#define I801_I2C_BLOCK_LAST 0x38 /* ICH5 and later */ -#define I801_START 0x40 -#define I801_PEC_EN 0x80 /* ICH3 and later */ - -/* I801 Hosts Status register bits */ -#define SMBHSTSTS_BYTE_DONE 0x80 -#define SMBHSTSTS_INUSE_STS 0x40 -#define SMBHSTSTS_SMBALERT_STS 0x20 -#define SMBHSTSTS_FAILED 0x10 -#define SMBHSTSTS_BUS_ERR 0x08 -#define SMBHSTSTS_DEV_ERR 0x04 -#define SMBHSTSTS_INTR 0x02 -#define SMBHSTSTS_HOST_BUSY 0x01 - -#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_FAILED | \ - SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | SMBHSTSTS_INTR) - -/* Older devices have their ID defined in <linux/pci_ids.h> */ -#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22 -#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22 -/* Patsburg also has three 'Integrated Device Function' SMBus controllers */ -#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0 0x1d70 -#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1 0x1d71 -#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2 0x1d72 -#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS 0x1e22 -#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330 -#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30 -#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 -#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22 - -#define FEATURE_SMBUS_PEC BIT(0) -#define FEATURE_BLOCK_BUFFER BIT(1) -#define FEATURE_BLOCK_PROC BIT(2) -#define FEATURE_I2C_BLOCK_READ BIT(3) -/* Not really a feature, but it's convenient to handle it as such */ -#define FEATURE_IDF BIT(15) - -// FIXME! -#undef inb_p -#define inb_p(a) readq((void __iomem *)a) -#undef outb_p -#define outb_p(d, a) writeq(d, (void __iomem *)a) - -/* Make sure the SMBus host is ready to start transmitting. - * Return 0 if it is, -EBUSY if it is not. - */ -static int i801_check_pre(struct kpc_i2c *priv) -{ - int status; - - status = inb_p(SMBHSTSTS(priv)); - if (status & SMBHSTSTS_HOST_BUSY) { - dev_err(&priv->adapter.dev, - "SMBus is busy, can't use it! (status=%x)\n", status); - return -EBUSY; - } - - status &= STATUS_FLAGS; - if (status) { - outb_p(status, SMBHSTSTS(priv)); - status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS; - if (status) { - dev_err(&priv->adapter.dev, - "Failed clearing status flags (%02x)\n", status); - return -EBUSY; - } - } - return 0; -} - -/* Convert the status register to an error code, and clear it. */ -static int i801_check_post(struct kpc_i2c *priv, int status, int timeout) -{ - int result = 0; - - /* If the SMBus is still busy, we give up */ - if (timeout) { - dev_err(&priv->adapter.dev, "Transaction timeout\n"); - /* try to stop the current command */ - dev_dbg(&priv->adapter.dev, - "Terminating the current operation\n"); - outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL, - SMBHSTCNT(priv)); - usleep_range(1000, 2000); - outb_p(inb_p(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL), - SMBHSTCNT(priv)); - - /* Check if it worked */ - status = inb_p(SMBHSTSTS(priv)); - if ((status & SMBHSTSTS_HOST_BUSY) || - !(status & SMBHSTSTS_FAILED)) - dev_err(&priv->adapter.dev, - "Failed terminating the transaction\n"); - outb_p(STATUS_FLAGS, SMBHSTSTS(priv)); - return -ETIMEDOUT; - } - - if (status & SMBHSTSTS_FAILED) { - result = -EIO; - dev_err(&priv->adapter.dev, "Transaction failed\n"); - } - if (status & SMBHSTSTS_DEV_ERR) { - result = -ENXIO; - dev_dbg(&priv->adapter.dev, "No response\n"); - } - if (status & SMBHSTSTS_BUS_ERR) { - result = -EAGAIN; - dev_dbg(&priv->adapter.dev, "Lost arbitration\n"); - } - - if (result) { - /* Clear error flags */ - outb_p(status & STATUS_FLAGS, SMBHSTSTS(priv)); - status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS; - if (status) - dev_warn(&priv->adapter.dev, - "Failed clearing status flags at end of transaction (%02x)\n", - status); - } - - return result; -} - -static int i801_transaction(struct kpc_i2c *priv, int xact) -{ - int status; - int result; - int timeout = 0; - - result = i801_check_pre(priv); - if (result < 0) - return result; - /* the current contents of SMBHSTCNT can be overwritten, since PEC, - * INTREN, SMBSCMD are passed in xact - */ - outb_p(xact | I801_START, SMBHSTCNT(priv)); - - /* We will always wait for a fraction of a second! */ - do { - usleep_range(250, 500); - status = inb_p(SMBHSTSTS(priv)); - } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_RETRIES)); - - result = i801_check_post(priv, status, timeout > MAX_RETRIES); - if (result < 0) - return result; - - outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv)); - return 0; -} - -/* wait for INTR bit as advised by Intel */ -static void i801_wait_hwpec(struct kpc_i2c *priv) -{ - int timeout = 0; - int status; - - do { - usleep_range(250, 500); - status = inb_p(SMBHSTSTS(priv)); - } while ((!(status & SMBHSTSTS_INTR)) && (timeout++ < MAX_RETRIES)); - - if (timeout > MAX_RETRIES) - dev_dbg(&priv->adapter.dev, "PEC Timeout!\n"); - - outb_p(status, SMBHSTSTS(priv)); -} - -static int i801_block_transaction_by_block(struct kpc_i2c *priv, - union i2c_smbus_data *data, - char read_write, int hwpec) -{ - int i, len; - int status; - - inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */ - - /* Use 32-byte buffer to process this transaction */ - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - outb_p(len, SMBHSTDAT0(priv)); - for (i = 0; i < len; i++) - outb_p(data->block[i + 1], SMBBLKDAT(priv)); - } - - status = i801_transaction(priv, - I801_BLOCK_DATA | ENABLE_INT9 | I801_PEC_EN * hwpec); - if (status) - return status; - - if (read_write == I2C_SMBUS_READ) { - len = inb_p(SMBHSTDAT0(priv)); - if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) - return -EPROTO; - - data->block[0] = len; - for (i = 0; i < len; i++) - data->block[i + 1] = inb_p(SMBBLKDAT(priv)); - } - return 0; -} - -static int i801_block_transaction_byte_by_byte(struct kpc_i2c *priv, - union i2c_smbus_data *data, - char read_write, int command, - int hwpec) -{ - int i, len; - int smbcmd; - int status; - int result; - int timeout; - - result = i801_check_pre(priv); - if (result < 0) - return result; - - len = data->block[0]; - - if (read_write == I2C_SMBUS_WRITE) { - outb_p(len, SMBHSTDAT0(priv)); - outb_p(data->block[1], SMBBLKDAT(priv)); - } - - for (i = 1; i <= len; i++) { - if (i == len && read_write == I2C_SMBUS_READ) { - if (command == I2C_SMBUS_I2C_BLOCK_DATA) - smbcmd = I801_I2C_BLOCK_LAST; - else - smbcmd = I801_BLOCK_LAST; - } else { - if (command == I2C_SMBUS_I2C_BLOCK_DATA && - read_write == I2C_SMBUS_READ) - smbcmd = I801_I2C_BLOCK_DATA; - else - smbcmd = I801_BLOCK_DATA; - } - outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT(priv)); - - if (i == 1) - outb_p(inb(SMBHSTCNT(priv)) | I801_START, - SMBHSTCNT(priv)); - /* We will always wait for a fraction of a second! */ - timeout = 0; - do { - usleep_range(250, 500); - status = inb_p(SMBHSTSTS(priv)); - } while (!(status & SMBHSTSTS_BYTE_DONE) && - (timeout++ < MAX_RETRIES)); - - result = i801_check_post(priv, status, timeout > MAX_RETRIES); - if (result < 0) - return result; - if (i == 1 && read_write == I2C_SMBUS_READ && - command != I2C_SMBUS_I2C_BLOCK_DATA) { - len = inb_p(SMBHSTDAT0(priv)); - if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) { - dev_err(&priv->adapter.dev, - "Illegal SMBus block read size %d\n", - len); - /* Recover */ - while (inb_p(SMBHSTSTS(priv)) & - SMBHSTSTS_HOST_BUSY) - outb_p(SMBHSTSTS_BYTE_DONE, - SMBHSTSTS(priv)); - outb_p(SMBHSTSTS_INTR, - SMBHSTSTS(priv)); - return -EPROTO; - } - data->block[0] = len; - } - - /* Retrieve/store value in SMBBLKDAT */ - if (read_write == I2C_SMBUS_READ) - data->block[i] = inb_p(SMBBLKDAT(priv)); - if (read_write == I2C_SMBUS_WRITE && i + 1 <= len) - outb_p(data->block[i + 1], SMBBLKDAT(priv)); - /* signals SMBBLKDAT ready */ - outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS(priv)); - } - - return 0; -} - -static int i801_set_block_buffer_mode(struct kpc_i2c *priv) -{ - outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv)); - if ((inb_p(SMBAUXCTL(priv)) & SMBAUXCTL_E32B) == 0) - return -EIO; - return 0; -} - -/* Block transaction function */ -static int i801_block_transaction(struct kpc_i2c *priv, - union i2c_smbus_data *data, char read_write, - int command, int hwpec) -{ - int result = 0; - //unsigned char hostc; - - if (command == I2C_SMBUS_I2C_BLOCK_DATA) { - if (read_write == I2C_SMBUS_WRITE) { - /* set I2C_EN bit in configuration register */ - //TODO: Figure out the right thing to do here... - //pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc); - //pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc | SMBHSTCFG_I2C_EN); - } else if (!(priv->features & FEATURE_I2C_BLOCK_READ)) { - dev_err(&priv->adapter.dev, - "I2C block read is unsupported!\n"); - return -EOPNOTSUPP; - } - } - - if (read_write == I2C_SMBUS_WRITE || - command == I2C_SMBUS_I2C_BLOCK_DATA) { - if (data->block[0] < 1) - data->block[0] = 1; - if (data->block[0] > I2C_SMBUS_BLOCK_MAX) - data->block[0] = I2C_SMBUS_BLOCK_MAX; - } else { - data->block[0] = 32; /* max for SMBus block reads */ - } - - /* Experience has shown that the block buffer can only be used for - * SMBus (not I2C) block transactions, even though the datasheet - * doesn't mention this limitation. - */ - if ((priv->features & FEATURE_BLOCK_BUFFER) && - command != I2C_SMBUS_I2C_BLOCK_DATA && - i801_set_block_buffer_mode(priv) == 0) { - result = i801_block_transaction_by_block(priv, data, - read_write, hwpec); - } else { - result = i801_block_transaction_byte_by_byte(priv, data, - read_write, - command, hwpec); - } - - if (result == 0 && hwpec) - i801_wait_hwpec(priv); - if (command == I2C_SMBUS_I2C_BLOCK_DATA && - read_write == I2C_SMBUS_WRITE) { - /* restore saved configuration register value */ - //TODO: Figure out the right thing to do here... - //pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc); - } - return result; -} - -/* Return negative errno on error. */ -static s32 i801_access(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, u8 command, - int size, union i2c_smbus_data *data) -{ - int hwpec; - int block = 0; - int ret, xact = 0; - struct kpc_i2c *priv = i2c_get_adapdata(adap); - - hwpec = (priv->features & FEATURE_SMBUS_PEC) && - (flags & I2C_CLIENT_PEC) && - size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA; - - switch (size) { - case I2C_SMBUS_QUICK: - dev_dbg(&priv->adapter.dev, " [acc] SMBUS_QUICK\n"); - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD(priv)); - - xact = I801_QUICK; - break; - case I2C_SMBUS_BYTE: - dev_dbg(&priv->adapter.dev, " [acc] SMBUS_BYTE\n"); - - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD(priv)); - if (read_write == I2C_SMBUS_WRITE) - outb_p(command, SMBHSTCMD(priv)); - xact = I801_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - dev_dbg(&priv->adapter.dev, " [acc] SMBUS_BYTE_DATA\n"); - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD(priv)); - - outb_p(command, SMBHSTCMD(priv)); - if (read_write == I2C_SMBUS_WRITE) - outb_p(data->byte, SMBHSTDAT0(priv)); - xact = I801_BYTE_DATA; - break; - case I2C_SMBUS_WORD_DATA: - dev_dbg(&priv->adapter.dev, " [acc] SMBUS_WORD_DATA\n"); - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD(priv)); - - outb_p(command, SMBHSTCMD(priv)); - if (read_write == I2C_SMBUS_WRITE) { - outb_p(data->word & 0xff, SMBHSTDAT0(priv)); - outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv)); - } - xact = I801_WORD_DATA; - break; - case I2C_SMBUS_BLOCK_DATA: - dev_dbg(&priv->adapter.dev, " [acc] SMBUS_BLOCK_DATA\n"); - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD(priv)); - - outb_p(command, SMBHSTCMD(priv)); - block = 1; - break; - case I2C_SMBUS_I2C_BLOCK_DATA: - dev_dbg(&priv->adapter.dev, " [acc] SMBUS_I2C_BLOCK_DATA\n"); - /* NB: page 240 of ICH5 datasheet shows that the R/#W - * bit should be cleared here, even when reading - */ - outb_p((addr & 0x7f) << 1, SMBHSTADD(priv)); - if (read_write == I2C_SMBUS_READ) { - /* NB: page 240 of ICH5 datasheet also shows - * that DATA1 is the cmd field when reading - */ - outb_p(command, SMBHSTDAT1(priv)); - } else { - outb_p(command, SMBHSTCMD(priv)); - } - block = 1; - break; - default: - dev_dbg(&priv->adapter.dev, - " [acc] Unsupported transaction %d\n", size); - return -EOPNOTSUPP; - } - - if (hwpec) { /* enable/disable hardware PEC */ - dev_dbg(&priv->adapter.dev, " [acc] hwpec: yes\n"); - outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv)); - } else { - dev_dbg(&priv->adapter.dev, " [acc] hwpec: no\n"); - outb_p(inb_p(SMBAUXCTL(priv)) & - (~SMBAUXCTL_CRC), SMBAUXCTL(priv)); - } - - if (block) { - dev_dbg(&priv->adapter.dev, " [acc] block: yes\n"); - ret = i801_block_transaction(priv, data, read_write, size, - hwpec); - } else { - dev_dbg(&priv->adapter.dev, " [acc] block: no\n"); - ret = i801_transaction(priv, xact | ENABLE_INT9); - } - - /* Some BIOSes don't like it when PEC is enabled at reboot or resume - * time, so we forcibly disable it after every transaction. Turn off - * E32B for the same reason. - */ - if (hwpec || block) { - dev_dbg(&priv->adapter.dev, " [acc] hwpec || block\n"); - outb_p(inb_p(SMBAUXCTL(priv)) & ~(SMBAUXCTL_CRC | - SMBAUXCTL_E32B), SMBAUXCTL(priv)); - } - if (block) { - dev_dbg(&priv->adapter.dev, " [acc] block\n"); - return ret; - } - if (ret) { - dev_dbg(&priv->adapter.dev, " [acc] ret %d\n", ret); - return ret; - } - if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK)) { - dev_dbg(&priv->adapter.dev, - " [acc] I2C_SMBUS_WRITE || I801_QUICK -> ret 0\n"); - return 0; - } - - switch (xact & 0x7f) { - case I801_BYTE: /* Result put in SMBHSTDAT0 */ - case I801_BYTE_DATA: - dev_dbg(&priv->adapter.dev, - " [acc] I801_BYTE or I801_BYTE_DATA\n"); - data->byte = inb_p(SMBHSTDAT0(priv)); - break; - case I801_WORD_DATA: - dev_dbg(&priv->adapter.dev, " [acc] I801_WORD_DATA\n"); - data->word = inb_p(SMBHSTDAT0(priv)) + - (inb_p(SMBHSTDAT1(priv)) << 8); - break; - } - return 0; -} - -#define enable_flag(x) (x) -#define disable_flag(x) 0 -#define enable_flag_if(x, cond) ((cond) ? (x) : 0) - -static u32 i801_func(struct i2c_adapter *adapter) -{ - struct kpc_i2c *priv = i2c_get_adapdata(adapter); - - /* original settings - * u32 f = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - * I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - * I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK | - * ((priv->features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) | - * ((priv->features & FEATURE_I2C_BLOCK_READ) ? - * I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0); - */ - - // http://lxr.free-electrons.com/source/include/uapi/linux/i2c.h#L85 - - u32 f = - enable_flag(I2C_FUNC_I2C) | /* 0x00000001(I enabled this one) */ - disable_flag(I2C_FUNC_10BIT_ADDR) | /* 0x00000002 */ - disable_flag(I2C_FUNC_PROTOCOL_MANGLING) | /* 0x00000004 */ - enable_flag_if(I2C_FUNC_SMBUS_PEC, - priv->features & FEATURE_SMBUS_PEC) | - /* 0x00000008 */ - disable_flag(I2C_FUNC_SMBUS_BLOCK_PROC_CALL) | /* 0x00008000 */ - enable_flag(I2C_FUNC_SMBUS_QUICK) | /* 0x00010000 */ - disable_flag(I2C_FUNC_SMBUS_READ_BYTE) | /* 0x00020000 */ - disable_flag(I2C_FUNC_SMBUS_WRITE_BYTE) | /* 0x00040000 */ - disable_flag(I2C_FUNC_SMBUS_READ_BYTE_DATA) | /* 0x00080000 */ - disable_flag(I2C_FUNC_SMBUS_WRITE_BYTE_DATA) | /* 0x00100000 */ - disable_flag(I2C_FUNC_SMBUS_READ_WORD_DATA) | /* 0x00200000 */ - disable_flag(I2C_FUNC_SMBUS_WRITE_WORD_DATA) | /* 0x00400000 */ - disable_flag(I2C_FUNC_SMBUS_PROC_CALL) | /* 0x00800000 */ - disable_flag(I2C_FUNC_SMBUS_READ_BLOCK_DATA) | /* 0x01000000 */ - disable_flag(I2C_FUNC_SMBUS_WRITE_BLOCK_DATA) | /* 0x02000000 */ - enable_flag_if(I2C_FUNC_SMBUS_READ_I2C_BLOCK, - priv->features & FEATURE_I2C_BLOCK_READ) | - /* 0x04000000 */ - enable_flag(I2C_FUNC_SMBUS_WRITE_I2C_BLOCK) | /* 0x08000000 */ - - enable_flag(I2C_FUNC_SMBUS_BYTE) | /* _READ_BYTE _WRITE_BYTE */ - enable_flag(I2C_FUNC_SMBUS_BYTE_DATA) | /* _READ_BYTE_DATA - * _WRITE_BYTE_DATA - */ - enable_flag(I2C_FUNC_SMBUS_WORD_DATA) | /* _READ_WORD_DATA - * _WRITE_WORD_DATA - */ - enable_flag(I2C_FUNC_SMBUS_BLOCK_DATA) | /* _READ_BLOCK_DATA - * _WRITE_BLOCK_DATA - */ - disable_flag(I2C_FUNC_SMBUS_I2C_BLOCK) | /* _READ_I2C_BLOCK - * _WRITE_I2C_BLOCK - */ - disable_flag(I2C_FUNC_SMBUS_EMUL); /* _QUICK _BYTE - * _BYTE_DATA _WORD_DATA - * _PROC_CALL - * _WRITE_BLOCK_DATA - * _I2C_BLOCK _PEC - */ - return f; -} - -#undef enable_flag -#undef disable_flag -#undef enable_flag_if - -static const struct i2c_algorithm smbus_algorithm = { - .smbus_xfer = i801_access, - .functionality = i801_func, -}; - -/******************************** - *** Part 2 - Driver Handlers *** - ********************************/ -static int kpc_i2c_probe(struct platform_device *pldev) -{ - int err; - struct kpc_i2c *priv; - struct resource *res; - - priv = devm_kzalloc(&pldev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - i2c_set_adapdata(&priv->adapter, priv); - priv->adapter.owner = THIS_MODULE; - priv->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - priv->adapter.algo = &smbus_algorithm; - - res = platform_get_resource(pldev, IORESOURCE_MEM, 0); - if (!res) - return -ENXIO; - - priv->smba = (unsigned long)devm_ioremap(&pldev->dev, - res->start, - resource_size(res)); - if (!priv->smba) - return -ENOMEM; - - platform_set_drvdata(pldev, priv); - - priv->features |= FEATURE_IDF; - priv->features |= FEATURE_I2C_BLOCK_READ; - priv->features |= FEATURE_SMBUS_PEC; - priv->features |= FEATURE_BLOCK_BUFFER; - - //init_MUTEX(&lddata->sem); - - /* set up the sysfs linkage to our parent device */ - priv->adapter.dev.parent = &pldev->dev; - - /* Retry up to 3 times on lost arbitration */ - priv->adapter.retries = 3; - - snprintf(priv->adapter.name, sizeof(priv->adapter.name), - "Fake SMBus I801 adapter"); - - err = i2c_add_adapter(&priv->adapter); - if (err) { - dev_err(&priv->adapter.dev, "Failed to add SMBus adapter\n"); - return err; - } - - return 0; -} - -static int kpc_i2c_remove(struct platform_device *pldev) -{ - struct kpc_i2c *lddev; - - lddev = (struct kpc_i2c *)platform_get_drvdata(pldev); - - i2c_del_adapter(&lddev->adapter); - - //TODO: Figure out the right thing to do here... - //pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg); - //pci_release_region(dev, SMBBAR); - //pci_set_drvdata(dev, NULL); - - //cdev_del(&lddev->cdev); - - return 0; -} - -static struct platform_driver kpc_i2c_driver = { - .probe = kpc_i2c_probe, - .remove = kpc_i2c_remove, - .driver = { - .name = KP_DRIVER_NAME_I2C, - }, -}; - -module_platform_driver(kpc_i2c_driver); diff --git a/drivers/staging/kpc2000/kpc2000_spi.c b/drivers/staging/kpc2000/kpc2000_spi.c deleted file mode 100644 index 16ca18b8aa15..000000000000 --- a/drivers/staging/kpc2000/kpc2000_spi.c +++ /dev/null @@ -1,517 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * KP2000 SPI controller driver - * - * Copyright (C) 2014-2018 Daktronics - * Author: Matt Sickler <matt.sickler@daktronics.com> - * Very loosely based on spi-omap2-mcspi.c - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/io-64-nonatomic-lo-hi.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/delay.h> -#include <linux/platform_device.h> -#include <linux/err.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/slab.h> -#include <linux/pm_runtime.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/gcd.h> -#include <linux/spi/spi.h> -#include <linux/spi/flash.h> -#include <linux/mtd/partitions.h> - -#include "kpc.h" - -static struct mtd_partition p2kr0_spi0_parts[] = { - { .name = "SLOT_0", .size = 7798784, .offset = 0, }, - { .name = "SLOT_1", .size = 7798784, .offset = MTDPART_OFS_NXTBLK}, - { .name = "SLOT_2", .size = 7798784, .offset = MTDPART_OFS_NXTBLK}, - { .name = "SLOT_3", .size = 7798784, .offset = MTDPART_OFS_NXTBLK}, - { .name = "CS0_EXTRA", .size = MTDPART_SIZ_FULL, .offset = MTDPART_OFS_NXTBLK}, -}; - -static struct mtd_partition p2kr0_spi1_parts[] = { - { .name = "SLOT_4", .size = 7798784, .offset = 0, }, - { .name = "SLOT_5", .size = 7798784, .offset = MTDPART_OFS_NXTBLK}, - { .name = "SLOT_6", .size = 7798784, .offset = MTDPART_OFS_NXTBLK}, - { .name = "SLOT_7", .size = 7798784, .offset = MTDPART_OFS_NXTBLK}, - { .name = "CS1_EXTRA", .size = MTDPART_SIZ_FULL, .offset = MTDPART_OFS_NXTBLK}, -}; - -static struct flash_platform_data p2kr0_spi0_pdata = { - .name = "SPI0", - .nr_parts = ARRAY_SIZE(p2kr0_spi0_parts), - .parts = p2kr0_spi0_parts, -}; - -static struct flash_platform_data p2kr0_spi1_pdata = { - .name = "SPI1", - .nr_parts = ARRAY_SIZE(p2kr0_spi1_parts), - .parts = p2kr0_spi1_parts, -}; - -static struct spi_board_info p2kr0_board_info[] = { - { - .modalias = "n25q256a11", - .bus_num = 1, - .chip_select = 0, - .mode = SPI_MODE_0, - .platform_data = &p2kr0_spi0_pdata - }, - { - .modalias = "n25q256a11", - .bus_num = 1, - .chip_select = 1, - .mode = SPI_MODE_0, - .platform_data = &p2kr0_spi1_pdata - }, -}; - -/*************** - * SPI Defines * - ***************/ -#define KP_SPI_REG_CONFIG 0x0 /* 0x00 */ -#define KP_SPI_REG_STATUS 0x1 /* 0x08 */ -#define KP_SPI_REG_FFCTRL 0x2 /* 0x10 */ -#define KP_SPI_REG_TXDATA 0x3 /* 0x18 */ -#define KP_SPI_REG_RXDATA 0x4 /* 0x20 */ - -#define KP_SPI_CLK 48000000 -#define KP_SPI_MAX_FIFODEPTH 64 -#define KP_SPI_MAX_FIFOWCNT 0xFFFF - -#define KP_SPI_REG_CONFIG_TRM_TXRX 0 -#define KP_SPI_REG_CONFIG_TRM_RX 1 -#define KP_SPI_REG_CONFIG_TRM_TX 2 - -#define KP_SPI_REG_STATUS_RXS 0x01 -#define KP_SPI_REG_STATUS_TXS 0x02 -#define KP_SPI_REG_STATUS_EOT 0x04 -#define KP_SPI_REG_STATUS_TXFFE 0x10 -#define KP_SPI_REG_STATUS_TXFFF 0x20 -#define KP_SPI_REG_STATUS_RXFFE 0x40 -#define KP_SPI_REG_STATUS_RXFFF 0x80 - -/****************** - * SPI Structures * - ******************/ -struct kp_spi { - struct spi_master *master; - u64 __iomem *base; - struct device *dev; -}; - -struct kp_spi_controller_state { - void __iomem *base; - s64 conf_cache; -}; - -union kp_spi_config { - /* use this to access individual elements */ - struct __packed spi_config_bitfield { - unsigned int pha : 1; /* spim_clk Phase */ - unsigned int pol : 1; /* spim_clk Polarity */ - unsigned int epol : 1; /* spim_csx Polarity */ - unsigned int dpe : 1; /* Transmission Enable */ - unsigned int wl : 5; /* Word Length */ - unsigned int : 3; - unsigned int trm : 2; /* TxRx Mode */ - unsigned int cs : 4; /* Chip Select */ - unsigned int wcnt : 7; /* Word Count */ - unsigned int ffen : 1; /* FIFO Enable */ - unsigned int spi_en : 1; /* SPI Enable */ - unsigned int : 5; - } bitfield; - /* use this to grab the whole register */ - u32 reg; -}; - -union kp_spi_status { - struct __packed spi_status_bitfield { - unsigned int rx : 1; /* Rx Status */ - unsigned int tx : 1; /* Tx Status */ - unsigned int eo : 1; /* End of Transfer */ - unsigned int : 1; - unsigned int txffe : 1; /* Tx FIFO Empty */ - unsigned int txfff : 1; /* Tx FIFO Full */ - unsigned int rxffe : 1; /* Rx FIFO Empty */ - unsigned int rxfff : 1; /* Rx FIFO Full */ - unsigned int : 24; - } bitfield; - u32 reg; -}; - -union kp_spi_ffctrl { - struct __packed spi_ffctrl_bitfield { - unsigned int ffstart : 1; /* FIFO Start */ - unsigned int : 31; - } bitfield; - u32 reg; -}; - -/*************** - * SPI Helpers * - ***************/ - static inline u64 -kp_spi_read_reg(struct kp_spi_controller_state *cs, int idx) -{ - u64 __iomem *addr = cs->base; - - addr += idx; - if ((idx == KP_SPI_REG_CONFIG) && (cs->conf_cache >= 0)) - return cs->conf_cache; - - return readq(addr); -} - - static inline void -kp_spi_write_reg(struct kp_spi_controller_state *cs, int idx, u64 val) -{ - u64 __iomem *addr = cs->base; - - addr += idx; - writeq(val, addr); - if (idx == KP_SPI_REG_CONFIG) - cs->conf_cache = val; -} - - static int -kp_spi_wait_for_reg_bit(struct kp_spi_controller_state *cs, int idx, - unsigned long bit) -{ - unsigned long timeout; - - timeout = jiffies + msecs_to_jiffies(1000); - while (!(kp_spi_read_reg(cs, idx) & bit)) { - if (time_after(jiffies, timeout)) { - if (!(kp_spi_read_reg(cs, idx) & bit)) - return -ETIMEDOUT; - else - return 0; - } - cpu_relax(); - } - return 0; -} - - static unsigned -kp_spi_txrx_pio(struct spi_device *spidev, struct spi_transfer *transfer) -{ - struct kp_spi_controller_state *cs = spidev->controller_state; - unsigned int count = transfer->len; - unsigned int c = count; - - int i; - int res; - u8 *rx = transfer->rx_buf; - const u8 *tx = transfer->tx_buf; - int processed = 0; - - if (tx) { - for (i = 0 ; i < c ; i++) { - char val = *tx++; - - res = kp_spi_wait_for_reg_bit(cs, KP_SPI_REG_STATUS, - KP_SPI_REG_STATUS_TXS); - if (res < 0) - goto out; - - kp_spi_write_reg(cs, KP_SPI_REG_TXDATA, val); - processed++; - } - } else if (rx) { - for (i = 0 ; i < c ; i++) { - char test = 0; - - kp_spi_write_reg(cs, KP_SPI_REG_TXDATA, 0x00); - res = kp_spi_wait_for_reg_bit(cs, KP_SPI_REG_STATUS, - KP_SPI_REG_STATUS_RXS); - if (res < 0) - goto out; - - test = kp_spi_read_reg(cs, KP_SPI_REG_RXDATA); - *rx++ = test; - processed++; - } - } - - if (kp_spi_wait_for_reg_bit(cs, KP_SPI_REG_STATUS, - KP_SPI_REG_STATUS_EOT) < 0) { - //TODO: Figure out how to abort transaction?? - //Ths has never happened in practice though... - } - -out: - return processed; -} - -/***************** - * SPI Functions * - *****************/ - static int -kp_spi_setup(struct spi_device *spidev) -{ - union kp_spi_config sc; - struct kp_spi *kpspi = spi_master_get_devdata(spidev->master); - struct kp_spi_controller_state *cs; - - /* setup controller state */ - cs = spidev->controller_state; - if (!cs) { - cs = kzalloc(sizeof(*cs), GFP_KERNEL); - if (!cs) - return -ENOMEM; - cs->base = kpspi->base; - cs->conf_cache = -1; - spidev->controller_state = cs; - } - - /* set config register */ - sc.bitfield.wl = spidev->bits_per_word - 1; - sc.bitfield.cs = spidev->chip_select; - sc.bitfield.spi_en = 0; - sc.bitfield.trm = 0; - sc.bitfield.ffen = 0; - kp_spi_write_reg(spidev->controller_state, KP_SPI_REG_CONFIG, sc.reg); - return 0; -} - - static int -kp_spi_transfer_one_message(struct spi_master *master, struct spi_message *m) -{ - struct kp_spi_controller_state *cs; - struct spi_device *spidev; - struct kp_spi *kpspi; - struct spi_transfer *transfer; - union kp_spi_config sc; - int status = 0; - - spidev = m->spi; - kpspi = spi_master_get_devdata(master); - m->actual_length = 0; - m->status = 0; - - cs = spidev->controller_state; - - /* reject invalid messages and transfers */ - if (list_empty(&m->transfers)) - return -EINVAL; - - /* validate input */ - list_for_each_entry(transfer, &m->transfers, transfer_list) { - const void *tx_buf = transfer->tx_buf; - void *rx_buf = transfer->rx_buf; - unsigned int len = transfer->len; - - if (transfer->speed_hz > KP_SPI_CLK || - (len && !(rx_buf || tx_buf))) { - dev_dbg(kpspi->dev, " transfer: %d Hz, %d %s%s, %d bpw\n", - transfer->speed_hz, - len, - tx_buf ? "tx" : "", - rx_buf ? "rx" : "", - transfer->bits_per_word); - dev_dbg(kpspi->dev, " transfer -EINVAL\n"); - return -EINVAL; - } - if (transfer->speed_hz && - transfer->speed_hz < (KP_SPI_CLK >> 15)) { - dev_dbg(kpspi->dev, "speed_hz %d below minimum %d Hz\n", - transfer->speed_hz, - KP_SPI_CLK >> 15); - dev_dbg(kpspi->dev, " speed_hz -EINVAL\n"); - return -EINVAL; - } - } - - /* assert chip select to start the sequence*/ - sc.reg = kp_spi_read_reg(cs, KP_SPI_REG_CONFIG); - sc.bitfield.spi_en = 1; - kp_spi_write_reg(cs, KP_SPI_REG_CONFIG, sc.reg); - - /* work */ - if (kp_spi_wait_for_reg_bit(cs, KP_SPI_REG_STATUS, - KP_SPI_REG_STATUS_EOT) < 0) { - dev_info(kpspi->dev, "EOT timed out\n"); - goto out; - } - - /* do the transfers for this message */ - list_for_each_entry(transfer, &m->transfers, transfer_list) { - if (!transfer->tx_buf && !transfer->rx_buf && - transfer->len) { - status = -EINVAL; - goto error; - } - - /* transfer */ - if (transfer->len) { - unsigned int word_len = spidev->bits_per_word; - unsigned int count; - - /* set up the transfer... */ - sc.reg = kp_spi_read_reg(cs, KP_SPI_REG_CONFIG); - - /* ...direction */ - if (transfer->tx_buf) - sc.bitfield.trm = KP_SPI_REG_CONFIG_TRM_TX; - else if (transfer->rx_buf) - sc.bitfield.trm = KP_SPI_REG_CONFIG_TRM_RX; - - /* ...word length */ - if (transfer->bits_per_word) - word_len = transfer->bits_per_word; - sc.bitfield.wl = word_len - 1; - - /* ...chip select */ - sc.bitfield.cs = spidev->chip_select; - - /* ...and write the new settings */ - kp_spi_write_reg(cs, KP_SPI_REG_CONFIG, sc.reg); - - /* do the transfer */ - count = kp_spi_txrx_pio(spidev, transfer); - m->actual_length += count; - - if (count != transfer->len) { - status = -EIO; - goto error; - } - } - - if (transfer->delay.value) - ndelay(spi_delay_to_ns(&transfer->delay, transfer)); - } - - /* de-assert chip select to end the sequence */ - sc.reg = kp_spi_read_reg(cs, KP_SPI_REG_CONFIG); - sc.bitfield.spi_en = 0; - kp_spi_write_reg(cs, KP_SPI_REG_CONFIG, sc.reg); - -out: - /* done work */ - spi_finalize_current_message(master); - return 0; - -error: - m->status = status; - return status; -} - - static void -kp_spi_cleanup(struct spi_device *spidev) -{ - struct kp_spi_controller_state *cs = spidev->controller_state; - - kfree(cs); -} - -/****************** - * Probe / Remove * - ******************/ - static int -kp_spi_probe(struct platform_device *pldev) -{ - struct kpc_core_device_platdata *drvdata; - struct spi_master *master; - struct kp_spi *kpspi; - struct resource *r; - int status = 0; - int i; - - drvdata = pldev->dev.platform_data; - if (!drvdata) { - dev_err(&pldev->dev, "%s: platform_data is NULL\n", __func__); - return -ENODEV; - } - - master = spi_alloc_master(&pldev->dev, sizeof(struct kp_spi)); - if (!master) { - dev_err(&pldev->dev, "%s: master allocation failed\n", - __func__); - return -ENOMEM; - } - - /* set up the spi functions */ - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; - master->bits_per_word_mask = (unsigned int)SPI_BPW_RANGE_MASK(4, 32); - master->setup = kp_spi_setup; - master->transfer_one_message = kp_spi_transfer_one_message; - master->cleanup = kp_spi_cleanup; - - platform_set_drvdata(pldev, master); - - kpspi = spi_master_get_devdata(master); - kpspi->master = master; - kpspi->dev = &pldev->dev; - - master->num_chipselect = 4; - if (pldev->id != -1) - master->bus_num = pldev->id; - - r = platform_get_resource(pldev, IORESOURCE_MEM, 0); - if (!r) { - dev_err(&pldev->dev, "%s: Unable to get platform resources\n", - __func__); - status = -ENODEV; - goto free_master; - } - - kpspi->base = devm_ioremap(&pldev->dev, r->start, - resource_size(r)); - - status = spi_register_master(master); - if (status < 0) { - dev_err(&pldev->dev, "Unable to register SPI device\n"); - goto free_master; - } - - /* register the slave boards */ -#define NEW_SPI_DEVICE_FROM_BOARD_INFO_TABLE(table) \ - for (i = 0 ; i < ARRAY_SIZE(table) ; i++) { \ - spi_new_device(master, &table[i]); \ - } - - switch ((drvdata->card_id & 0xFFFF0000) >> 16) { - case PCI_DEVICE_ID_DAKTRONICS_KADOKA_P2KR0: - NEW_SPI_DEVICE_FROM_BOARD_INFO_TABLE(p2kr0_board_info); - break; - default: - dev_err(&pldev->dev, "Unknown hardware, cant know what partition table to use!\n"); - goto free_master; - } - - return status; - -free_master: - spi_master_put(master); - return status; -} - - static int -kp_spi_remove(struct platform_device *pldev) -{ - struct spi_master *master = platform_get_drvdata(pldev); - - spi_unregister_master(master); - return 0; -} - -static struct platform_driver kp_spi_driver = { - .driver = { - .name = KP_DRIVER_NAME_SPI, - }, - .probe = kp_spi_probe, - .remove = kp_spi_remove, -}; - -module_platform_driver(kp_spi_driver); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:kp_spi"); diff --git a/drivers/staging/kpc2000/kpc_dma/Makefile b/drivers/staging/kpc2000/kpc_dma/Makefile deleted file mode 100644 index fe5db532c8c8..000000000000 --- a/drivers/staging/kpc2000/kpc_dma/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -obj-m := kpc_dma.o -kpc_dma-objs += dma.o -kpc_dma-objs += fileops.o -kpc_dma-objs += kpc_dma_driver.o diff --git a/drivers/staging/kpc2000/kpc_dma/dma.c b/drivers/staging/kpc2000/kpc_dma/dma.c deleted file mode 100644 index e169ac609ba4..000000000000 --- a/drivers/staging/kpc2000/kpc_dma/dma.c +++ /dev/null @@ -1,270 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/io.h> -#include <linux/export.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <linux/fs.h> -#include <linux/rwsem.h> -#include "kpc_dma_driver.h" - -/********** IRQ Handlers **********/ -static -irqreturn_t ndd_irq_handler(int irq, void *dev_id) -{ - struct kpc_dma_device *ldev = (struct kpc_dma_device *)dev_id; - - if ((GetEngineControl(ldev) & ENG_CTL_IRQ_ACTIVE) || - (ldev->desc_completed->MyDMAAddr != GetEngineCompletePtr(ldev))) - schedule_work(&ldev->irq_work); - - return IRQ_HANDLED; -} - -static -void ndd_irq_worker(struct work_struct *ws) -{ - struct kpc_dma_descriptor *cur; - struct kpc_dma_device *eng = container_of(ws, struct kpc_dma_device, irq_work); - - lock_engine(eng); - - if (GetEngineCompletePtr(eng) == 0) - goto out; - - if (eng->desc_completed->MyDMAAddr == GetEngineCompletePtr(eng)) - goto out; - - cur = eng->desc_completed; - do { - cur = cur->Next; - dev_dbg(&eng->pldev->dev, "Handling completed descriptor %p (acd = %p)\n", - cur, cur->acd); - BUG_ON(cur == eng->desc_next); // Ordering failure. - - if (cur->DescControlFlags & DMA_DESC_CTL_SOP) { - eng->accumulated_bytes = 0; - eng->accumulated_flags = 0; - } - - eng->accumulated_bytes += cur->DescByteCount; - if (cur->DescStatusFlags & DMA_DESC_STS_ERROR) - eng->accumulated_flags |= ACD_FLAG_ENG_ACCUM_ERROR; - - if (cur->DescStatusFlags & DMA_DESC_STS_SHORT) - eng->accumulated_flags |= ACD_FLAG_ENG_ACCUM_SHORT; - - if (cur->DescControlFlags & DMA_DESC_CTL_EOP) { - if (cur->acd) - transfer_complete_cb(cur->acd, eng->accumulated_bytes, - eng->accumulated_flags | ACD_FLAG_DONE); - } - - eng->desc_completed = cur; - } while (cur->MyDMAAddr != GetEngineCompletePtr(eng)); - - out: - SetClearEngineControl(eng, ENG_CTL_IRQ_ACTIVE, 0); - - unlock_engine(eng); -} - -/********** DMA Engine Init/Teardown **********/ -void start_dma_engine(struct kpc_dma_device *eng) -{ - eng->desc_next = eng->desc_pool_first; - eng->desc_completed = eng->desc_pool_last; - - // Setup the engine pointer registers - SetEngineNextPtr(eng, eng->desc_pool_first); - SetEngineSWPtr(eng, eng->desc_pool_first); - ClearEngineCompletePtr(eng); - - WriteEngineControl(eng, ENG_CTL_DMA_ENABLE | ENG_CTL_IRQ_ENABLE); -} - -int setup_dma_engine(struct kpc_dma_device *eng, u32 desc_cnt) -{ - u32 caps; - struct kpc_dma_descriptor *cur; - struct kpc_dma_descriptor *next; - dma_addr_t next_handle; - dma_addr_t head_handle; - unsigned int i; - int rv; - - caps = GetEngineCapabilities(eng); - - if (WARN(!(caps & ENG_CAP_PRESENT), "%s() called for DMA Engine at %p which isn't present in hardware!\n", __func__, eng)) - return -ENXIO; - - if (caps & ENG_CAP_DIRECTION) - eng->dir = DMA_FROM_DEVICE; - else - eng->dir = DMA_TO_DEVICE; - - eng->desc_pool_cnt = desc_cnt; - eng->desc_pool = dma_pool_create("KPC DMA Descriptors", &eng->pldev->dev, - sizeof(struct kpc_dma_descriptor), - DMA_DESC_ALIGNMENT, 4096); - - eng->desc_pool_first = dma_pool_alloc(eng->desc_pool, GFP_KERNEL | GFP_DMA, &head_handle); - if (!eng->desc_pool_first) { - dev_err(&eng->pldev->dev, "%s: couldn't allocate desc_pool_first!\n", __func__); - dma_pool_destroy(eng->desc_pool); - return -ENOMEM; - } - - eng->desc_pool_first->MyDMAAddr = head_handle; - clear_desc(eng->desc_pool_first); - - cur = eng->desc_pool_first; - for (i = 1 ; i < eng->desc_pool_cnt ; i++) { - next = dma_pool_alloc(eng->desc_pool, GFP_KERNEL | GFP_DMA, &next_handle); - if (!next) - goto done_alloc; - - clear_desc(next); - next->MyDMAAddr = next_handle; - - cur->DescNextDescPtr = next_handle; - cur->Next = next; - cur = next; - } - - done_alloc: - // Link the last descriptor back to the first, so it's a circular linked list - cur->Next = eng->desc_pool_first; - cur->DescNextDescPtr = eng->desc_pool_first->MyDMAAddr; - - eng->desc_pool_last = cur; - eng->desc_completed = eng->desc_pool_last; - - // Setup work queue - INIT_WORK(&eng->irq_work, ndd_irq_worker); - - // Grab IRQ line - rv = request_irq(eng->irq, ndd_irq_handler, IRQF_SHARED, - KP_DRIVER_NAME_DMA_CONTROLLER, eng); - if (rv) { - dev_err(&eng->pldev->dev, "%s: failed to request_irq: %d\n", __func__, rv); - return rv; - } - - // Turn on the engine! - start_dma_engine(eng); - unlock_engine(eng); - - return 0; -} - -void stop_dma_engine(struct kpc_dma_device *eng) -{ - unsigned long timeout; - - // Disable the descriptor engine - WriteEngineControl(eng, 0); - - // Wait for descriptor engine to finish current operaion - timeout = jiffies + (HZ / 2); - while (GetEngineControl(eng) & ENG_CTL_DMA_RUNNING) { - if (time_after(jiffies, timeout)) { - dev_crit(&eng->pldev->dev, "DMA_RUNNING still asserted!\n"); - break; - } - } - - // Request a reset - WriteEngineControl(eng, ENG_CTL_DMA_RESET_REQUEST); - - // Wait for reset request to be processed - timeout = jiffies + (HZ / 2); - while (GetEngineControl(eng) & (ENG_CTL_DMA_RUNNING | ENG_CTL_DMA_RESET_REQUEST)) { - if (time_after(jiffies, timeout)) { - dev_crit(&eng->pldev->dev, "ENG_CTL_DMA_RESET_REQUEST still asserted!\n"); - break; - } - } - - // Request a reset - WriteEngineControl(eng, ENG_CTL_DMA_RESET); - - // And wait for reset to complete - timeout = jiffies + (HZ / 2); - while (GetEngineControl(eng) & ENG_CTL_DMA_RESET) { - if (time_after(jiffies, timeout)) { - dev_crit(&eng->pldev->dev, "DMA_RESET still asserted!\n"); - break; - } - } - - // Clear any persistent bits just to make sure there is no residue from the reset - SetClearEngineControl(eng, (ENG_CTL_IRQ_ACTIVE | ENG_CTL_DESC_COMPLETE | - ENG_CTL_DESC_ALIGN_ERR | ENG_CTL_DESC_FETCH_ERR | - ENG_CTL_SW_ABORT_ERR | ENG_CTL_DESC_CHAIN_END | - ENG_CTL_DMA_WAITING_PERSIST), 0); - - // Reset performance counters - - // Completely disable the engine - WriteEngineControl(eng, 0); -} - -void destroy_dma_engine(struct kpc_dma_device *eng) -{ - struct kpc_dma_descriptor *cur; - dma_addr_t cur_handle; - unsigned int i; - - stop_dma_engine(eng); - - cur = eng->desc_pool_first; - cur_handle = eng->desc_pool_first->MyDMAAddr; - - for (i = 0 ; i < eng->desc_pool_cnt ; i++) { - struct kpc_dma_descriptor *next = cur->Next; - dma_addr_t next_handle = cur->DescNextDescPtr; - - dma_pool_free(eng->desc_pool, cur, cur_handle); - cur_handle = next_handle; - cur = next; - } - - dma_pool_destroy(eng->desc_pool); - - free_irq(eng->irq, eng); -} - -/********** Helper Functions **********/ -int count_descriptors_available(struct kpc_dma_device *eng) -{ - u32 count = 0; - struct kpc_dma_descriptor *cur = eng->desc_next; - - while (cur != eng->desc_completed) { - BUG_ON(!cur); - count++; - cur = cur->Next; - } - return count; -} - -void clear_desc(struct kpc_dma_descriptor *desc) -{ - if (!desc) - return; - desc->DescByteCount = 0; - desc->DescStatusErrorFlags = 0; - desc->DescStatusFlags = 0; - desc->DescUserControlLS = 0; - desc->DescUserControlMS = 0; - desc->DescCardAddrLS = 0; - desc->DescBufferByteCount = 0; - desc->DescCardAddrMS = 0; - desc->DescControlFlags = 0; - desc->DescSystemAddrLS = 0; - desc->DescSystemAddrMS = 0; - desc->acd = NULL; -} diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c deleted file mode 100644 index 10dcd6646b01..000000000000 --- a/drivers/staging/kpc2000/kpc_dma/fileops.c +++ /dev/null @@ -1,363 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -#include <linux/module.h> -#include <linux/init.h> -#include <linux/mm.h> -#include <linux/kernel.h> /* printk() */ -#include <linux/slab.h> /* kmalloc() */ -#include <linux/fs.h> /* everything... */ -#include <linux/errno.h> /* error codes */ -#include <linux/types.h> /* size_t */ -#include <linux/cdev.h> -#include <linux/uaccess.h> /* copy_*_user */ -#include <linux/highmem.h> -#include <linux/pagemap.h> -#include "kpc_dma_driver.h" -#include "uapi.h" - -/********** Helper Functions **********/ -static inline -unsigned int count_pages(unsigned long iov_base, size_t iov_len) -{ - unsigned long first = (iov_base & PAGE_MASK) >> PAGE_SHIFT; - unsigned long last = ((iov_base + iov_len - 1) & PAGE_MASK) >> PAGE_SHIFT; - - return last - first + 1; -} - -static inline -unsigned int count_parts_for_sge(struct scatterlist *sg) -{ - return DIV_ROUND_UP(sg_dma_len(sg), 0x80000); -} - -/********** Transfer Helpers **********/ -static int kpc_dma_transfer(struct dev_private_data *priv, - unsigned long iov_base, size_t iov_len) -{ - unsigned int i = 0; - int rv = 0, nr_pages = 0; - struct kpc_dma_device *ldev; - struct aio_cb_data *acd; - DECLARE_COMPLETION_ONSTACK(done); - u32 desc_needed = 0; - struct scatterlist *sg; - u32 num_descrs_avail; - struct kpc_dma_descriptor *desc; - unsigned int pcnt; - unsigned int p; - u64 card_addr; - u64 dma_addr; - u64 user_ctl; - - ldev = priv->ldev; - - acd = kzalloc(sizeof(*acd), GFP_KERNEL); - if (!acd) { - dev_err(&priv->ldev->pldev->dev, "Couldn't kmalloc space for the aio data\n"); - return -ENOMEM; - } - memset(acd, 0x66, sizeof(struct aio_cb_data)); - - acd->priv = priv; - acd->ldev = priv->ldev; - acd->cpl = &done; - acd->flags = 0; - acd->len = iov_len; - acd->page_count = count_pages(iov_base, iov_len); - - // Allocate an array of page pointers - acd->user_pages = kcalloc(acd->page_count, sizeof(struct page *), - GFP_KERNEL); - if (!acd->user_pages) { - dev_err(&priv->ldev->pldev->dev, "Couldn't kmalloc space for the page pointers\n"); - rv = -ENOMEM; - goto err_alloc_userpages; - } - - // Lock the user buffer pages in memory, and hold on to the page pointers (for the sglist) - mmap_read_lock(current->mm); /* get memory map semaphore */ - rv = pin_user_pages(iov_base, acd->page_count, FOLL_TOUCH | FOLL_WRITE, - acd->user_pages, NULL); - mmap_read_unlock(current->mm); /* release the semaphore */ - if (rv != acd->page_count) { - nr_pages = rv; - if (rv > 0) - rv = -EFAULT; - - dev_err(&priv->ldev->pldev->dev, "Couldn't pin_user_pages (%d)\n", rv); - goto unpin_pages; - } - nr_pages = acd->page_count; - - // Allocate and setup the sg_table (scatterlist entries) - rv = sg_alloc_table_from_pages(&acd->sgt, acd->user_pages, acd->page_count, - iov_base & (PAGE_SIZE - 1), iov_len, GFP_KERNEL); - if (rv) { - dev_err(&priv->ldev->pldev->dev, "Couldn't alloc sg_table (%d)\n", rv); - goto unpin_pages; - } - - // Setup the DMA mapping for all the sg entries - acd->mapped_entry_count = dma_map_sg(&ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, - ldev->dir); - if (acd->mapped_entry_count <= 0) { - dev_err(&priv->ldev->pldev->dev, "Couldn't dma_map_sg (%d)\n", - acd->mapped_entry_count); - goto free_table; - } - - // Calculate how many descriptors are actually needed for this transfer. - for_each_sg(acd->sgt.sgl, sg, acd->mapped_entry_count, i) { - desc_needed += count_parts_for_sge(sg); - } - - lock_engine(ldev); - - // Figoure out how many descriptors are available and return an error if there aren't enough - num_descrs_avail = count_descriptors_available(ldev); - dev_dbg(&priv->ldev->pldev->dev, - " mapped_entry_count = %d num_descrs_needed = %d num_descrs_avail = %d\n", - acd->mapped_entry_count, desc_needed, num_descrs_avail); - - if (desc_needed >= ldev->desc_pool_cnt) { - dev_warn(&priv->ldev->pldev->dev, - " mapped_entry_count = %d num_descrs_needed = %d num_descrs_avail = %d TOO MANY to ever complete!\n", - acd->mapped_entry_count, desc_needed, num_descrs_avail); - rv = -EAGAIN; - goto err_descr_too_many; - } - if (desc_needed > num_descrs_avail) { - dev_warn(&priv->ldev->pldev->dev, - " mapped_entry_count = %d num_descrs_needed = %d num_descrs_avail = %d Too many to complete right now.\n", - acd->mapped_entry_count, desc_needed, num_descrs_avail); - rv = -EMSGSIZE; - goto err_descr_too_many; - } - - // Loop through all the sg table entries and fill out a descriptor for each one. - desc = ldev->desc_next; - card_addr = acd->priv->card_addr; - for_each_sg(acd->sgt.sgl, sg, acd->mapped_entry_count, i) { - pcnt = count_parts_for_sge(sg); - for (p = 0 ; p < pcnt ; p++) { - // Fill out the descriptor - BUG_ON(!desc); - clear_desc(desc); - if (p != pcnt - 1) - desc->DescByteCount = 0x80000; - else - desc->DescByteCount = sg_dma_len(sg) - (p * 0x80000); - - desc->DescBufferByteCount = desc->DescByteCount; - - desc->DescControlFlags |= DMA_DESC_CTL_IRQONERR; - if (i == 0 && p == 0) - desc->DescControlFlags |= DMA_DESC_CTL_SOP; - if (i == acd->mapped_entry_count - 1 && p == pcnt - 1) - desc->DescControlFlags |= DMA_DESC_CTL_EOP | DMA_DESC_CTL_IRQONDONE; - - desc->DescCardAddrLS = (card_addr & 0xFFFFFFFF); - desc->DescCardAddrMS = (card_addr >> 32) & 0xF; - card_addr += desc->DescByteCount; - - dma_addr = sg_dma_address(sg) + (p * 0x80000); - desc->DescSystemAddrLS = (dma_addr & 0x00000000FFFFFFFFUL) >> 0; - desc->DescSystemAddrMS = (dma_addr & 0xFFFFFFFF00000000UL) >> 32; - - user_ctl = acd->priv->user_ctl; - if (i == acd->mapped_entry_count - 1 && p == pcnt - 1) - user_ctl = acd->priv->user_ctl_last; - - desc->DescUserControlLS = (user_ctl & 0x00000000FFFFFFFFUL) >> 0; - desc->DescUserControlMS = (user_ctl & 0xFFFFFFFF00000000UL) >> 32; - - if (i == acd->mapped_entry_count - 1 && p == pcnt - 1) - desc->acd = acd; - - dev_dbg(&priv->ldev->pldev->dev, " Filled descriptor %p (acd = %p)\n", - desc, desc->acd); - - ldev->desc_next = desc->Next; - desc = desc->Next; - } - } - - // Send the filled descriptors off to the hardware to process! - SetEngineSWPtr(ldev, ldev->desc_next); - - unlock_engine(ldev); - - rv = wait_for_completion_interruptible(&done); - /* - * If the user aborted (rv == -ERESTARTSYS), we're no longer responsible - * for cleaning up the acd - */ - if (rv == -ERESTARTSYS) - acd->cpl = NULL; - if (rv == 0) { - rv = acd->len; - kfree(acd); - } - return rv; - - err_descr_too_many: - unlock_engine(ldev); - dma_unmap_sg(&ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, ldev->dir); - free_table: - sg_free_table(&acd->sgt); - - unpin_pages: - if (nr_pages > 0) - unpin_user_pages(acd->user_pages, nr_pages); - kfree(acd->user_pages); - err_alloc_userpages: - kfree(acd); - dev_dbg(&priv->ldev->pldev->dev, "%s returning with error %d\n", __func__, rv); - return rv; -} - -void transfer_complete_cb(struct aio_cb_data *acd, size_t xfr_count, u32 flags) -{ - unsigned int i; - - BUG_ON(!acd); - BUG_ON(!acd->user_pages); - BUG_ON(!acd->sgt.sgl); - BUG_ON(!acd->ldev); - BUG_ON(!acd->ldev->pldev); - - dma_unmap_sg(&acd->ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, acd->ldev->dir); - - for (i = 0 ; i < acd->page_count ; i++) { - if (!PageReserved(acd->user_pages[i])) - set_page_dirty_lock(acd->user_pages[i]); - } - - unpin_user_pages(acd->user_pages, acd->page_count); - - sg_free_table(&acd->sgt); - - kfree(acd->user_pages); - - acd->flags = flags; - - if (acd->cpl) { - complete(acd->cpl); - } else { - /* - * There's no completion, so we're responsible for cleaning up - * the acd - */ - kfree(acd); - } -} - -/********** Fileops **********/ -static -int kpc_dma_open(struct inode *inode, struct file *filp) -{ - struct dev_private_data *priv; - struct kpc_dma_device *ldev = kpc_dma_lookup_device(iminor(inode)); - - if (!ldev) - return -ENODEV; - - if (!atomic_dec_and_test(&ldev->open_count)) { - atomic_inc(&ldev->open_count); - return -EBUSY; /* already open */ - } - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->ldev = ldev; - filp->private_data = priv; - - return 0; -} - -static -int kpc_dma_close(struct inode *inode, struct file *filp) -{ - struct kpc_dma_descriptor *cur; - struct dev_private_data *priv = (struct dev_private_data *)filp->private_data; - struct kpc_dma_device *eng = priv->ldev; - - lock_engine(eng); - - stop_dma_engine(eng); - - cur = eng->desc_completed->Next; - while (cur != eng->desc_next) { - dev_dbg(&eng->pldev->dev, "Aborting descriptor %p (acd = %p)\n", cur, cur->acd); - if (cur->DescControlFlags & DMA_DESC_CTL_EOP) { - if (cur->acd) - transfer_complete_cb(cur->acd, 0, ACD_FLAG_ABORT); - } - - clear_desc(cur); - eng->desc_completed = cur; - - cur = cur->Next; - } - - start_dma_engine(eng); - - unlock_engine(eng); - - atomic_inc(&priv->ldev->open_count); /* release the device */ - kfree(priv); - return 0; -} - -static -ssize_t kpc_dma_read(struct file *filp, char __user *user_buf, size_t count, loff_t *ppos) -{ - struct dev_private_data *priv = (struct dev_private_data *)filp->private_data; - - if (priv->ldev->dir != DMA_FROM_DEVICE) - return -EMEDIUMTYPE; - - return kpc_dma_transfer(priv, (unsigned long)user_buf, count); -} - -static -ssize_t kpc_dma_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *ppos) -{ - struct dev_private_data *priv = (struct dev_private_data *)filp->private_data; - - if (priv->ldev->dir != DMA_TO_DEVICE) - return -EMEDIUMTYPE; - - return kpc_dma_transfer(priv, (unsigned long)user_buf, count); -} - -static -long kpc_dma_ioctl(struct file *filp, unsigned int ioctl_num, unsigned long ioctl_param) -{ - struct dev_private_data *priv = (struct dev_private_data *)filp->private_data; - - switch (ioctl_num) { - case KND_IOCTL_SET_CARD_ADDR: - priv->card_addr = ioctl_param; return priv->card_addr; - case KND_IOCTL_SET_USER_CTL: - priv->user_ctl = ioctl_param; return priv->user_ctl; - case KND_IOCTL_SET_USER_CTL_LAST: - priv->user_ctl_last = ioctl_param; return priv->user_ctl_last; - case KND_IOCTL_GET_USER_STS: - return priv->user_sts; - } - - return -ENOTTY; -} - -const struct file_operations kpc_dma_fops = { - .owner = THIS_MODULE, - .open = kpc_dma_open, - .release = kpc_dma_close, - .read = kpc_dma_read, - .write = kpc_dma_write, - .unlocked_ioctl = kpc_dma_ioctl, -}; - diff --git a/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c b/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c deleted file mode 100644 index 175fe8b0d055..000000000000 --- a/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c +++ /dev/null @@ -1,249 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/io.h> -#include <linux/export.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <linux/fs.h> -#include <linux/rwsem.h> -#include "kpc_dma_driver.h" - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Matt.Sickler@daktronics.com"); - -#define KPC_DMA_CHAR_MAJOR UNNAMED_MAJOR -#define KPC_DMA_NUM_MINORS BIT(MINORBITS) -static DEFINE_MUTEX(kpc_dma_mtx); -static int assigned_major_num; -static LIST_HEAD(kpc_dma_list); - -/********** kpc_dma_list list management **********/ -struct kpc_dma_device *kpc_dma_lookup_device(int minor) -{ - struct kpc_dma_device *c; - - mutex_lock(&kpc_dma_mtx); - list_for_each_entry(c, &kpc_dma_list, list) { - if (c->pldev->id == minor) - goto out; - } - c = NULL; // not-found case -out: - mutex_unlock(&kpc_dma_mtx); - return c; -} - -static void kpc_dma_add_device(struct kpc_dma_device *ldev) -{ - mutex_lock(&kpc_dma_mtx); - list_add(&ldev->list, &kpc_dma_list); - mutex_unlock(&kpc_dma_mtx); -} - -static void kpc_dma_del_device(struct kpc_dma_device *ldev) -{ - mutex_lock(&kpc_dma_mtx); - list_del(&ldev->list); - mutex_unlock(&kpc_dma_mtx); -} - -/********** SysFS Attributes **********/ -static ssize_t engine_regs_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct kpc_dma_device *ldev; - struct platform_device *pldev = to_platform_device(dev); - - if (!pldev) - return 0; - ldev = platform_get_drvdata(pldev); - if (!ldev) - return 0; - - return scnprintf(buf, PAGE_SIZE, - "EngineControlStatus = 0x%08x\n" - "RegNextDescPtr = 0x%08x\n" - "RegSWDescPtr = 0x%08x\n" - "RegCompletedDescPtr = 0x%08x\n" - "desc_pool_first = %p\n" - "desc_pool_last = %p\n" - "desc_next = %p\n" - "desc_completed = %p\n", - readl(ldev->eng_regs + 1), - readl(ldev->eng_regs + 2), - readl(ldev->eng_regs + 3), - readl(ldev->eng_regs + 4), - ldev->desc_pool_first, - ldev->desc_pool_last, - ldev->desc_next, - ldev->desc_completed - ); -} -static DEVICE_ATTR_RO(engine_regs); - -static const struct attribute *ndd_attr_list[] = { - &dev_attr_engine_regs.attr, - NULL, -}; - -static struct class *kpc_dma_class; - -/********** Platform Driver Functions **********/ -static -int kpc_dma_probe(struct platform_device *pldev) -{ - struct resource *r = NULL; - int rv = 0; - dev_t dev; - - struct kpc_dma_device *ldev = kzalloc(sizeof(*ldev), GFP_KERNEL); - - if (!ldev) { - dev_err(&pldev->dev, "%s: unable to kzalloc space for kpc_dma_device\n", __func__); - rv = -ENOMEM; - goto err_rv; - } - - INIT_LIST_HEAD(&ldev->list); - - ldev->pldev = pldev; - platform_set_drvdata(pldev, ldev); - atomic_set(&ldev->open_count, 1); - - mutex_init(&ldev->sem); - lock_engine(ldev); - - // Get Engine regs resource - r = platform_get_resource(pldev, IORESOURCE_MEM, 0); - if (!r) { - dev_err(&ldev->pldev->dev, "%s: didn't get the engine regs resource!\n", __func__); - rv = -ENXIO; - goto err_kfree; - } - ldev->eng_regs = ioremap(r->start, resource_size(r)); - if (!ldev->eng_regs) { - dev_err(&ldev->pldev->dev, "%s: failed to ioremap engine regs!\n", __func__); - rv = -ENXIO; - goto err_kfree; - } - - r = platform_get_resource(pldev, IORESOURCE_IRQ, 0); - if (!r) { - dev_err(&ldev->pldev->dev, "%s: didn't get the IRQ resource!\n", __func__); - rv = -ENXIO; - goto err_kfree; - } - ldev->irq = r->start; - - // Setup miscdev struct - dev = MKDEV(assigned_major_num, pldev->id); - ldev->kpc_dma_dev = device_create(kpc_dma_class, &pldev->dev, dev, ldev, - "kpc_dma%d", pldev->id); - if (IS_ERR(ldev->kpc_dma_dev)) { - rv = PTR_ERR(ldev->kpc_dma_dev); - dev_err(&ldev->pldev->dev, "%s: device_create failed: %d\n", __func__, rv); - goto err_kfree; - } - - // Setup the DMA engine - rv = setup_dma_engine(ldev, 30); - if (rv) { - dev_err(&ldev->pldev->dev, "%s: failed to setup_dma_engine: %d\n", __func__, rv); - goto err_misc_dereg; - } - - // Setup the sysfs files - rv = sysfs_create_files(&(ldev->pldev->dev.kobj), ndd_attr_list); - if (rv) { - dev_err(&ldev->pldev->dev, "%s: Failed to add sysfs files: %d\n", __func__, rv); - goto err_destroy_eng; - } - - kpc_dma_add_device(ldev); - - return 0; - - err_destroy_eng: - destroy_dma_engine(ldev); - err_misc_dereg: - device_destroy(kpc_dma_class, dev); - err_kfree: - kfree(ldev); - err_rv: - return rv; -} - -static -int kpc_dma_remove(struct platform_device *pldev) -{ - struct kpc_dma_device *ldev = platform_get_drvdata(pldev); - - if (!ldev) - return -ENXIO; - - lock_engine(ldev); - sysfs_remove_files(&(ldev->pldev->dev.kobj), ndd_attr_list); - destroy_dma_engine(ldev); - kpc_dma_del_device(ldev); - device_destroy(kpc_dma_class, MKDEV(assigned_major_num, ldev->pldev->id)); - kfree(ldev); - - return 0; -} - -/********** Driver Functions **********/ -static struct platform_driver kpc_dma_plat_driver_i = { - .probe = kpc_dma_probe, - .remove = kpc_dma_remove, - .driver = { - .name = KP_DRIVER_NAME_DMA_CONTROLLER, - }, -}; - -static -int __init kpc_dma_driver_init(void) -{ - int err; - - err = __register_chrdev(KPC_DMA_CHAR_MAJOR, 0, KPC_DMA_NUM_MINORS, - "kpc_dma", &kpc_dma_fops); - if (err < 0) { - pr_err("Can't allocate a major number (%d) for kpc_dma (err = %d)\n", - KPC_DMA_CHAR_MAJOR, err); - goto fail_chrdev_register; - } - assigned_major_num = err; - - kpc_dma_class = class_create(THIS_MODULE, "kpc_dma"); - err = PTR_ERR(kpc_dma_class); - if (IS_ERR(kpc_dma_class)) { - pr_err("Can't create class kpc_dma (err = %d)\n", err); - goto fail_class_create; - } - - err = platform_driver_register(&kpc_dma_plat_driver_i); - if (err) { - pr_err("Can't register platform driver for kpc_dma (err = %d)\n", err); - goto fail_platdriver_register; - } - - return err; - -fail_platdriver_register: - class_destroy(kpc_dma_class); -fail_class_create: - __unregister_chrdev(KPC_DMA_CHAR_MAJOR, 0, KPC_DMA_NUM_MINORS, "kpc_dma"); -fail_chrdev_register: - return err; -} -module_init(kpc_dma_driver_init); - -static -void __exit kpc_dma_driver_exit(void) -{ - platform_driver_unregister(&kpc_dma_plat_driver_i); - class_destroy(kpc_dma_class); - __unregister_chrdev(KPC_DMA_CHAR_MAJOR, 0, KPC_DMA_NUM_MINORS, "kpc_dma"); -} -module_exit(kpc_dma_driver_exit); diff --git a/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h b/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h deleted file mode 100644 index 8b9c978257b9..000000000000 --- a/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h +++ /dev/null @@ -1,222 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -#ifndef KPC_DMA_DRIVER_H -#define KPC_DMA_DRIVER_H -#include <linux/platform_device.h> -#include <linux/cdev.h> -#include <linux/kfifo.h> -#include <linux/list.h> -#include <linux/spinlock.h> -#include <linux/sched.h> -#include <linux/miscdevice.h> -#include <linux/rwsem.h> -#include <linux/dma-mapping.h> -#include <linux/dmapool.h> -#include <linux/pci.h> -#include <linux/interrupt.h> -#include <linux/workqueue.h> -#include <linux/bitops.h> -#include "../kpc.h" - -struct kp2000_device; -struct kpc_dma_device { - struct list_head list; - struct platform_device *pldev; - u32 __iomem *eng_regs; - struct device *kpc_dma_dev; - struct kobject kobj; - char name[16]; - - int dir; // DMA_FROM_DEVICE || DMA_TO_DEVICE - struct mutex sem; - unsigned int irq; - struct work_struct irq_work; - - atomic_t open_count; - - size_t accumulated_bytes; - u32 accumulated_flags; - - // Descriptor "Pool" housekeeping - u32 desc_pool_cnt; - struct dma_pool *desc_pool; - struct kpc_dma_descriptor *desc_pool_first; - struct kpc_dma_descriptor *desc_pool_last; - - struct kpc_dma_descriptor *desc_next; - struct kpc_dma_descriptor *desc_completed; -}; - -struct dev_private_data { - struct kpc_dma_device *ldev; - u64 card_addr; - u64 user_ctl; - u64 user_ctl_last; - u64 user_sts; -}; - -struct kpc_dma_device *kpc_dma_lookup_device(int minor); - -extern const struct file_operations kpc_dma_fops; - -#define ENG_CAP_PRESENT 0x00000001 -#define ENG_CAP_DIRECTION 0x00000002 -#define ENG_CAP_TYPE_MASK 0x000000F0 -#define ENG_CAP_NUMBER_MASK 0x0000FF00 -#define ENG_CAP_CARD_ADDR_SIZE_MASK 0x007F0000 -#define ENG_CAP_DESC_MAX_BYTE_CNT_MASK 0x3F000000 -#define ENG_CAP_PERF_SCALE_MASK 0xC0000000 - -#define ENG_CTL_IRQ_ENABLE BIT(0) -#define ENG_CTL_IRQ_ACTIVE BIT(1) -#define ENG_CTL_DESC_COMPLETE BIT(2) -#define ENG_CTL_DESC_ALIGN_ERR BIT(3) -#define ENG_CTL_DESC_FETCH_ERR BIT(4) -#define ENG_CTL_SW_ABORT_ERR BIT(5) -#define ENG_CTL_DESC_CHAIN_END BIT(7) -#define ENG_CTL_DMA_ENABLE BIT(8) -#define ENG_CTL_DMA_RUNNING BIT(10) -#define ENG_CTL_DMA_WAITING BIT(11) -#define ENG_CTL_DMA_WAITING_PERSIST BIT(12) -#define ENG_CTL_DMA_RESET_REQUEST BIT(14) -#define ENG_CTL_DMA_RESET BIT(15) -#define ENG_CTL_DESC_FETCH_ERR_CLASS_MASK 0x700000 - -struct aio_cb_data { - struct dev_private_data *priv; - struct kpc_dma_device *ldev; - struct completion *cpl; - unsigned char flags; - size_t len; - - unsigned int page_count; - struct page **user_pages; - struct sg_table sgt; - int mapped_entry_count; -}; - -#define ACD_FLAG_DONE 0 -#define ACD_FLAG_ABORT 1 -#define ACD_FLAG_ENG_ACCUM_ERROR 4 -#define ACD_FLAG_ENG_ACCUM_SHORT 5 - -struct kpc_dma_descriptor { - struct { - volatile u32 DescByteCount :20; - volatile u32 DescStatusErrorFlags :4; - volatile u32 DescStatusFlags :8; - }; - volatile u32 DescUserControlLS; - volatile u32 DescUserControlMS; - volatile u32 DescCardAddrLS; - struct { - volatile u32 DescBufferByteCount :20; - volatile u32 DescCardAddrMS :4; - volatile u32 DescControlFlags :8; - }; - volatile u32 DescSystemAddrLS; - volatile u32 DescSystemAddrMS; - volatile u32 DescNextDescPtr; - - dma_addr_t MyDMAAddr; - struct kpc_dma_descriptor *Next; - - struct aio_cb_data *acd; -} __attribute__((packed)); -// DescControlFlags: -#define DMA_DESC_CTL_SOP BIT(7) -#define DMA_DESC_CTL_EOP BIT(6) -#define DMA_DESC_CTL_AFIFO BIT(2) -#define DMA_DESC_CTL_IRQONERR BIT(1) -#define DMA_DESC_CTL_IRQONDONE BIT(0) -// DescStatusFlags: -#define DMA_DESC_STS_SOP BIT(7) -#define DMA_DESC_STS_EOP BIT(6) -#define DMA_DESC_STS_ERROR BIT(4) -#define DMA_DESC_STS_USMSZ BIT(3) -#define DMA_DESC_STS_USLSZ BIT(2) -#define DMA_DESC_STS_SHORT BIT(1) -#define DMA_DESC_STS_COMPLETE BIT(0) -// DescStatusErrorFlags: -#define DMA_DESC_ESTS_ECRC BIT(2) -#define DMA_DESC_ESTS_POISON BIT(1) -#define DMA_DESC_ESTS_UNSUCCESSFUL BIT(0) - -#define DMA_DESC_ALIGNMENT 0x20 - -static inline -u32 GetEngineCapabilities(struct kpc_dma_device *eng) -{ - return readl(eng->eng_regs + 0); -} - -static inline -void WriteEngineControl(struct kpc_dma_device *eng, u32 value) -{ - writel(value, eng->eng_regs + 1); -} - -static inline -u32 GetEngineControl(struct kpc_dma_device *eng) -{ - return readl(eng->eng_regs + 1); -} - -static inline -void SetClearEngineControl(struct kpc_dma_device *eng, u32 set_bits, u32 clear_bits) -{ - u32 val = GetEngineControl(eng); - - val |= set_bits; - val &= ~clear_bits; - WriteEngineControl(eng, val); -} - -static inline -void SetEngineNextPtr(struct kpc_dma_device *eng, struct kpc_dma_descriptor *desc) -{ - writel(desc->MyDMAAddr, eng->eng_regs + 2); -} - -static inline -void SetEngineSWPtr(struct kpc_dma_device *eng, struct kpc_dma_descriptor *desc) -{ - writel(desc->MyDMAAddr, eng->eng_regs + 3); -} - -static inline -void ClearEngineCompletePtr(struct kpc_dma_device *eng) -{ - writel(0, eng->eng_regs + 4); -} - -static inline -u32 GetEngineCompletePtr(struct kpc_dma_device *eng) -{ - return readl(eng->eng_regs + 4); -} - -static inline -void lock_engine(struct kpc_dma_device *eng) -{ - BUG_ON(!eng); - mutex_lock(&eng->sem); -} - -static inline -void unlock_engine(struct kpc_dma_device *eng) -{ - BUG_ON(!eng); - mutex_unlock(&eng->sem); -} - -/// Shared Functions -void start_dma_engine(struct kpc_dma_device *eng); -int setup_dma_engine(struct kpc_dma_device *eng, u32 desc_cnt); -void stop_dma_engine(struct kpc_dma_device *eng); -void destroy_dma_engine(struct kpc_dma_device *eng); -void clear_desc(struct kpc_dma_descriptor *desc); -int count_descriptors_available(struct kpc_dma_device *eng); -void transfer_complete_cb(struct aio_cb_data *acd, size_t xfr_count, u32 flags); - -#endif /* KPC_DMA_DRIVER_H */ - diff --git a/drivers/staging/kpc2000/kpc_dma/uapi.h b/drivers/staging/kpc2000/kpc_dma/uapi.h deleted file mode 100644 index 5ff6a1a36ff9..000000000000 --- a/drivers/staging/kpc2000/kpc_dma/uapi.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -#ifndef KPC_DMA_DRIVER_UAPI_H_ -#define KPC_DMA_DRIVER_UAPI_H_ -#include <linux/ioctl.h> - -#define KND_IOCTL_SET_CARD_ADDR _IOW('k', 1, __u32) -#define KND_IOCTL_SET_USER_CTL _IOW('k', 2, __u64) -#define KND_IOCTL_SET_USER_CTL_LAST _IOW('k', 4, __u64) -#define KND_IOCTL_GET_USER_STS _IOR('k', 3, __u64) - -#endif /* KPC_DMA_DRIVER_UAPI_H_ */ diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index 8bc3b7d8d3d5..eaa70893224a 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -524,13 +524,11 @@ void hostif_mib_get_confirm(struct ks_wlan_private *priv) struct net_device *dev = priv->net_dev; u32 mib_status; u32 mib_attribute; - u16 mib_val_size; - u16 mib_val_type; mib_status = get_dword(priv); mib_attribute = get_dword(priv); - mib_val_size = get_word(priv); - mib_val_type = get_word(priv); + get_word(priv); /* mib_val_size */ + get_word(priv); /* mib_val_type */ if (mib_status) { netdev_err(priv->net_dev, "attribute=%08X, status=%08X\n", @@ -846,9 +844,7 @@ void hostif_ps_adhoc_set_confirm(struct ks_wlan_private *priv) static void hostif_infrastructure_set_confirm(struct ks_wlan_private *priv) { - u16 result_code; - - result_code = get_word(priv); + get_word(priv); /* result_code */ priv->infra_status = 1; /* infrastructure mode set */ hostif_sme_enqueue(priv, SME_MODE_SET_CONFIRM); } @@ -926,14 +922,14 @@ static void hostif_phy_information_confirm(struct ks_wlan_private *priv) { struct iw_statistics *wstats = &priv->wstats; - u8 rssi, signal, noise; + u8 rssi, signal; u8 link_speed; u32 transmitted_frame_count, received_fragment_count; u32 failed_count, fcs_error_count; rssi = get_byte(priv); signal = get_byte(priv); - noise = get_byte(priv); + get_byte(priv); /* noise */ link_speed = get_byte(priv); transmitted_frame_count = get_dword(priv); received_fragment_count = get_dword(priv); diff --git a/drivers/staging/ks7010/ks_hostif.h b/drivers/staging/ks7010/ks_hostif.h index 39138191a556..c62a494ed6bb 100644 --- a/drivers/staging/ks7010/ks_hostif.h +++ b/drivers/staging/ks7010/ks_hostif.h @@ -498,20 +498,20 @@ struct hostif_mic_failure_request { #define TX_RATE_FIXED 5 /* 11b rate */ -#define TX_RATE_1M (u8)(10 / 5) /* 11b 11g basic rate */ -#define TX_RATE_2M (u8)(20 / 5) /* 11b 11g basic rate */ -#define TX_RATE_5M (u8)(55 / 5) /* 11g basic rate */ -#define TX_RATE_11M (u8)(110 / 5) /* 11g basic rate */ +#define TX_RATE_1M ((u8)(10 / 5)) /* 11b 11g basic rate */ +#define TX_RATE_2M ((u8)(20 / 5)) /* 11b 11g basic rate */ +#define TX_RATE_5M ((u8)(55 / 5)) /* 11g basic rate */ +#define TX_RATE_11M ((u8)(110 / 5)) /* 11g basic rate */ /* 11g rate */ -#define TX_RATE_6M (u8)(60 / 5) /* 11g basic rate */ -#define TX_RATE_12M (u8)(120 / 5) /* 11g basic rate */ -#define TX_RATE_24M (u8)(240 / 5) /* 11g basic rate */ -#define TX_RATE_9M (u8)(90 / 5) -#define TX_RATE_18M (u8)(180 / 5) -#define TX_RATE_36M (u8)(360 / 5) -#define TX_RATE_48M (u8)(480 / 5) -#define TX_RATE_54M (u8)(540 / 5) +#define TX_RATE_6M ((u8)(60 / 5)) /* 11g basic rate */ +#define TX_RATE_12M ((u8)(120 / 5)) /* 11g basic rate */ +#define TX_RATE_24M ((u8)(240 / 5)) /* 11g basic rate */ +#define TX_RATE_9M ((u8)(90 / 5)) +#define TX_RATE_18M ((u8)(180 / 5)) +#define TX_RATE_36M ((u8)(360 / 5)) +#define TX_RATE_48M ((u8)(480 / 5)) +#define TX_RATE_54M ((u8)(540 / 5)) static inline bool is_11b_rate(u8 rate) { diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c index b34e3c130f53..093ef9a2b291 100644 --- a/drivers/staging/most/dim2/dim2.c +++ b/drivers/staging/most/dim2/dim2.c @@ -50,8 +50,10 @@ static DECLARE_TASKLET_OLD(dim2_tasklet, dim2_tasklet_fn); /** * struct hdm_channel - private structure to keep channel specific data + * @name: channel name * @is_initialized: identifier to know whether the channel is initialized * @ch: HAL specific channel data + * @reset_dbr_size: reset DBR data buffer size * @pending_list: list to keep MBO's before starting transfer * @started_list: list to keep MBO's after starting transfer * @direction: channel direction (TX or RX) @@ -68,7 +70,7 @@ struct hdm_channel { enum most_channel_data_type data_type; }; -/** +/* * struct dim2_hdm - private structure to keep interface specific data * @hch: an array of channel specific data * @most_iface: most interface structure @@ -428,9 +430,9 @@ static void complete_all_mbos(struct list_head *head) /** * configure_channel - initialize a channel - * @iface: interface the channel belongs to - * @channel: channel to be configured - * @channel_config: structure that holds the configuration information + * @most_iface: interface the channel belongs to + * @ch_idx: channel index to be configured + * @ccfg: structure that holds the configuration information * * Receives configuration information from mostcore and initialize * the corresponding channel. Return 0 on success, negative on failure. @@ -546,8 +548,8 @@ static int configure_channel(struct most_interface *most_iface, int ch_idx, /** * enqueue - enqueue a buffer for data transfer - * @iface: intended interface - * @channel: ID of the channel the buffer is intended for + * @most_iface: intended interface + * @ch_idx: ID of the channel the buffer is intended for * @mbo: pointer to the buffer object * * Push the buffer into pending_list and try to transfer one buffer from @@ -579,8 +581,9 @@ static int enqueue(struct most_interface *most_iface, int ch_idx, /** * request_netinfo - triggers retrieving of network info - * @iface: pointer to the interface - * @channel_id: corresponding channel ID + * @most_iface: pointer to the interface + * @ch_idx: corresponding channel ID + * @on_netinfo: call-back used to deliver network status to mostcore * * Send a command to INIC which triggers retrieving of network info by means of * "Message exchange over MDP/MEP". Return 0 on success, negative on failure. @@ -621,8 +624,8 @@ static void request_netinfo(struct most_interface *most_iface, int ch_idx, /** * poison_channel - poison buffers of a channel - * @iface: pointer to the interface the channel to be poisoned belongs to - * @channel_id: corresponding channel ID + * @most_iface: pointer to the interface the channel to be poisoned belongs to + * @ch_idx: corresponding channel ID * * Destroy a channel and complete all the buffers in both started_list & * pending_list. Return 0 on success, negative on failure. diff --git a/drivers/staging/most/dim2/hal.c b/drivers/staging/most/dim2/hal.c index 39e17a7d2f24..65282c276862 100644 --- a/drivers/staging/most/dim2/hal.c +++ b/drivers/staging/most/dim2/hal.c @@ -96,9 +96,9 @@ static int dbr_get_mask_size(u16 size) } /** - * Allocates DBR memory. - * @param size Allocating memory size. - * @return Offset in DBR memory by success or DBR_SIZE if out of memory. + * alloc_dbr() - Allocates DBR memory. + * @size: Allocating memory size. + * Returns: Offset in DBR memory by success or DBR_SIZE if out of memory. */ static int alloc_dbr(u16 size) { @@ -778,7 +778,7 @@ void dim_service_mlb_int_irq(void) writel(0, &g.dim2->MS1); } -/** +/* * Retrieves maximal possible correct buffer size for isochronous data type * conform to given packet length and not bigger than given buffer size. * @@ -792,7 +792,7 @@ u16 dim_norm_isoc_buffer_size(u16 buf_size, u16 packet_length) return norm_isoc_buffer_size(buf_size, packet_length); } -/** +/* * Retrieves maximal possible correct buffer size for synchronous data type * conform to given bytes per frame and not bigger than given buffer size. * diff --git a/drivers/staging/most/i2c/i2c.c b/drivers/staging/most/i2c/i2c.c index 893a8babdb2f..7042f10887bb 100644 --- a/drivers/staging/most/i2c/i2c.c +++ b/drivers/staging/most/i2c/i2c.c @@ -51,8 +51,8 @@ static void pending_rx_work(struct work_struct *); /** * configure_channel - called from MOST core to configure a channel - * @iface: interface the channel belongs to - * @channel: channel to be configured + * @most_iface: interface the channel belongs to + * @ch_idx: channel to be configured * @channel_config: structure that holds the configuration information * * Return 0 on success, negative on failure. @@ -107,8 +107,8 @@ static int configure_channel(struct most_interface *most_iface, /** * enqueue - called from MOST core to enqueue a buffer for data transfer - * @iface: intended interface - * @channel: ID of the channel the buffer is intended for + * @most_iface: intended interface + * @ch_idx: ID of the channel the buffer is intended for * @mbo: pointer to the buffer object * * Return 0 on success, negative on failure. @@ -153,8 +153,8 @@ static int enqueue(struct most_interface *most_iface, /** * poison_channel - called from MOST core to poison buffers of a channel - * @iface: pointer to the interface the channel to be poisoned belongs to - * @channel_id: corresponding channel ID + * @most_iface: pointer to the interface the channel to be poisoned belongs to + * @ch_idx: corresponding channel ID * * Return 0 on success, negative on failure. * diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c index f125bb6da406..a5fd14246046 100644 --- a/drivers/staging/most/net/net.c +++ b/drivers/staging/most/net/net.c @@ -539,9 +539,9 @@ static void __exit most_net_exit(void) /** * on_netinfo - callback for HDM to be informed about HW's MAC - * @param iface - most interface instance - * @param link_stat - link status - * @param mac_addr - MAC address + * @iface: most interface instance + * @link_stat: link status + * @mac_addr: MAC address */ static void on_netinfo(struct most_interface *iface, unsigned char link_stat, unsigned char *mac_addr) diff --git a/drivers/staging/mt7621-dts/gbpc1.dts b/drivers/staging/mt7621-dts/gbpc1.dts index 7716d0efe524..b65d71686814 100644 --- a/drivers/staging/mt7621-dts/gbpc1.dts +++ b/drivers/staging/mt7621-dts/gbpc1.dts @@ -101,12 +101,6 @@ }; &pcie { - pinctrl-names = "default"; - pinctrl-0 = <&pcie_pins>; - - reset-gpios = <&gpio 19 GPIO_ACTIVE_LOW>, - <&gpio 8 GPIO_ACTIVE_LOW>, - <&gpio 7 GPIO_ACTIVE_LOW>; status = "okay"; }; diff --git a/drivers/staging/mt7621-dts/mt7621.dtsi b/drivers/staging/mt7621-dts/mt7621.dtsi index 093a7f8091b5..eeabe9c0f4fb 100644 --- a/drivers/staging/mt7621-dts/mt7621.dtsi +++ b/drivers/staging/mt7621-dts/mt7621.dtsi @@ -55,7 +55,7 @@ #address-cells = <1>; #size-cells = <1>; - sysc: sysc@0 { + sysc: syscon@0 { compatible = "mediatek,mt7621-sysc", "syscon"; reg = <0x0 0x100>; #clock-cells = <1>; @@ -122,7 +122,7 @@ status = "disabled"; }; - memc: memc@5000 { + memc: syscon@5000 { compatible = "mediatek,mt7621-memc", "syscon"; reg = <0x5000 0x1000>; }; @@ -372,13 +372,6 @@ clock-names = "nand"; }; - ethsys: syscon@1e000000 { - compatible = "mediatek,mt7621-ethsys", - "syscon"; - reg = <0x1e000000 0x1000>; - #clock-cells = <1>; - }; - ethernet: ethernet@1e100000 { compatible = "mediatek,mt7621-eth"; reg = <0x1e100000 0x10000>; @@ -396,7 +389,7 @@ interrupt-parent = <&gic>; interrupts = <GIC_SHARED 3 IRQ_TYPE_LEVEL_HIGH>; - mediatek,ethsys = <ðsys>; + mediatek,ethsys = <&sysc>; gmac0: mac@0 { @@ -488,10 +481,10 @@ pcie: pcie@1e140000 { compatible = "mediatek,mt7621-pci"; - reg = <0x1e140000 0x100 /* host-pci bridge registers */ - 0x1e142000 0x100 /* pcie port 0 RC control registers */ - 0x1e143000 0x100 /* pcie port 1 RC control registers */ - 0x1e144000 0x100>; /* pcie port 2 RC control registers */ + reg = <0x1e140000 0x100>, /* host-pci bridge registers */ + <0x1e142000 0x100>, /* pcie port 0 RC control registers */ + <0x1e143000 0x100>, /* pcie port 1 RC control registers */ + <0x1e144000 0x100>; /* pcie port 2 RC control registers */ #address-cells = <3>; #size-cells = <2>; @@ -500,64 +493,76 @@ device_type = "pci"; - bus-range = <0 255>; - ranges = < - 0x02000000 0 0x00000000 0x60000000 0 0x10000000 /* pci memory */ - 0x01000000 0 0x00000000 0x1e160000 0 0x00010000 /* io space */ - >; + ranges = <0x02000000 0 0x60000000 0x60000000 0 0x10000000>, /* pci memory */ + <0x01000000 0 0x00000000 0x1e160000 0 0x00010000>; /* io space */ - interrupt-parent = <&gic>; - interrupts = <GIC_SHARED 4 IRQ_TYPE_LEVEL_HIGH - GIC_SHARED 24 IRQ_TYPE_LEVEL_HIGH - GIC_SHARED 25 IRQ_TYPE_LEVEL_HIGH>; + #interrupt-cells = <1>; + interrupt-map-mask = <0xF800 0 0 0>; + interrupt-map = <0x0000 0 0 0 &gic GIC_SHARED 4 IRQ_TYPE_LEVEL_HIGH>, + <0x0800 0 0 0 &gic GIC_SHARED 24 IRQ_TYPE_LEVEL_HIGH>, + <0x1000 0 0 0 &gic GIC_SHARED 25 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; - resets = <&rstctrl 24 &rstctrl 25 &rstctrl 26>; - reset-names = "pcie0", "pcie1", "pcie2"; - clocks = <&sysc MT7621_CLK_PCIE0>, - <&sysc MT7621_CLK_PCIE1>, - <&sysc MT7621_CLK_PCIE2>; - clock-names = "pcie0", "pcie1", "pcie2"; - phys = <&pcie0_phy 1>, <&pcie2_phy 0>; - phy-names = "pcie-phy0", "pcie-phy2"; - reset-gpios = <&gpio 19 GPIO_ACTIVE_LOW>; pcie@0,0 { reg = <0x0000 0 0 0 0>; #address-cells = <3>; #size-cells = <2>; + device_type = "pci"; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SHARED 4 IRQ_TYPE_LEVEL_HIGH>; + resets = <&rstctrl 24>; + clocks = <&sysc MT7621_CLK_PCIE0>; + phys = <&pcie0_phy 1>; + phy-names = "pcie-phy0"; ranges; - bus-range = <0x00 0xff>; }; pcie@1,0 { reg = <0x0800 0 0 0 0>; #address-cells = <3>; #size-cells = <2>; + device_type = "pci"; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SHARED 24 IRQ_TYPE_LEVEL_HIGH>; + resets = <&rstctrl 25>; + clocks = <&sysc MT7621_CLK_PCIE1>; + phys = <&pcie0_phy 1>; + phy-names = "pcie-phy1"; ranges; - bus-range = <0x00 0xff>; }; pcie@2,0 { reg = <0x1000 0 0 0 0>; #address-cells = <3>; #size-cells = <2>; + device_type = "pci"; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SHARED 25 IRQ_TYPE_LEVEL_HIGH>; + resets = <&rstctrl 26>; + clocks = <&sysc MT7621_CLK_PCIE2>; + phys = <&pcie2_phy 0>; + phy-names = "pcie-phy2"; ranges; - bus-range = <0x00 0xff>; }; }; pcie0_phy: pcie-phy@1e149000 { compatible = "mediatek,mt7621-pci-phy"; reg = <0x1e149000 0x0700>; + clocks = <&sysc MT7621_CLK_XTAL>; #phy-cells = <1>; }; pcie2_phy: pcie-phy@1e14a000 { compatible = "mediatek,mt7621-pci-phy"; reg = <0x1e14a000 0x0700>; + clocks = <&sysc MT7621_CLK_XTAL>; #phy-cells = <1>; }; }; diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c index 115250115f10..691030e1a5ed 100644 --- a/drivers/staging/mt7621-pci/pci-mt7621.c +++ b/drivers/staging/mt7621-pci/pci-mt7621.c @@ -16,13 +16,12 @@ */ #include <linux/bitops.h> +#include <linux/clk.h> #include <linux/delay.h> #include <linux/gpio/consumer.h> -#include <linux/iopoll.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_irq.h> #include <linux/of_pci.h> #include <linux/of_platform.h> #include <linux/pci.h> @@ -30,22 +29,12 @@ #include <linux/platform_device.h> #include <linux/reset.h> #include <linux/sys_soc.h> -#include <mt7621.h> -#include <ralink_regs.h> - -#include "../../pci/pci.h" - -/* sysctl */ -#define MT7621_GPIO_MODE 0x60 /* MediaTek specific configuration registers */ #define PCIE_FTS_NUM 0x70c #define PCIE_FTS_NUM_MASK GENMASK(15, 8) #define PCIE_FTS_NUM_L0(x) (((x) & 0xff) << 8) -/* rt_sysc_membase relative registers */ -#define RALINK_CLKCFG1 0x30 - /* Host-PCI bridge registers */ #define RALINK_PCI_PCICFG_ADDR 0x0000 #define RALINK_PCI_PCIMSK_ADDR 0x000C @@ -54,20 +43,7 @@ #define RALINK_PCI_MEMBASE 0x0028 #define RALINK_PCI_IOBASE 0x002C -/* PCICFG virtual bridges */ -#define PCIE_P2P_CNT 3 -#define PCIE_P2P_BR_DEVNUM_SHIFT(p) (16 + (p) * 4) -#define PCIE_P2P_BR_DEVNUM0_SHIFT PCIE_P2P_BR_DEVNUM_SHIFT(0) -#define PCIE_P2P_BR_DEVNUM1_SHIFT PCIE_P2P_BR_DEVNUM_SHIFT(1) -#define PCIE_P2P_BR_DEVNUM2_SHIFT PCIE_P2P_BR_DEVNUM_SHIFT(2) -#define PCIE_P2P_BR_DEVNUM_MASK 0xf -#define PCIE_P2P_BR_DEVNUM_MASK_FULL (0xfff << PCIE_P2P_BR_DEVNUM0_SHIFT) - /* PCIe RC control registers */ -#define MT7621_PCIE_OFFSET 0x2000 -#define MT7621_NEXT_PORT 0x1000 - -#define RALINK_PCI_BAR0SETUP_ADDR 0x0010 #define RALINK_PCI_ID 0x0030 #define RALINK_PCI_CLASS 0x0034 #define RALINK_PCI_SUBID 0x0038 @@ -79,11 +55,8 @@ #define PCIE_BAR_MAP_MAX GENMASK(30, 16) #define PCIE_BAR_ENABLE BIT(0) #define PCIE_PORT_INT_EN(x) BIT(20 + (x)) -#define PCIE_PORT_CLK_EN(x) BIT(24 + (x)) #define PCIE_PORT_LINKUP BIT(0) -#define PERST_MODE_MASK GENMASK(11, 10) -#define PERST_MODE_GPIO BIT(10) #define PERST_DELAY_MS 100 /** @@ -91,76 +64,68 @@ * @base: I/O mapped register base * @list: port list * @pcie: pointer to PCIe host info + * @clk: pointer to the port clock gate * @phy: pointer to PHY control block * @pcie_rst: pointer to port reset control * @gpio_rst: gpio reset * @slot: port slot - * @irq: GIC irq * @enabled: indicates if port is enabled */ struct mt7621_pcie_port { void __iomem *base; struct list_head list; struct mt7621_pcie *pcie; + struct clk *clk; struct phy *phy; struct reset_control *pcie_rst; struct gpio_desc *gpio_rst; u32 slot; - int irq; bool enabled; }; /** * struct mt7621_pcie - PCIe host information * @base: IO Mapped Register Base - * @io: IO resource - * @mem: pointer to non-prefetchable memory resource * @dev: Pointer to PCIe device - * @io_map_base: virtual memory base address for io * @ports: pointer to PCIe port information - * @irq_map: irq mapping info according pcie link status * @resets_inverted: depends on chip revision * reset lines are inverted. */ struct mt7621_pcie { void __iomem *base; struct device *dev; - struct resource io; - struct resource *mem; - unsigned long io_map_base; struct list_head ports; - int irq_map[PCIE_P2P_CNT]; bool resets_inverted; }; static inline u32 pcie_read(struct mt7621_pcie *pcie, u32 reg) { - return readl(pcie->base + reg); + return readl_relaxed(pcie->base + reg); } static inline void pcie_write(struct mt7621_pcie *pcie, u32 val, u32 reg) { - writel(val, pcie->base + reg); + writel_relaxed(val, pcie->base + reg); } static inline void pcie_rmw(struct mt7621_pcie *pcie, u32 reg, u32 clr, u32 set) { - u32 val = readl(pcie->base + reg); + u32 val = readl_relaxed(pcie->base + reg); val &= ~clr; val |= set; - writel(val, pcie->base + reg); + writel_relaxed(val, pcie->base + reg); } static inline u32 pcie_port_read(struct mt7621_pcie_port *port, u32 reg) { - return readl(port->base + reg); + return readl_relaxed(port->base + reg); } static inline void pcie_port_write(struct mt7621_pcie_port *port, u32 val, u32 reg) { - writel(val, port->base + reg); + writel_relaxed(val, port->base + reg); } static inline u32 mt7621_pci_get_cfgaddr(unsigned int bus, unsigned int slot, @@ -177,7 +142,7 @@ static void __iomem *mt7621_pcie_map_bus(struct pci_bus *bus, u32 address = mt7621_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where); - writel(address, pcie->base + RALINK_PCI_CONFIG_ADDR); + writel_relaxed(address, pcie->base + RALINK_PCI_CONFIG_ADDR); return pcie->base + RALINK_PCI_CONFIG_DATA + (where & 3); } @@ -222,16 +187,6 @@ static inline bool mt7621_pcie_port_is_linkup(struct mt7621_pcie_port *port) return (pcie_port_read(port, RALINK_PCI_STATUS) & PCIE_PORT_LINKUP) != 0; } -static inline void mt7621_pcie_port_clk_enable(struct mt7621_pcie_port *port) -{ - rt_sysc_m32(0, PCIE_PORT_CLK_EN(port->slot), RALINK_CLKCFG1); -} - -static inline void mt7621_pcie_port_clk_disable(struct mt7621_pcie_port *port) -{ - rt_sysc_m32(PCIE_PORT_CLK_EN(port->slot), 0, RALINK_CLKCFG1); -} - static inline void mt7621_control_assert(struct mt7621_pcie_port *port) { struct mt7621_pcie *pcie = port->pcie; @@ -252,96 +207,46 @@ static inline void mt7621_control_deassert(struct mt7621_pcie_port *port) reset_control_assert(port->pcie_rst); } -static void setup_cm_memory_region(struct mt7621_pcie *pcie) +static int setup_cm_memory_region(struct pci_host_bridge *host) { - struct resource *mem_resource = pcie->mem; + struct mt7621_pcie *pcie = pci_host_bridge_priv(host); struct device *dev = pcie->dev; + struct resource_entry *entry; resource_size_t mask; + entry = resource_list_first_type(&host->windows, IORESOURCE_MEM); + if (!entry) { + dev_err(dev, "Cannot get memory resource\n"); + return -EINVAL; + } + if (mips_cps_numiocu(0)) { /* * FIXME: hardware doesn't accept mask values with 1s after * 0s (e.g. 0xffef), so it would be great to warn if that's * about to happen */ - mask = ~(mem_resource->end - mem_resource->start); + mask = ~(entry->res->end - entry->res->start); - write_gcr_reg1_base(mem_resource->start); + write_gcr_reg1_base(entry->res->start); write_gcr_reg1_mask(mask | CM_GCR_REGn_MASK_CMTGT_IOCU0); dev_info(dev, "PCI coherence region base: 0x%08llx, mask/settings: 0x%08llx\n", (unsigned long long)read_gcr_reg1_base(), (unsigned long long)read_gcr_reg1_mask()); } -} - -static int mt7621_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin) -{ - struct mt7621_pcie *pcie = pdev->bus->sysdata; - struct device *dev = pcie->dev; - int irq = pcie->irq_map[slot]; - - dev_info(dev, "bus=%d slot=%d irq=%d\n", pdev->bus->number, slot, irq); - return irq; -} - -static int mt7621_pci_parse_request_of_pci_ranges(struct pci_host_bridge *host) -{ - struct mt7621_pcie *pcie = pci_host_bridge_priv(host); - struct device *dev = pcie->dev; - struct device_node *node = dev->of_node; - struct of_pci_range_parser parser; - struct resource_entry *entry; - struct of_pci_range range; - LIST_HEAD(res); - - if (of_pci_range_parser_init(&parser, node)) { - dev_err(dev, "missing \"ranges\" property\n"); - return -EINVAL; - } - - /* - * IO_SPACE_LIMIT for MIPS is 0xffff but this platform uses IO at - * upper address 0x001e160000. of_pci_range_to_resource does not work - * well for MIPS platforms that don't define PCI_IOBASE, so set the IO - * resource manually instead. - */ - pcie->io.name = node->full_name; - pcie->io.parent = pcie->io.child = pcie->io.sibling = NULL; - for_each_of_pci_range(&parser, &range) { - switch (range.flags & IORESOURCE_TYPE_BITS) { - case IORESOURCE_IO: - pcie->io_map_base = - (unsigned long)ioremap(range.cpu_addr, - range.size); - pcie->io.flags = range.flags; - pcie->io.start = range.cpu_addr; - pcie->io.end = range.cpu_addr + range.size - 1; - set_io_port_base(pcie->io_map_base); - break; - } - } - - entry = resource_list_first_type(&host->windows, IORESOURCE_MEM); - if (!entry) { - dev_err(dev, "Cannot get memory resource"); - return -EINVAL; - } - - pcie->mem = entry->res; - pci_add_resource(&res, &pcie->io); - pci_add_resource(&res, entry->res); - list_splice_init(&res, &host->windows); return 0; } static int mt7621_pcie_parse_port(struct mt7621_pcie *pcie, + struct device_node *node, int slot) { struct mt7621_pcie_port *port; struct device *dev = pcie->dev; struct platform_device *pdev = to_platform_device(dev); char name[10]; + int err; port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); if (!port) @@ -351,38 +256,45 @@ static int mt7621_pcie_parse_port(struct mt7621_pcie *pcie, if (IS_ERR(port->base)) return PTR_ERR(port->base); - snprintf(name, sizeof(name), "pcie%d", slot); - port->pcie_rst = devm_reset_control_get_exclusive(dev, name); + port->clk = devm_get_clk_from_child(dev, node, NULL); + if (IS_ERR(port->clk)) { + dev_err(dev, "failed to get pcie%d clock\n", slot); + return PTR_ERR(port->clk); + } + + port->pcie_rst = of_reset_control_get_exclusive(node, NULL); if (PTR_ERR(port->pcie_rst) == -EPROBE_DEFER) { dev_err(dev, "failed to get pcie%d reset control\n", slot); return PTR_ERR(port->pcie_rst); } snprintf(name, sizeof(name), "pcie-phy%d", slot); - port->phy = devm_phy_get(dev, name); - if (IS_ERR(port->phy) && slot != 1) - return PTR_ERR(port->phy); + port->phy = devm_of_phy_get(dev, node, name); + if (IS_ERR(port->phy)) { + dev_err(dev, "failed to get pcie-phy%d\n", slot); + err = PTR_ERR(port->phy); + goto remove_reset; + } port->gpio_rst = devm_gpiod_get_index_optional(dev, "reset", slot, GPIOD_OUT_LOW); if (IS_ERR(port->gpio_rst)) { dev_err(dev, "Failed to get GPIO for PCIe%d\n", slot); - return PTR_ERR(port->gpio_rst); + err = PTR_ERR(port->gpio_rst); + goto remove_reset; } port->slot = slot; port->pcie = pcie; - port->irq = platform_get_irq(pdev, slot); - if (port->irq < 0) { - dev_err(dev, "Failed to get IRQ for PCIe%d\n", slot); - return -ENXIO; - } - INIT_LIST_HEAD(&port->list); list_add_tail(&port->list, &pcie->ports); return 0; + +remove_reset: + reset_control_put(port->pcie_rst); + return err; } static int mt7621_pcie_parse_dt(struct mt7621_pcie *pcie) @@ -408,7 +320,7 @@ static int mt7621_pcie_parse_dt(struct mt7621_pcie *pcie) slot = PCI_SLOT(err); - err = mt7621_pcie_parse_port(pcie, slot); + err = mt7621_pcie_parse_port(pcie, child, slot); if (err) { of_node_put(child); return err; @@ -455,7 +367,7 @@ static void mt7621_pcie_reset_assert(struct mt7621_pcie *pcie) mt7621_rst_gpio_pcie_assert(port); } - mdelay(PERST_DELAY_MS); + msleep(PERST_DELAY_MS); } static void mt7621_pcie_reset_rc_deassert(struct mt7621_pcie *pcie) @@ -473,7 +385,7 @@ static void mt7621_pcie_reset_ep_deassert(struct mt7621_pcie *pcie) list_for_each_entry(port, &pcie->ports, list) mt7621_rst_gpio_pcie_deassert(port); - mdelay(PERST_DELAY_MS); + msleep(PERST_DELAY_MS); } static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie) @@ -482,8 +394,6 @@ static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie) struct mt7621_pcie_port *port, *tmp; int err; - rt_sysc_m32(PERST_MODE_MASK, PERST_MODE_GPIO, MT7621_GPIO_MODE); - mt7621_pcie_reset_assert(pcie); mt7621_pcie_reset_rc_deassert(pcie); @@ -512,7 +422,7 @@ static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie) dev_err(dev, "pcie%d no card, disable it (RST & CLK)\n", slot); mt7621_control_assert(port); - mt7621_pcie_port_clk_disable(port); + clk_disable_unprepare(port->clk); port->enabled = false; if (slot == 0) { @@ -530,7 +440,6 @@ static void mt7621_pcie_enable_port(struct mt7621_pcie_port *port) { struct mt7621_pcie *pcie = port->pcie; u32 slot = port->slot; - u32 offset = MT7621_PCIE_OFFSET + (slot * MT7621_NEXT_PORT); u32 val; /* enable pcie interrupt */ @@ -539,95 +448,52 @@ static void mt7621_pcie_enable_port(struct mt7621_pcie_port *port) pcie_write(pcie, val, RALINK_PCI_PCIMSK_ADDR); /* map 2G DDR region */ - pcie_write(pcie, PCIE_BAR_MAP_MAX | PCIE_BAR_ENABLE, - offset + RALINK_PCI_BAR0SETUP_ADDR); + pcie_port_write(port, PCIE_BAR_MAP_MAX | PCIE_BAR_ENABLE, + PCI_BASE_ADDRESS_0); /* configure class code and revision ID */ - pcie_write(pcie, PCIE_CLASS_CODE | PCIE_REVISION_ID, - offset + RALINK_PCI_CLASS); + pcie_port_write(port, PCIE_CLASS_CODE | PCIE_REVISION_ID, + RALINK_PCI_CLASS); + + /* configure RC FTS number to 250 when it leaves L0s */ + val = read_config(pcie, slot, PCIE_FTS_NUM); + val &= ~PCIE_FTS_NUM_MASK; + val |= PCIE_FTS_NUM_L0(0x50); + write_config(pcie, slot, PCIE_FTS_NUM, val); } -static void mt7621_pcie_enable_ports(struct mt7621_pcie *pcie) +static int mt7621_pcie_enable_ports(struct pci_host_bridge *host) { + struct mt7621_pcie *pcie = pci_host_bridge_priv(host); struct device *dev = pcie->dev; struct mt7621_pcie_port *port; - u8 num_slots_enabled = 0; - u32 slot; - u32 val; + struct resource_entry *entry; + int err; + + entry = resource_list_first_type(&host->windows, IORESOURCE_IO); + if (!entry) { + dev_err(dev, "Cannot get io resource\n"); + return -EINVAL; + } /* Setup MEMWIN and IOWIN */ pcie_write(pcie, 0xffffffff, RALINK_PCI_MEMBASE); - pcie_write(pcie, pcie->io.start, RALINK_PCI_IOBASE); + pcie_write(pcie, entry->res->start, RALINK_PCI_IOBASE); list_for_each_entry(port, &pcie->ports, list) { if (port->enabled) { - mt7621_pcie_port_clk_enable(port); + err = clk_prepare_enable(port->clk); + if (err) { + dev_err(dev, "enabling clk pcie%d\n", + port->slot); + return err; + } + mt7621_pcie_enable_port(port); dev_info(dev, "PCIE%d enabled\n", port->slot); - num_slots_enabled++; } } - for (slot = 0; slot < num_slots_enabled; slot++) { - val = read_config(pcie, slot, PCI_COMMAND); - val |= PCI_COMMAND_MASTER; - write_config(pcie, slot, PCI_COMMAND, val); - /* configure RC FTS number to 250 when it leaves L0s */ - val = read_config(pcie, slot, PCIE_FTS_NUM); - val &= ~PCIE_FTS_NUM_MASK; - val |= PCIE_FTS_NUM_L0(0x50); - write_config(pcie, slot, PCIE_FTS_NUM, val); - } -} - -static int mt7621_pcie_init_virtual_bridges(struct mt7621_pcie *pcie) -{ - u32 pcie_link_status = 0; - u32 n = 0; - int i = 0; - u32 p2p_br_devnum[PCIE_P2P_CNT]; - int irqs[PCIE_P2P_CNT]; - struct mt7621_pcie_port *port; - - list_for_each_entry(port, &pcie->ports, list) { - u32 slot = port->slot; - - irqs[i++] = port->irq; - if (port->enabled) - pcie_link_status |= BIT(slot); - } - - if (pcie_link_status == 0) - return -1; - - /* - * Assign device numbers from zero to the enabled ports, - * then assigning remaining device numbers to any disabled - * ports. - */ - for (i = 0; i < PCIE_P2P_CNT; i++) - if (pcie_link_status & BIT(i)) - p2p_br_devnum[i] = n++; - - for (i = 0; i < PCIE_P2P_CNT; i++) - if ((pcie_link_status & BIT(i)) == 0) - p2p_br_devnum[i] = n++; - - pcie_rmw(pcie, RALINK_PCI_PCICFG_ADDR, - PCIE_P2P_BR_DEVNUM_MASK_FULL, - (p2p_br_devnum[0] << PCIE_P2P_BR_DEVNUM0_SHIFT) | - (p2p_br_devnum[1] << PCIE_P2P_BR_DEVNUM1_SHIFT) | - (p2p_br_devnum[2] << PCIE_P2P_BR_DEVNUM2_SHIFT)); - - /* Assign IRQs */ - n = 0; - for (i = 0; i < PCIE_P2P_CNT; i++) - if (pcie_link_status & BIT(i)) - pcie->irq_map[n++] = irqs[i]; - - for (i = n; i < PCIE_P2P_CNT; i++) - pcie->irq_map[i] = -1; - return 0; } @@ -636,9 +502,7 @@ static int mt7621_pcie_register_host(struct pci_host_bridge *host) struct mt7621_pcie *pcie = pci_host_bridge_priv(host); host->ops = &mt7621_pci_ops; - host->map_irq = mt7621_map_irq; host->sysdata = pcie; - return pci_host_probe(host); } @@ -650,6 +514,7 @@ static int mt7621_pci_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; const struct soc_device_attribute *attr; + struct mt7621_pcie_port *port; struct mt7621_pcie *pcie; struct pci_host_bridge *bridge; int err; @@ -676,33 +541,36 @@ static int mt7621_pci_probe(struct platform_device *pdev) return err; } - err = mt7621_pci_parse_request_of_pci_ranges(bridge); + mt7621_pcie_init_ports(pcie); + + err = mt7621_pcie_enable_ports(bridge); if (err) { - dev_err(dev, "Error requesting pci resources from ranges"); - return err; + dev_err(dev, "Error enabling pcie ports\n"); + goto remove_resets; } - /* set resources limits */ - ioport_resource.start = pcie->io.start; - ioport_resource.end = pcie->io.end; - - mt7621_pcie_init_ports(pcie); - - err = mt7621_pcie_init_virtual_bridges(pcie); + err = setup_cm_memory_region(bridge); if (err) { - dev_err(dev, "Nothing is connected in virtual bridges. Exiting..."); - return 0; + dev_err(dev, "Error setting up iocu mem regions\n"); + goto remove_resets; } - mt7621_pcie_enable_ports(pcie); + return mt7621_pcie_register_host(bridge); - setup_cm_memory_region(pcie); +remove_resets: + list_for_each_entry(port, &pcie->ports, list) + reset_control_put(port->pcie_rst); - err = mt7621_pcie_register_host(bridge); - if (err) { - dev_err(dev, "Error registering host\n"); - return err; - } + return err; +} + +static int mt7621_pci_remove(struct platform_device *pdev) +{ + struct mt7621_pcie *pcie = platform_get_drvdata(pdev); + struct mt7621_pcie_port *port; + + list_for_each_entry(port, &pcie->ports, list) + reset_control_put(port->pcie_rst); return 0; } @@ -715,10 +583,10 @@ MODULE_DEVICE_TABLE(of, mt7621_pci_ids); static struct platform_driver mt7621_pci_driver = { .probe = mt7621_pci_probe, + .remove = mt7621_pci_remove, .driver = { .name = "mt7621-pci", .of_match_table = of_match_ptr(mt7621_pci_ids), }, }; - builtin_platform_driver(mt7621_pci_driver); diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index a80996b2f5ce..990d15c31a13 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -99,6 +99,7 @@ static const struct mfd_cell nvec_devices[] = { * nvec_register_notifier - Register a notifier with nvec * @nvec: A &struct nvec_chip * @nb: The notifier block to register + * @events: Unused * * Registers a notifier with @nvec. The notifier will be added to an atomic * notifier chain that is called for all received messages except those that @@ -125,7 +126,7 @@ int nvec_unregister_notifier(struct nvec_chip *nvec, struct notifier_block *nb) } EXPORT_SYMBOL_GPL(nvec_unregister_notifier); -/** +/* * nvec_status_notifier - The final notifier * * Prints a message about control events not handled in the notifier @@ -343,8 +344,8 @@ static void nvec_toggle_global_events(struct nvec_chip *nvec, bool state) /** * nvec_event_mask - fill the command string with event bitfield - * ev: points to event command string - * mask: bit to insert into the event mask + * @ev: points to event command string + * @mask: bit to insert into the event mask * * Configure event command expects a 32 bit bitfield which describes * which events to enable. The bitfield has the following structure diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index 9c71ad5af7b9..1ad94c5060b5 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -504,7 +504,6 @@ skip_xmit: * cvm_oct_xmit_pow - transmit a packet to the POW * @skb: Packet to send * @dev: Device info structure - * Returns Always returns zero */ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev) diff --git a/drivers/staging/qlge/qlge_ethtool.c b/drivers/staging/qlge/qlge_ethtool.c index b70570b7b467..87d60115ac67 100644 --- a/drivers/staging/qlge/qlge_ethtool.c +++ b/drivers/staging/qlge/qlge_ethtool.c @@ -553,7 +553,7 @@ static int qlge_run_loopback_test(struct qlge_adapter *qdev) atomic_inc(&qdev->lb_count); } /* Give queue time to settle before testing results. */ - msleep(2); + usleep_range(2000, 2100); qlge_clean_lb_rx_ring(&qdev->rx_ring[0], 128); return atomic_read(&qdev->lb_count) ? -EIO : 0; } diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c index c9dc6a852af4..19a02e958865 100644 --- a/drivers/staging/qlge/qlge_main.c +++ b/drivers/staging/qlge/qlge_main.c @@ -1389,7 +1389,7 @@ static void qlge_categorize_rx_err(struct qlge_adapter *qdev, u8 rx_err, } } -/** +/* * qlge_update_mac_hdr_len - helper routine to update the mac header length * based on vlan tags if present */ @@ -2235,7 +2235,7 @@ static void qlge_vlan_mode(struct net_device *ndev, netdev_features_t features) } } -/** +/* * qlge_update_hw_vlan_features - helper routine to reinitialize the adapter * based on the features to enable/disable hardware vlan accel */ @@ -2796,12 +2796,8 @@ static int qlge_init_bq(struct qlge_bq *bq) bq->base = dma_alloc_coherent(&qdev->pdev->dev, QLGE_BQ_SIZE, &bq->base_dma, GFP_ATOMIC); - if (!bq->base) { - netif_err(qdev, ifup, qdev->ndev, - "ring %u %s allocation failed.\n", rx_ring->cq_id, - bq_type_name[bq->type]); + if (!bq->base) return -ENOMEM; - } bq->queue = kmalloc_array(QLGE_BQ_LEN, sizeof(struct qlge_bq_desc), GFP_KERNEL); diff --git a/drivers/staging/rtl8188eu/Makefile b/drivers/staging/rtl8188eu/Makefile index 7da911c2ab89..28b936e8be0a 100644 --- a/drivers/staging/rtl8188eu/Makefile +++ b/drivers/staging/rtl8188eu/Makefile @@ -2,7 +2,6 @@ r8188eu-y := \ core/rtw_ap.o \ core/rtw_cmd.o \ - core/rtw_debug.o \ core/rtw_efuse.o \ core/rtw_ieee80211.o \ core/rtw_ioctl_set.o \ diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c index 008b60e72758..b817aa8b9de4 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ap.c +++ b/drivers/staging/rtl8188eu/core/rtw_ap.c @@ -164,9 +164,9 @@ static u8 chk_sta_is_alive(struct sta_info *psta) void expire_timeout_chk(struct adapter *padapter) { - struct list_head *phead, *plist; + struct list_head *phead; u8 updated = 0; - struct sta_info *psta = NULL; + struct sta_info *psta, *temp; struct sta_priv *pstapriv = &padapter->stapriv; u8 chk_alive_num = 0; char chk_alive_list[NUM_STA]; @@ -175,22 +175,14 @@ void expire_timeout_chk(struct adapter *padapter) spin_lock_bh(&pstapriv->auth_list_lock); phead = &pstapriv->auth_list; - plist = phead->next; - /* check auth_queue */ - while (phead != plist) { - psta = container_of(plist, struct sta_info, auth_list); - plist = plist->next; - + list_for_each_entry_safe(psta, temp, phead, auth_list) { if (psta->expire_to > 0) { psta->expire_to--; if (psta->expire_to == 0) { list_del_init(&psta->auth_list); pstapriv->auth_list_cnt--; - DBG_88E("auth expire %6ph\n", - psta->hwaddr); - spin_unlock_bh(&pstapriv->auth_list_lock); spin_lock_bh(&pstapriv->sta_hash_lock); @@ -208,13 +200,8 @@ void expire_timeout_chk(struct adapter *padapter) spin_lock_bh(&pstapriv->asoc_list_lock); phead = &pstapriv->asoc_list; - plist = phead->next; - /* check asoc_queue */ - while (phead != plist) { - psta = container_of(plist, struct sta_info, asoc_list); - plist = plist->next; - + list_for_each_entry_safe(psta, temp, phead, asoc_list) { if (chk_sta_is_alive(psta) || !psta->expire_to) { psta->expire_to = pstapriv->expire_to; psta->keep_alive_trycnt = 0; @@ -264,20 +251,13 @@ void expire_timeout_chk(struct adapter *padapter) list_del_init(&psta->asoc_list); pstapriv->asoc_list_cnt--; - DBG_88E("asoc expire %pM, state = 0x%x\n", - (psta->hwaddr), psta->state); updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING); } else { /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */ if (psta->sleepq_len > (NR_XMITFRAME / pstapriv->asoc_list_cnt) && - padapter->xmitpriv.free_xmitframe_cnt < (NR_XMITFRAME / pstapriv->asoc_list_cnt / 2)) { - DBG_88E("%s sta:%pM, sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", __func__, - (psta->hwaddr), psta->sleepq_len, - padapter->xmitpriv.free_xmitframe_cnt, - pstapriv->asoc_list_cnt); + padapter->xmitpriv.free_xmitframe_cnt < (NR_XMITFRAME / pstapriv->asoc_list_cnt / 2)) wakeup_sta_to_xmit(padapter, psta); - } } } @@ -309,21 +289,16 @@ void expire_timeout_chk(struct adapter *padapter) psta->keep_alive_trycnt++; if (ret == _SUCCESS) { - DBG_88E("asoc check, sta(%pM) is alive\n", - (psta->hwaddr)); psta->expire_to = pstapriv->expire_to; psta->keep_alive_trycnt = 0; continue; } else if (psta->keep_alive_trycnt <= 3) { - DBG_88E("ack check for asoc expire, keep_alive_trycnt =%d\n", psta->keep_alive_trycnt); psta->expire_to = 1; continue; } psta->keep_alive_trycnt = 0; - DBG_88E("asoc expire %pM, state = 0x%x\n", - psta->hwaddr, psta->state); spin_lock_bh(&pstapriv->asoc_list_lock); list_del_init(&psta->asoc_list); pstapriv->asoc_list_cnt--; @@ -394,9 +369,6 @@ void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level) tx_ra_bitmap |= ((raid << 28) & 0xf0000000); - DBG_88E("%s => mac_id:%d , raid:%d , bitmap = 0x%x, arg = 0x%x\n", - __func__, psta->mac_id, raid, tx_ra_bitmap, arg); - /* bitmap[0:27] = tx_rate_bitmap */ /* bitmap[28:31]= Rate Adaptive id */ /* arg[0:4] = macid */ @@ -410,8 +382,6 @@ void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level) psta->raid = raid; psta->init_rate = init_rate; - } else { - DBG_88E("station aid %d exceed the max number\n", psta->aid); } } @@ -467,8 +437,6 @@ static void update_bmc_sta(struct adapter *padapter) arg = psta->mac_id & 0x1f; arg |= BIT(7); tx_ra_bitmap |= ((raid << 28) & 0xf0000000); - DBG_88E("%s, mask = 0x%x, arg = 0x%x\n", __func__, - tx_ra_bitmap, arg); /* bitmap[0:27] = tx_rate_bitmap */ /* bitmap[28:31]= Rate Adaptive id */ @@ -486,8 +454,6 @@ static void update_bmc_sta(struct adapter *padapter) psta->state = _FW_LINKED; spin_unlock_bh(&psta->lock); - } else { - DBG_88E("add_RATid_bmc_sta error!\n"); } } @@ -582,8 +548,6 @@ static void update_hw_ht_param(struct adapter *padapter) /* Config SM Power Save setting */ pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & 0x0C) >> 2; - if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC) - DBG_88E("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__); } static void start_bss_network(struct adapter *padapter, u8 *pbuf) @@ -695,9 +659,6 @@ static void start_bss_network(struct adapter *padapter, u8 *pbuf) */ set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode); - DBG_88E("CH =%d, BW =%d, offset =%d\n", cur_channel, cur_bwmode, - cur_ch_offset); - /* */ pmlmeext->cur_channel = cur_channel; pmlmeext->cur_bwmode = cur_bwmode; @@ -717,8 +678,7 @@ static void start_bss_network(struct adapter *padapter, u8 *pbuf) update_beacon(padapter, WLAN_EID_TIM, NULL, false); /* issue beacon frame */ - if (send_beacon(padapter) == _FAIL) - DBG_88E("send_beacon, fail!\n"); + send_beacon(padapter); } /* update bc/mc sta_info */ @@ -756,8 +716,6 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) /* ht_capab, ht_oper */ /* WPS IE */ - DBG_88E("%s, len =%d\n", __func__, len); - if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) return _FAIL; @@ -1009,8 +967,6 @@ void rtw_set_macaddr_acl(struct adapter *padapter, int mode) struct sta_priv *pstapriv = &padapter->stapriv; struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - DBG_88E("%s, mode =%d\n", __func__, mode); - pacl_list->mode = mode; } @@ -1024,24 +980,18 @@ int rtw_acl_add_sta(struct adapter *padapter, u8 *addr) struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; struct __queue *pacl_node_q = &pacl_list->acl_node_q; - DBG_88E("%s(acl_num =%d) =%pM\n", __func__, pacl_list->num, (addr)); - if ((NUM_ACL - 1) < pacl_list->num) return -1; spin_lock_bh(&pacl_node_q->lock); phead = get_list_head(pacl_node_q); - plist = phead->next; - - while (phead != plist) { - paclnode = container_of(plist, struct rtw_wlan_acl_node, list); - plist = plist->next; + list_for_each(plist, phead) { + paclnode = list_entry(plist, struct rtw_wlan_acl_node, list); if (!memcmp(paclnode->addr, addr, ETH_ALEN)) { if (paclnode->valid) { added = true; - DBG_88E("%s, sta has been added\n", __func__); break; } } @@ -1072,8 +1022,6 @@ int rtw_acl_add_sta(struct adapter *padapter, u8 *addr) } } - DBG_88E("%s, acl_num =%d\n", __func__, pacl_list->num); - spin_unlock_bh(&pacl_node_q->lock); return ret; @@ -1081,23 +1029,16 @@ int rtw_acl_add_sta(struct adapter *padapter, u8 *addr) int rtw_acl_remove_sta(struct adapter *padapter, u8 *addr) { - struct list_head *plist, *phead; - struct rtw_wlan_acl_node *paclnode; + struct list_head *phead; + struct rtw_wlan_acl_node *paclnode, *temp; struct sta_priv *pstapriv = &padapter->stapriv; struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; struct __queue *pacl_node_q = &pacl_list->acl_node_q; - DBG_88E("%s(acl_num =%d) =%pM\n", __func__, pacl_list->num, (addr)); - spin_lock_bh(&pacl_node_q->lock); phead = get_list_head(pacl_node_q); - plist = phead->next; - - while (phead != plist) { - paclnode = container_of(plist, struct rtw_wlan_acl_node, list); - plist = plist->next; - + list_for_each_entry_safe(paclnode, temp, phead, list) { if (!memcmp(paclnode->addr, addr, ETH_ALEN)) { if (paclnode->valid) { paclnode->valid = false; @@ -1111,7 +1052,6 @@ int rtw_acl_remove_sta(struct adapter *padapter, u8 *addr) spin_unlock_bh(&pacl_node_q->lock); - DBG_88E("%s, acl_num =%d\n", __func__, pacl_list->num); return 0; } @@ -1124,8 +1064,6 @@ static void update_bcn_erpinfo_ie(struct adapter *padapter) unsigned char *p, *ie = pnetwork->ies; u32 len = 0; - DBG_88E("%s, ERP_enable =%d\n", __func__, pmlmeinfo->ERP_enable); - if (!pmlmeinfo->ERP_enable) return; @@ -1205,8 +1143,6 @@ static void update_bcn_vendor_spec_ie(struct adapter *padapter, u8 *oui) if (!memcmp(WPS_OUI, oui, 4)) update_bcn_wps_ie(padapter); - else - DBG_88E("unknown OUI type!\n"); } void update_beacon(struct adapter *padapter, u8 ie_id, u8 *oui, u8 tx) @@ -1269,9 +1205,6 @@ static int rtw_ht_operation_update(struct adapter *padapter) if (pmlmepriv->htpriv.ht_option) return 0; - DBG_88E("%s current operation mode = 0x%X\n", - __func__, pmlmepriv->ht_op_mode); - if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) && pmlmepriv->num_sta_ht_no_gf) { pmlmepriv->ht_op_mode |= @@ -1321,9 +1254,6 @@ static int rtw_ht_operation_update(struct adapter *padapter) op_mode_changes++; } - DBG_88E("%s new operation mode = 0x%X changes =%d\n", - __func__, pmlmepriv->ht_op_mode, op_mode_changes); - return op_mode_changes; } @@ -1338,13 +1268,9 @@ void associated_clients_update(struct adapter *padapter, u8 updated) spin_lock_bh(&pstapriv->asoc_list_lock); phead = &pstapriv->asoc_list; - plist = phead->next; - /* check asoc_queue */ - while (phead != plist) { - psta = container_of(plist, struct sta_info, asoc_list); - - plist = plist->next; + list_for_each(plist, phead) { + psta = list_entry(plist, struct sta_info, asoc_list); VCS_update(padapter, psta); } @@ -1438,9 +1364,6 @@ void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta) if (psta->flags & WLAN_STA_HT) { u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info); - DBG_88E("HT: STA %pM HT Capabilities Info: 0x%04x\n", - (psta->hwaddr), ht_capab); - if (psta->no_ht_set) { psta->no_ht_set = 0; pmlmepriv->num_sta_no_ht--; @@ -1451,9 +1374,6 @@ void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta) psta->no_ht_gf_set = 1; pmlmepriv->num_sta_ht_no_gf++; } - DBG_88E("%s STA %pM - no greenfield, num of non-gf stations %d\n", - __func__, (psta->hwaddr), - pmlmepriv->num_sta_ht_no_gf); } if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH_20_40) == 0) { @@ -1461,20 +1381,12 @@ void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta) psta->ht_20mhz_set = 1; pmlmepriv->num_sta_ht_20mhz++; } - DBG_88E("%s STA %pM - 20 MHz HT, num of 20MHz HT STAs %d\n", - __func__, (psta->hwaddr), - pmlmepriv->num_sta_ht_20mhz); } } else { if (!psta->no_ht_set) { psta->no_ht_set = 1; pmlmepriv->num_sta_no_ht++; } - if (pmlmepriv->htpriv.ht_option) { - DBG_88E("%s STA %pM - no HT, num of non-HT stations %d\n", - __func__, (psta->hwaddr), - pmlmepriv->num_sta_no_ht); - } } if (rtw_ht_operation_update(padapter) > 0) { @@ -1484,8 +1396,6 @@ void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta) /* update associated stations cap. */ associated_clients_update(padapter, beacon_updated); - - DBG_88E("%s, updated =%d\n", __func__, beacon_updated); } u8 bss_cap_update_on_sta_leave(struct adapter *padapter, struct sta_info *psta) @@ -1548,8 +1458,6 @@ u8 bss_cap_update_on_sta_leave(struct adapter *padapter, struct sta_info *psta) /* update associated stations cap. */ - DBG_88E("%s, updated =%d\n", __func__, beacon_updated); - return beacon_updated; } @@ -1595,28 +1503,20 @@ u8 ap_free_sta(struct adapter *padapter, struct sta_info *psta, int rtw_sta_flush(struct adapter *padapter) { - struct list_head *phead, *plist; - struct sta_info *psta = NULL; + struct list_head *phead; + struct sta_info *psta, *temp; struct sta_priv *pstapriv = &padapter->stapriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - DBG_88E(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev)); - if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE) return 0; spin_lock_bh(&pstapriv->asoc_list_lock); phead = &pstapriv->asoc_list; - plist = phead->next; - /* free sta asoc_queue */ - while (phead != plist) { - psta = container_of(plist, struct sta_info, asoc_list); - - plist = plist->next; - + list_for_each_entry_safe(psta, temp, phead, asoc_list) { list_del_init(&psta->asoc_list); pstapriv->asoc_list_cnt--; @@ -1716,8 +1616,7 @@ void start_ap_mode(struct adapter *padapter) void stop_ap_mode(struct adapter *padapter) { - struct list_head *phead, *plist; - struct rtw_wlan_acl_node *paclnode; + struct rtw_wlan_acl_node *paclnode, *n; struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; @@ -1737,12 +1636,7 @@ void stop_ap_mode(struct adapter *padapter) /* for ACL */ spin_lock_bh(&pacl_node_q->lock); - phead = get_list_head(pacl_node_q); - plist = phead->next; - while (phead != plist) { - paclnode = container_of(plist, struct rtw_wlan_acl_node, list); - plist = plist->next; - + list_for_each_entry_safe(paclnode, n, &pacl_node_q->queue, list) { if (paclnode->valid) { paclnode->valid = false; @@ -1753,8 +1647,6 @@ void stop_ap_mode(struct adapter *padapter) } spin_unlock_bh(&pacl_node_q->lock); - DBG_88E("%s, free acl_node_queue, num =%d\n", __func__, pacl_list->num); - rtw_sta_flush(padapter); /* free_assoc_sta_resources */ diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c index 6728391d39e3..eb89a52aa4e3 100644 --- a/drivers/staging/rtl8188eu/core/rtw_cmd.c +++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c @@ -37,7 +37,7 @@ static struct _cmd_callback rtw_cmd_callback[] = { {_SiteSurvey_CMD_, &rtw_survey_cmd_callback}, {_SetAuth_CMD_, NULL}, {_SetKey_CMD_, NULL}, - {_SetStaKey_CMD_, &rtw_setstaKey_cmdrsp_callback}, + {_SetStaKey_CMD_, NULL}, {_SetAssocSta_CMD_, &rtw_setassocsta_cmdrsp_callback}, {_AddBAReq_CMD_, NULL}, {_SetChannel_CMD_, NULL}, @@ -52,13 +52,11 @@ static struct _cmd_callback rtw_cmd_callback[] = { * No irqsave is necessary. */ -int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv) +void rtw_init_cmd_priv(struct cmd_priv *pcmdpriv) { init_completion(&pcmdpriv->cmd_queue_comp); - init_completion(&pcmdpriv->terminate_cmdthread_comp); _rtw_init_queue(&pcmdpriv->cmd_queue); - return _SUCCESS; } /* @@ -74,17 +72,12 @@ static int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj) { unsigned long irqL; - if (!obj) - goto exit; - spin_lock_irqsave(&queue->lock, irqL); list_add_tail(&obj->list, &queue->queue); spin_unlock_irqrestore(&queue->lock, irqL); -exit: - return _SUCCESS; } @@ -104,11 +97,12 @@ struct cmd_obj *rtw_dequeue_cmd(struct __queue *queue) static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) { + struct adapter *padapter = container_of(pcmdpriv, struct adapter, cmdpriv); u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */ /* To decide allow or not */ - if ((pcmdpriv->padapter->pwrctrlpriv.bHWPwrPindetect) && - (!pcmdpriv->padapter->registrypriv.usbss_enable)) { + if ((padapter->pwrctrlpriv.bHWPwrPindetect) && + (!padapter->registrypriv.usbss_enable)) { if (cmd_obj->cmdcode == _Set_Drv_Extra_CMD_) { struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)cmd_obj->parmbuf; @@ -120,8 +114,8 @@ static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) if (cmd_obj->cmdcode == _SetChannelPlan_CMD_) bAllow = true; - if ((!pcmdpriv->padapter->hw_init_completed && !bAllow) || - !pcmdpriv->cmdthd_running) /* com_thread not running */ + if ((!padapter->hw_init_completed && !bAllow) || + !padapter->cmdThread) /* com_thread not running */ return _FAIL; return _SUCCESS; } @@ -129,7 +123,7 @@ static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) { int res = _FAIL; - struct adapter *padapter = pcmdpriv->padapter; + struct adapter *padapter = container_of(pcmdpriv, struct adapter, cmdpriv); if (!cmd_obj) goto exit; @@ -181,20 +175,9 @@ int rtw_cmd_thread(void *context) allow_signal(SIGTERM); - pcmdpriv->cmdthd_running = true; - complete(&pcmdpriv->terminate_cmdthread_comp); - - RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, - ("start r871x %s !!!!\n", __func__)); - - while (1) { - if (padapter->bDriverStopped || - padapter->bSurpriseRemoved) { - DBG_88E("%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n", - __func__, padapter->bDriverStopped, - padapter->bSurpriseRemoved, __LINE__); + do { + if (padapter->bDriverStopped || padapter->bSurpriseRemoved) break; - } pcmd = rtw_dequeue_cmd(&pcmdpriv->cmd_queue); if (!pcmd) { @@ -223,33 +206,23 @@ int rtw_cmd_thread(void *context) /* call callback function for post-processed */ if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) { pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback; - if (!pcmd_callback) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, - ("mlme_cmd_hdl(): pcmd_callback = 0x%p, cmdcode = 0x%x\n", - pcmd_callback, pcmd->cmdcode)); - } else { + if (pcmd_callback) { /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */ pcmd_callback(pcmd->padapter, pcmd); } - } else { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - ("%s: cmdcode = 0x%x callback not defined!\n", - __func__, pcmd->cmdcode)); } rtw_free_cmd_obj(pcmd); if (signal_pending(current)) flush_signals(current); - } - pcmdpriv->cmdthd_running = false; + } while (!kthread_should_stop()); /* free all cmd_obj resources */ while ((pcmd = rtw_dequeue_cmd(&pcmdpriv->cmd_queue))) rtw_free_cmd_obj(pcmd); - complete(&pcmdpriv->terminate_cmdthread_comp); - - complete_and_exit(NULL, 0); + padapter->cmdThread = NULL; + return 0; } /* @@ -282,8 +255,6 @@ u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, rtw_free_network_queue(padapter, false); - RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("%s: flush network queue\n", __func__)); - init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, _SiteSurvey_CMD_); psurveyPara->scan_mode = pmlmepriv->scan_mode; @@ -342,19 +313,11 @@ u8 rtw_createbss_cmd(struct adapter *padapter) { struct cmd_obj *pcmd; struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network; u8 res = _SUCCESS; led_control_8188eu(padapter, LED_CTL_START_TO_LINK); - if (pmlmepriv->assoc_ssid.ssid_length == 0) - RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, - (" createbss for Any SSid:%s\n", pmlmepriv->assoc_ssid.ssid)); - else - RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, - (" createbss for SSid:%s\n", pmlmepriv->assoc_ssid.ssid)); - pcmd = kzalloc(sizeof(*pcmd), GFP_ATOMIC); if (!pcmd) { res = _FAIL; @@ -392,12 +355,6 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) led_control_8188eu(padapter, LED_CTL_START_TO_LINK); - if (pmlmepriv->assoc_ssid.ssid_length == 0) - RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+Join cmd: Any SSid\n")); - else - RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, - ("+Join cmd: SSid =[%s]\n", pmlmepriv->assoc_ssid.ssid)); - pcmd = kzalloc(sizeof(*pcmd), GFP_ATOMIC); if (!pcmd) { res = _FAIL; @@ -428,9 +385,6 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) res = _FAIL; - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - ("%s :psecnetwork == NULL!!!\n", __func__)); - goto exit; } @@ -502,8 +456,6 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) else padapter->pwrctrlpriv.smart_ps = padapter->registrypriv.smart_ps; - DBG_88E("%s: smart_ps =%d\n", __func__, padapter->pwrctrlpriv.smart_ps); - pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */ INIT_LIST_HEAD(&pcmd->list); @@ -526,8 +478,6 @@ u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueu struct cmd_priv *cmdpriv = &padapter->cmdpriv; u8 res = _SUCCESS; - RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+%s\n", __func__)); - /* prepare cmd parameter */ param = kzalloc(sizeof(*param), GFP_ATOMIC); if (!param) { @@ -745,8 +695,6 @@ u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue) u8 res = _SUCCESS; - RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+%s\n", __func__)); - /* check input parameter */ if (!rtw_is_channel_plan_valid(chplan)) { res = _FAIL; @@ -912,39 +860,28 @@ static void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type) u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue) { + struct cmd_priv *pcmdpriv = &padapter->cmdpriv; + struct drvextra_cmd_parm *pdrvextra_cmd_parm; struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - u8 res = _SUCCESS; - - if (enqueue) { - ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID; - pdrvextra_cmd_parm->type_size = lps_ctrl_type; - pdrvextra_cmd_parm->pbuf = NULL; - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_); - - res = rtw_enqueue_cmd(pcmdpriv, ph2c); - } else { + if (!enqueue) { lps_ctrl_wk_hdl(padapter, lps_ctrl_type); + return _SUCCESS; } -exit: + ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC); + pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC); + if (!ph2c || !pdrvextra_cmd_parm) { + kfree(ph2c); + kfree(pdrvextra_cmd_parm); + return _FAIL; + } - return res; + pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID; + pdrvextra_cmd_parm->type_size = lps_ctrl_type; + + init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_); + return rtw_enqueue_cmd(pcmdpriv, ph2c); } static void rpt_timer_setting_wk_hdl(struct adapter *padapter, u16 min_time) @@ -1172,8 +1109,6 @@ void rtw_survey_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) } else if (pcmd->res != H2C_SUCCESS) { mod_timer(&pmlmepriv->scan_to_timer, jiffies + msecs_to_jiffies(1)); - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - ("\n ********Error: MgntActrtw_set_802_11_bssid_LIST_SCAN Fail ************\n\n.")); } } @@ -1185,9 +1120,6 @@ void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) spin_lock_bh(&pmlmepriv->lock); set_fwstate(pmlmepriv, _FW_LINKED); spin_unlock_bh(&pmlmepriv->lock); - - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - ("\n ***Error: disconnect_cmd_callback Fail ***\n.")); } } @@ -1201,8 +1133,6 @@ void rtw_joinbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) mod_timer(&pmlmepriv->assoc_timer, jiffies + msecs_to_jiffies(1)); } else if (pcmd->res != H2C_SUCCESS) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - ("********Error:rtw_select_and_join_from_scanned_queue Wait Sema Fail ************\n")); mod_timer(&pmlmepriv->assoc_timer, jiffies + msecs_to_jiffies(1)); } @@ -1217,8 +1147,6 @@ void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) struct wlan_network *tgt_network = &pmlmepriv->cur_network; if (pcmd->res != H2C_SUCCESS) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - ("\n **** Error: %s Fail ****\n\n.", __func__)); mod_timer(&pmlmepriv->assoc_timer, jiffies + msecs_to_jiffies(1)); } @@ -1232,8 +1160,6 @@ void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) if (!psta) { psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress); if (!psta) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - ("\nCan't alloc sta_info when createbss_cmd_callback\n")); goto createbss_cmd_fail; } } @@ -1245,8 +1171,6 @@ void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) if (!pwlan) { pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue); if (!pwlan) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - ("\n Error: can't get pwlan in rtw_joinbss_event_callback\n")); spin_unlock_bh(&pmlmepriv->scanned_queue.lock); goto createbss_cmd_fail; } @@ -1274,18 +1198,6 @@ createbss_cmd_fail: spin_unlock_bh(&pmlmepriv->lock); } -void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp); - struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr); - - if (!psta) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - ("\nERROR: %s => can't get sta_info\n\n", __func__)); - } -} - void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd) { struct sta_priv *pstapriv = &padapter->stapriv; @@ -1294,11 +1206,8 @@ void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter, struct cmd_obj * struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *)(pcmd->rsp); struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr); - if (!psta) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - ("\nERROR: %s => can't get sta_info\n\n", __func__)); + if (!psta) return; - } psta->aid = passocsta_rsp->cam_id; psta->mac_id = passocsta_rsp->cam_id; diff --git a/drivers/staging/rtl8188eu/core/rtw_debug.c b/drivers/staging/rtl8188eu/core/rtw_debug.c deleted file mode 100644 index 1060837fe463..000000000000 --- a/drivers/staging/rtl8188eu/core/rtw_debug.c +++ /dev/null @@ -1,187 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#define _RTW_DEBUG_C_ - -#include <rtw_debug.h> -#include <usb_ops_linux.h> - -int proc_get_drv_version(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - int len = 0; - - len += scnprintf(page + len, count - len, "%s\n", DRIVERVERSION); - - *eof = 1; - return len; -} - -int proc_get_write_reg(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - *eof = 1; - return 0; -} - -int proc_set_write_reg(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = netdev_priv(dev); - char tmp[32]; - u32 addr, val, len; - - if (count < 3) { - DBG_88E("argument size is less than 3\n"); - return -EFAULT; - } - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - int num = sscanf(tmp, "%x %x %x", &addr, &val, &len); - - if (num != 3) { - DBG_88E("invalid write_reg parameter!\n"); - return count; - } - switch (len) { - case 1: - usb_write8(padapter, addr, (u8)val); - break; - case 2: - usb_write16(padapter, addr, (u16)val); - break; - case 4: - usb_write32(padapter, addr, val); - break; - default: - DBG_88E("error write length =%d", len); - break; - } - } - return count; -} - -static u32 proc_get_read_addr = 0xeeeeeeee; -static u32 proc_get_read_len = 0x4; - -int proc_get_read_reg(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = netdev_priv(dev); - - int len = 0; - - if (proc_get_read_addr == 0xeeeeeeee) { - *eof = 1; - return len; - } - - switch (proc_get_read_len) { - case 1: - len += scnprintf(page + len, count - len, "usb_read8(0x%x)=0x%x\n", - proc_get_read_addr, usb_read8(padapter, proc_get_read_addr)); - break; - case 2: - len += scnprintf(page + len, count - len, "usb_read16(0x%x)=0x%x\n", - proc_get_read_addr, usb_read16(padapter, proc_get_read_addr)); - break; - case 4: - len += scnprintf(page + len, count - len, "usb_read32(0x%x)=0x%x\n", - proc_get_read_addr, usb_read32(padapter, proc_get_read_addr)); - break; - default: - len += scnprintf(page + len, count - len, "error read length=%d\n", - proc_get_read_len); - break; - } - - *eof = 1; - return len; -} - -int proc_set_read_reg(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - char tmp[16]; - u32 addr, len; - - if (count < 2) { - DBG_88E("argument size is less than 2\n"); - return -EFAULT; - } - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - int num = sscanf(tmp, "%x %x", &addr, &len); - - if (num != 2) { - DBG_88E("invalid read_reg parameter!\n"); - return count; - } - - proc_get_read_addr = addr; - - proc_get_read_len = len; - } - - return count; -} - -int proc_get_adapter_state(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = netdev_priv(dev); - int len = 0; - - len += scnprintf(page + len, count - len, "bSurpriseRemoved=%d, bDriverStopped=%d\n", - padapter->bSurpriseRemoved, - padapter->bDriverStopped); - - *eof = 1; - return len; -} - -int proc_get_best_channel(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = netdev_priv(dev); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - int len = 0; - u32 i, best_channel_24G = 1, index_24G = 0; - - for (i = 0; pmlmeext->channel_set[i].ChannelNum != 0; i++) { - if (pmlmeext->channel_set[i].ChannelNum == 1) - index_24G = i; - } - - for (i = 0; pmlmeext->channel_set[i].ChannelNum != 0; i++) { - /* 2.4G */ - if (pmlmeext->channel_set[i].ChannelNum == 6) { - if (pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_24G].rx_count) { - index_24G = i; - best_channel_24G = pmlmeext->channel_set[i].ChannelNum; - } - } - - /* debug */ - len += scnprintf(page + len, count - len, "The rx cnt of channel %3d = %d\n", - pmlmeext->channel_set[i].ChannelNum, - pmlmeext->channel_set[i].rx_count); - } - - len += scnprintf(page + len, count - len, "best_channel_24G = %d\n", best_channel_24G); - - *eof = 1; - return len; -} diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index 9bb3ec0cd62f..80673a73c119 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -91,10 +91,8 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) tmp = kcalloc(EFUSE_MAX_SECTION_88E, sizeof(void *) + EFUSE_MAX_WORD_UNIT * sizeof(u16), GFP_KERNEL); - if (!tmp) { - DBG_88E("%s: alloc eFuseWord fail!\n", __func__); + if (!tmp) goto eFuseWord_failed; - } for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) tmp[i] = ((char *)(tmp + EFUSE_MAX_SECTION_88E)) + i * EFUSE_MAX_WORD_UNIT * sizeof(u16); eFuseWord = (u16 **)tmp; @@ -113,7 +111,6 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) efuse_utilized++; eFuse_Addr++; } else { - DBG_88E("EFUSE is empty efuse_Addr-%d efuse_data =%x\n", eFuse_Addr, rtemp8); goto exit; } @@ -220,8 +217,6 @@ static void efuse_read_phymap_from_txpktbuf( if (bcnhead < 0) /* if not valid */ bcnhead = usb_read8(adapter, REG_TDECTRL + 1); - DBG_88E("%s bcnhead:%d\n", __func__, bcnhead); - usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT); dbg_addr = bcnhead * 128 / 8; /* 8-bytes addressing */ @@ -232,31 +227,20 @@ static void efuse_read_phymap_from_txpktbuf( usb_write8(adapter, REG_TXPKTBUF_DBG, 0); start = jiffies; while (!(reg_0x143 = usb_read8(adapter, REG_TXPKTBUF_DBG)) && - jiffies_to_msecs(jiffies - start) < 1000) { - DBG_88E("%s polling reg_0x143:0x%02x, reg_0x106:0x%02x\n", __func__, reg_0x143, usb_read8(adapter, 0x106)); + jiffies_to_msecs(jiffies - start) < 1000) usleep_range(1000, 2000); - } lo32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_L); hi32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_H); if (i == 0) { - u8 lenc[2]; - u16 lenbak, aaabak; - u16 aaa; + usb_read8(adapter, REG_PKTBUF_DBG_DATA_L); + usb_read8(adapter, REG_PKTBUF_DBG_DATA_L + 1); - lenc[0] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L); - lenc[1] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L + 1); - - aaabak = le16_to_cpup((__le16 *)lenc); - lenbak = le16_to_cpu(*((__le16 *)lenc)); - aaa = le16_to_cpup((__le16 *)&lo32); len = le16_to_cpu(*((__le16 *)&lo32)); limit = min_t(u16, len - 2, limit); - DBG_88E("%s len:%u, lenbak:%u, aaa:%u, aaabak:%u\n", __func__, len, lenbak, aaa, aaabak); - memcpy(pos, ((u8 *)&lo32) + 2, (limit >= count + 2) ? 2 : limit - count); count += (limit >= count + 2) ? 2 : limit - count; pos = content + count; @@ -278,7 +262,6 @@ static void efuse_read_phymap_from_txpktbuf( i++; } usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, DISABLE_TRXPKT_BUF_ACCESS); - DBG_88E("%s read count:%u\n", __func__, count); *size = count; } @@ -298,7 +281,7 @@ static s32 iol_read_efuse(struct adapter *padapter, u8 txpktbuf_bndy, u16 offset return status; } -void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf) +static void efuse_ReadEFuse(struct adapter *Adapter, u16 _offset, u16 _size_byte, u8 *pbuf) { if (rtw_iol_applied(Adapter)) { rtw_hal_power_on(Adapter); @@ -432,7 +415,6 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) hoffset = ((tmp_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); hworden = efuse_data & 0x0F; } else { - DBG_88E("Error, All words disabled\n"); efuse_addr++; continue; } @@ -479,7 +461,7 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) return true; } -static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, struct pgpkt *pFixPkt, u16 *pAddr) +static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, struct pgpkt *pFixPkt, u16 *pAddr) { u8 originaldata[8], badworden = 0; u16 efuse_addr = *pAddr; @@ -508,7 +490,7 @@ static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, st return true; } -static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt) +static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter *pAdapter, u16 *pAddr, struct pgpkt *pTargetPkt) { bool ret = false; u16 efuse_addr = *pAddr; @@ -559,7 +541,7 @@ static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter *pAdapter, u8 efuse fixPkt.offset = ((pg_header_temp & 0xE0) >> 5) | ((tmp_header & 0xF0) >> 1); fixPkt.word_en = tmp_header & 0x0F; fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en); - if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr)) + if (!hal_EfuseFixHeaderProcess(pAdapter, &fixPkt, &efuse_addr)) return false; } else { ret = true; @@ -575,7 +557,7 @@ static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter *pAdapter, u8 efuse return ret; } -static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt) +static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u16 *pAddr, struct pgpkt *pTargetPkt) { bool ret = false; u8 pg_header = 0, tmp_header = 0; @@ -602,7 +584,7 @@ static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuse fixPkt.offset = (tmp_header >> 4) & 0x0F; fixPkt.word_en = tmp_header & 0x0F; fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en); - if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr)) + if (!hal_EfuseFixHeaderProcess(pAdapter, &fixPkt, &efuse_addr)) return false; } @@ -610,7 +592,7 @@ static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuse return ret; } -static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt) +static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u16 *pAddr, struct pgpkt *pTargetPkt) { u16 efuse_addr = *pAddr; u8 badworden; @@ -632,16 +614,15 @@ static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u static bool hal_EfusePgPacketWriteHeader( struct adapter *pAdapter, - u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt) { bool ret = false; if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE) - ret = hal_EfusePgPacketWrite2ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt); + ret = hal_EfusePgPacketWrite2ByteHeader(pAdapter, pAddr, pTargetPkt); else - ret = hal_EfusePgPacketWrite1ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt); + ret = hal_EfusePgPacketWrite1ByteHeader(pAdapter, pAddr, pTargetPkt); return ret; } @@ -685,7 +666,7 @@ static bool hal_EfuseCheckIfDatafollowed(struct adapter *pAdapter, u8 word_cnts, return ret; } -static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt) +static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u16 *pAddr, struct pgpkt *pTargetPkt) { bool ret = false; u8 i, efuse_data = 0, cur_header = 0; @@ -772,20 +753,19 @@ bool Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *pD { struct pgpkt targetPkt; u16 startAddr = 0; - u8 efuseType = EFUSE_WIFI; if (Efuse_GetCurrentSize(pAdapter) >= EFUSE_MAP_LEN_88E) return false; hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt); - if (!hal_EfusePartialWriteCheck(pAdapter, efuseType, &startAddr, &targetPkt)) + if (!hal_EfusePartialWriteCheck(pAdapter, &startAddr, &targetPkt)) return false; - if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType, &startAddr, &targetPkt)) + if (!hal_EfusePgPacketWriteHeader(pAdapter, &startAddr, &targetPkt)) return false; - if (!hal_EfusePgPacketWriteData(pAdapter, efuseType, &startAddr, &targetPkt)) + if (!hal_EfusePgPacketWriteData(pAdapter, &startAddr, &targetPkt)) return false; return true; @@ -875,22 +855,22 @@ void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata) } /* Read All Efuse content */ -static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse) +static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 *Efuse) { efuse_power_switch(pAdapter, false, true); - efuse_ReadEFuse(pAdapter, efuseType, 0, EFUSE_MAP_LEN_88E, Efuse); + efuse_ReadEFuse(pAdapter, 0, EFUSE_MAP_LEN_88E, Efuse); efuse_power_switch(pAdapter, false, false); } /* Transfer current EFUSE content to shadow init and modify map. */ -void EFUSE_ShadowMapUpdate(struct adapter *pAdapter, u8 efuseType) +void EFUSE_ShadowMapUpdate(struct adapter *pAdapter) { struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); if (pEEPROM->bautoload_fail_flag) memset(pEEPROM->efuse_eeprom_data, 0xFF, EFUSE_MAP_LEN_88E); else - Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data); + Efuse_ReadAllMap(pAdapter, pEEPROM->efuse_eeprom_data); } diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index 7a706fe11750..e431914db008 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -370,7 +370,6 @@ int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwis pos += WPA_SELECTOR_LEN; left -= WPA_SELECTOR_LEN; } else if (left > 0) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie length mismatch, %u too much", __func__, left)); return _FAIL; } @@ -380,11 +379,8 @@ int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwis pos += 2; left -= 2; - if (count == 0 || left < count * WPA_SELECTOR_LEN) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie count botch (pairwise), count %u left %u", - __func__, count, left)); + if (count == 0 || left < count * WPA_SELECTOR_LEN) return _FAIL; - } for (i = 0; i < count; i++) { *pairwise_cipher |= rtw_get_wpa_cipher_suite(pos); @@ -393,17 +389,14 @@ int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwis left -= WPA_SELECTOR_LEN; } } else if (left == 1) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie too short (for key mgmt)", __func__)); return _FAIL; } if (is_8021x) { if (left >= 6) { pos += 2; - if (!memcmp(pos, SUITE_1X, 4)) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s : there has 802.1x auth\n", __func__)); + if (!memcmp(pos, SUITE_1X, 4)) *is_8021x = 1; - } } } @@ -437,7 +430,6 @@ int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, int *pairwi left -= RSN_SELECTOR_LEN; } else if (left > 0) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie length mismatch, %u too much", __func__, left)); return _FAIL; } @@ -447,11 +439,8 @@ int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, int *pairwi pos += 2; left -= 2; - if (count == 0 || left < count * RSN_SELECTOR_LEN) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie count botch (pairwise), count %u left %u", - __func__, count, left)); + if (count == 0 || left < count * RSN_SELECTOR_LEN) return _FAIL; - } for (i = 0; i < count; i++) { *pairwise_cipher |= rtw_get_wpa2_cipher_suite(pos); @@ -461,18 +450,14 @@ int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, int *pairwi } } else if (left == 1) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie too short (for key mgmt)", __func__)); - return _FAIL; } if (is_8021x) { if (left >= 6) { pos += 2; - if (!memcmp(pos, SUITE_1X, 4)) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s (): there has 802.1x auth\n", __func__)); + if (!memcmp(pos, SUITE_1X, 4)) *is_8021x = 1; - } } } return ret; @@ -480,7 +465,7 @@ int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, int *pairwi void rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, u8 *wpa_ie, u16 *wpa_len) { - u8 authmode, sec_idx, i; + u8 authmode, sec_idx; u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01}; uint cnt; @@ -494,40 +479,16 @@ void rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, u8 *wpa_ie authmode = in_ie[cnt]; if ((authmode == WLAN_EID_VENDOR_SPECIFIC) && (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("\n rtw_get_wpa_ie: sec_idx =%d in_ie[cnt+1]+2 =%d\n", - sec_idx, in_ie[cnt + 1] + 2)); - - if (wpa_ie) { + if (wpa_ie) memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - for (i = 0; i < (in_ie[cnt + 1] + 2); i += 8) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n", - wpa_ie[i], wpa_ie[i + 1], wpa_ie[i + 2], wpa_ie[i + 3], wpa_ie[i + 4], - wpa_ie[i + 5], wpa_ie[i + 6], wpa_ie[i + 7])); - } - } - *wpa_len = in_ie[cnt + 1] + 2; cnt += in_ie[cnt + 1] + 2; /* get next */ } else { if (authmode == WLAN_EID_RSN) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("\n get_rsn_ie: sec_idx =%d in_ie[cnt+1]+2 =%d\n", - sec_idx, in_ie[cnt + 1] + 2)); - - if (rsn_ie) { + if (rsn_ie) memcpy(rsn_ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - for (i = 0; i < (in_ie[cnt + 1] + 2); i += 8) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n", - rsn_ie[i], rsn_ie[i + 1], rsn_ie[i + 2], rsn_ie[i + 3], rsn_ie[i + 4], - rsn_ie[i + 5], rsn_ie[i + 6], rsn_ie[i + 7])); - } - } - *rsn_len = in_ie[cnt + 1] + 2; cnt += in_ie[cnt + 1] + 2; /* get next */ } else { @@ -686,13 +647,8 @@ static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen, * OUI of the vendor. The following byte is used a vendor specific * sub-type. */ - if (elen < 4) { - if (show_errors) { - DBG_88E("short vendor specific information element ignored (len=%lu)\n", - (unsigned long)elen); - } + if (elen < 4) return -1; - } oui = RTW_GET_BE24(pos); switch (oui) { @@ -711,11 +667,9 @@ static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen, elems->wpa_ie_len = elen; break; case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */ - if (elen < 5) { - DBG_88E("short WME information element ignored (len=%lu)\n", - (unsigned long)elen); + if (elen < 5) return -1; - } + switch (pos[4]) { case WME_OUI_SUBTYPE_INFORMATION_ELEMENT: case WME_OUI_SUBTYPE_PARAMETER_ELEMENT: @@ -727,8 +681,6 @@ static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen, elems->wme_tspec_len = elen; break; default: - DBG_88E("unknown WME information element ignored (subtype=%d len=%lu)\n", - pos[4], (unsigned long)elen); return -1; } break; @@ -738,8 +690,6 @@ static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen, elems->wps_ie_len = elen; break; default: - DBG_88E("Unknown Microsoft information element ignored (type=%d len=%lu)\n", - pos[3], (unsigned long)elen); return -1; } break; @@ -751,21 +701,17 @@ static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen, elems->vendor_ht_cap_len = elen; break; default: - DBG_88E("Unknown Broadcom information element ignored (type=%d len=%lu)\n", - pos[3], (unsigned long)elen); return -1; } break; default: - DBG_88E("unknown vendor specific information element ignored (vendor OUI %3phC len=%lu)\n", - pos, (unsigned long)elen); return -1; } return 0; } /** - * ieee802_11_parse_elems - Parse information elements in management frames + * rtw_ieee802_11_parse_elems - Parse information elements in management frames * @start: Pointer to the start of ies * @len: Length of IE buffer in octets * @elems: Data structure for parsed elements @@ -789,13 +735,8 @@ enum parse_res rtw_ieee802_11_parse_elems(u8 *start, uint len, elen = *pos++; left -= 2; - if (elen > left) { - if (show_errors) { - DBG_88E("IEEE 802.11 element parse failed (id=%d elen=%d left=%lu)\n", - id, elen, (unsigned long)left); - } + if (elen > left) return ParseFailed; - } switch (id) { case WLAN_EID_SSID: @@ -876,10 +817,6 @@ enum parse_res rtw_ieee802_11_parse_elems(u8 *start, uint len, break; default: unknown++; - if (!show_errors) - break; - DBG_88E("IEEE 802.11 element parse ignored unknown element (id=%d elen=%d)\n", - id, elen); break; } left -= elen; @@ -905,12 +842,8 @@ void rtw_macaddr_cfg(u8 *mac_addr) ether_addr_copy(mac, mac_addr); } - if (is_broadcast_ether_addr(mac) || is_zero_ether_addr(mac)) { + if (is_broadcast_ether_addr(mac) || is_zero_ether_addr(mac)) eth_random_addr(mac_addr); - DBG_88E("MAC Address from efuse error, assign random one !!!\n"); - } - - DBG_88E("%s MAC Address = %pM\n", __func__, mac_addr); } static int rtw_get_cipher_info(struct wlan_network *pnetwork) @@ -923,30 +856,20 @@ static int rtw_get_cipher_info(struct wlan_network *pnetwork) pbuf = rtw_get_wpa_ie(&pnetwork->network.ies[12], &wpa_ielen, pnetwork->network.ie_length - 12); if (pbuf && (wpa_ielen > 0)) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: wpa_ielen: %d", __func__, wpa_ielen)); if (rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is8021x) == _SUCCESS) { pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher; pnetwork->BcnInfo.group_cipher = group_cipher; pnetwork->BcnInfo.is_8021x = is8021x; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("%s: pnetwork->pairwise_cipher: %d, is_8021x is %d", - __func__, pnetwork->BcnInfo.pairwise_cipher, - pnetwork->BcnInfo.is_8021x)); ret = _SUCCESS; } } else { pbuf = rtw_get_wpa2_ie(&pnetwork->network.ies[12], &wpa_ielen, pnetwork->network.ie_length - 12); if (pbuf && (wpa_ielen > 0)) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("get RSN IE\n")); if (rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is8021x) == _SUCCESS) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("get RSN IE OK!!!\n")); pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher; pnetwork->BcnInfo.group_cipher = group_cipher; pnetwork->BcnInfo.is_8021x = is8021x; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: pnetwork->pairwise_cipher: %d, pnetwork->group_cipher is %d, is_8021x is %d", - __func__, pnetwork->BcnInfo.pairwise_cipher, - pnetwork->BcnInfo.group_cipher, pnetwork->BcnInfo.is_8021x)); ret = _SUCCESS; } } @@ -974,10 +897,6 @@ void rtw_get_bcn_info(struct wlan_network *pnetwork) pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS; } rtw_get_sec_ie(pnetwork->network.ies, pnetwork->network.ie_length, NULL, &rsn_len, NULL, &wpa_len); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: ssid =%s\n", __func__, pnetwork->network.ssid.ssid)); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: wpa_len =%d rsn_len =%d\n", __func__, wpa_len, rsn_len)); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: ssid =%s\n", __func__, pnetwork->network.ssid.ssid)); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: wpa_len =%d rsn_len =%d\n", __func__, wpa_len, rsn_len)); if (rsn_len > 0) { pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2; @@ -987,10 +906,6 @@ void rtw_get_bcn_info(struct wlan_network *pnetwork) if (bencrypt) pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP; } - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: pnetwork->encryp_protocol is %x\n", - __func__, pnetwork->BcnInfo.encryp_protocol)); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: pnetwork->encryp_protocol is %x\n", - __func__, pnetwork->BcnInfo.encryp_protocol)); rtw_get_cipher_info(pnetwork); /* get bwmode and ch_offset */ diff --git a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c index 17b999f45132..f679a7f8fe75 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c +++ b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c @@ -12,12 +12,12 @@ #include <hal_intf.h> static const struct { - int channel_plan; - char *name; + int channel_plan; + char *name; } channel_table[] = { { RT_CHANNEL_DOMAIN_FCC, "US" }, - { RT_CHANNEL_DOMAIN_ETSI, "EU" }, - { RT_CHANNEL_DOMAIN_MKK, "JP" }, - { RT_CHANNEL_DOMAIN_CHINA, "CN"} }; + { RT_CHANNEL_DOMAIN_ETSI, "EU" }, + { RT_CHANNEL_DOMAIN_MKK, "JP" }, + { RT_CHANNEL_DOMAIN_CHINA, "CN"} }; extern void indicate_wx_scan_complete_event(struct adapter *padapter); @@ -33,8 +33,6 @@ u8 rtw_do_join(struct adapter *padapter) phead = get_list_head(queue); plist = phead->next; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("\n %s: phead = %p; plist = %p\n\n\n", __func__, phead, plist)); - pmlmepriv->cur_network.join_res = -2; set_fwstate(pmlmepriv, _FW_UNDER_LINKING); @@ -52,13 +50,10 @@ u8 rtw_do_join(struct adapter *padapter) if (!pmlmepriv->LinkDetectInfo.bBusyTraffic || pmlmepriv->to_roaming > 0) { - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("%s: site survey if scanned_queue is empty\n.", __func__)); /* submit site_survey_cmd */ ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0); - if (ret != _SUCCESS) { + if (ret != _SUCCESS) pmlmepriv->to_join = false; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("%s: site survey return error\n.", __func__)); - } } else { pmlmepriv->to_join = false; ret = _FAIL; @@ -92,14 +87,10 @@ u8 rtw_do_join(struct adapter *padapter) rtw_generate_random_ibss(pibss); if (rtw_createbss_cmd(padapter) != _SUCCESS) { - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("***Error =>do_goin: rtw_createbss_cmd status FAIL***\n ")); ret = false; goto exit; } pmlmepriv->to_join = false; - - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - ("***Error => rtw_select_and_join_from_scanned_queue FAIL under STA_Mode***\n ")); } else { /* can't associate ; reset under-linking */ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); @@ -109,10 +100,8 @@ u8 rtw_do_join(struct adapter *padapter) if (!pmlmepriv->LinkDetectInfo.bBusyTraffic || pmlmepriv->to_roaming > 0) { ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0); - if (ret != _SUCCESS) { + if (ret != _SUCCESS) pmlmepriv->to_join = false; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("do_join(): site survey return error\n.")); - } } else { ret = _FAIL; pmlmepriv->to_join = false; @@ -131,8 +120,6 @@ u8 rtw_set_802_11_bssid(struct adapter *padapter, u8 *bssid) u32 cur_time = 0; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - DBG_88E_LEVEL(_drv_info_, "set bssid:%pM\n", bssid); - if ((bssid[0] == 0x00 && bssid[1] == 0x00 && bssid[2] == 0x00 && bssid[3] == 0x00 && bssid[4] == 0x00 && bssid[5] == 0x00) || (bssid[0] == 0xFF && bssid[1] == 0xFF && bssid[2] == 0xFF && @@ -143,23 +130,16 @@ u8 rtw_set_802_11_bssid(struct adapter *padapter, u8 *bssid) spin_lock_bh(&pmlmepriv->lock); - DBG_88E("Set BSSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv)); if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) goto handle_tkip_countermeasure; else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) goto release_mlme_lock; if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) { - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_bssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n")); - if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN)) { if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */ } else { - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("Set BSSID not the same bssid\n")); - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_bssid =%pM\n", (bssid))); - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("cur_bssid =%pM\n", (pmlmepriv->cur_network.network.MacAddress))); - rtw_disassoc_cmd(padapter, 0, true); if (check_fwstate(pmlmepriv, _FW_LINKED)) @@ -201,9 +181,6 @@ release_mlme_lock: spin_unlock_bh(&pmlmepriv->lock); exit: - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, - ("%s: status=%d\n", __func__, status)); - return status; } @@ -215,35 +192,22 @@ u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid) struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct wlan_network *pnetwork = &pmlmepriv->cur_network; - DBG_88E_LEVEL(_drv_info_, "set ssid [%s] fw_state=0x%08x\n", - ssid->ssid, get_fwstate(pmlmepriv)); - if (!padapter->hw_init_completed) { - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, - ("set_ssid: hw_init_completed == false =>exit!!!\n")); status = _FAIL; goto exit; } spin_lock_bh(&pmlmepriv->lock); - DBG_88E("Set SSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv)); if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) goto handle_tkip_countermeasure; else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) goto release_mlme_lock; if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) { - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - ("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n")); - if (pmlmepriv->assoc_ssid.ssid_length == ssid->ssid_length && !memcmp(&pmlmepriv->assoc_ssid.ssid, ssid->ssid, ssid->ssid_length)) { if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, - ("Set SSID is the same ssid, fw_state = 0x%08x\n", - get_fwstate(pmlmepriv))); - if (!rtw_is_same_ibss(padapter, pnetwork)) { /* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */ rtw_disassoc_cmd(padapter, 0, true); @@ -264,10 +228,6 @@ u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid) rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_JOINBSS, 1); } } else { - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("Set SSID not the same ssid\n")); - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_ssid =[%s] len = 0x%x\n", ssid->ssid, (unsigned int)ssid->ssid_length)); - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("assoc_ssid =[%s] len = 0x%x\n", pmlmepriv->assoc_ssid.ssid, (unsigned int)pmlmepriv->assoc_ssid.ssid_length)); - rtw_disassoc_cmd(padapter, 0, true); if (check_fwstate(pmlmepriv, _FW_LINKED)) @@ -308,8 +268,6 @@ release_mlme_lock: spin_unlock_bh(&pmlmepriv->lock); exit: - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, - ("-%s: status =%d\n", __func__, status)); return status; } @@ -320,16 +278,9 @@ u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter, struct wlan_network *cur_network = &pmlmepriv->cur_network; enum ndis_802_11_network_infra *pold_state = &cur_network->network.InfrastructureMode; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_, - ("+%s: old =%d new =%d fw_state = 0x%08x\n", __func__, - *pold_state, networktype, get_fwstate(pmlmepriv))); - if (*pold_state != networktype) { spin_lock_bh(&pmlmepriv->lock); - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, (" change mode!")); - /* DBG_88E("change mode, old_mode =%d, new_mode =%d, fw_state = 0x%x\n", *pold_state, networktype, get_fwstate(pmlmepriv)); */ - if (*pold_state == Ndis802_11APMode) { /* change to other mode from Ndis802_11APMode */ cur_network->join_res = -1; @@ -387,9 +338,6 @@ u8 rtw_set_802_11_disassociate(struct adapter *padapter) spin_lock_bh(&pmlmepriv->lock); if (check_fwstate(pmlmepriv, _FW_LINKED)) { - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - ("MgntActrtw_set_802_11_disassociate: rtw_indicate_disconnect\n")); - rtw_disassoc_cmd(padapter, 0, true); rtw_indicate_disconnect(padapter); rtw_free_assoc_resources(padapter); @@ -406,33 +354,21 @@ u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_s struct mlme_priv *pmlmepriv = &padapter->mlmepriv; u8 res = true; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("+%s(), fw_state =%x\n", __func__, get_fwstate(pmlmepriv))); - if (!padapter) { res = false; goto exit; } if (!padapter->hw_init_completed) { res = false; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n === %s:hw_init_completed == false ===\n", __func__)); goto exit; } if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) || pmlmepriv->LinkDetectInfo.bBusyTraffic) { /* Scan or linking is in progress, do nothing. */ - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("%s fail since fw_state = %x\n", __func__, get_fwstate(pmlmepriv))); res = true; - - if (check_fwstate(pmlmepriv, - _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n###_FW_UNDER_SURVEY|_FW_UNDER_LINKING\n\n")); - else - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n###pmlmepriv->sitesurveyctrl.traffic_busy == true\n\n")); - } else { if (rtw_is_scan_deny(padapter)) { - DBG_88E(FUNC_ADPT_FMT": scan deny\n", FUNC_ADPT_ARG(padapter)); indicate_wx_scan_complete_event(padapter); return _SUCCESS; } @@ -453,15 +389,8 @@ u8 rtw_set_802_11_authentication_mode(struct adapter *padapter, enum ndis_802_11 int res; u8 ret; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - ("set_802_11_auth.mode(): mode =%x\n", authmode)); - psecuritypriv->ndisauthtype = authmode; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - ("%s:psecuritypriv->ndisauthtype=%d", __func__, - psecuritypriv->ndisauthtype)); - if (psecuritypriv->ndisauthtype > 3) psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; @@ -484,7 +413,6 @@ u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep) keyid = wep->KeyIndex & 0x3fffffff; if (keyid >= 4) { - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("MgntActrtw_set_802_11_add_wep:keyid>4 =>fail\n")); ret = false; goto exit; } @@ -492,20 +420,14 @@ u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep) switch (wep->KeyLength) { case 5: psecuritypriv->dot11PrivacyAlgrthm = _WEP40_; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("MgntActrtw_set_802_11_add_wep:wep->KeyLength = 5\n")); break; case 13: psecuritypriv->dot11PrivacyAlgrthm = _WEP104_; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("MgntActrtw_set_802_11_add_wep:wep->KeyLength = 13\n")); break; default: psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("MgntActrtw_set_802_11_add_wep:wep->KeyLength!= 5 or 13\n")); break; } - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - ("%s:before memcpy, wep->KeyLength = 0x%x wep->KeyIndex = 0x%x keyid =%x\n", __func__, - wep->KeyLength, wep->KeyIndex, keyid)); memcpy(&psecuritypriv->dot11DefKey[keyid].skey[0], &wep->KeyMaterial, wep->KeyLength); @@ -514,22 +436,6 @@ u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep) psecuritypriv->dot11PrivacyKeyIndex = keyid; - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, - ("%s:security key material : %x %x %x %x %x %x %x %x %x %x %x %x %x\n", __func__, - psecuritypriv->dot11DefKey[keyid].skey[0], - psecuritypriv->dot11DefKey[keyid].skey[1], - psecuritypriv->dot11DefKey[keyid].skey[2], - psecuritypriv->dot11DefKey[keyid].skey[3], - psecuritypriv->dot11DefKey[keyid].skey[4], - psecuritypriv->dot11DefKey[keyid].skey[5], - psecuritypriv->dot11DefKey[keyid].skey[6], - psecuritypriv->dot11DefKey[keyid].skey[7], - psecuritypriv->dot11DefKey[keyid].skey[8], - psecuritypriv->dot11DefKey[keyid].skey[9], - psecuritypriv->dot11DefKey[keyid].skey[10], - psecuritypriv->dot11DefKey[keyid].skey[11], - psecuritypriv->dot11DefKey[keyid].skey[12])); - res = rtw_set_key(padapter, psecuritypriv, keyid, 1); if (res == _FAIL) @@ -595,7 +501,6 @@ int rtw_set_country(struct adapter *adapter, const char *country_code) int i; int channel_plan = RT_CHANNEL_DOMAIN_WORLD_WIDE_5G; - DBG_88E("%s country_code:%s\n", __func__, country_code); for (i = 0; i < ARRAY_SIZE(channel_table); i++) { if (strcmp(channel_table[i].name, country_code) == 0) { channel_plan = channel_table[i].channel_plan; @@ -603,8 +508,5 @@ int rtw_set_country(struct adapter *adapter, const char *country_code) } } - if (i == ARRAY_SIZE(channel_table)) - DBG_88E("%s unknown country_code:%s\n", __func__, country_code); - return rtw_set_chplan_cmd(adapter, channel_plan, 1); } diff --git a/drivers/staging/rtl8188eu/core/rtw_led.c b/drivers/staging/rtl8188eu/core/rtw_led.c index 32dccae186ca..be868f386204 100644 --- a/drivers/staging/rtl8188eu/core/rtw_led.c +++ b/drivers/staging/rtl8188eu/core/rtw_led.c @@ -43,7 +43,7 @@ void BlinkWorkItemCallback(struct work_struct *work) void ResetLedStatus(struct LED_871x *pLed) { pLed->CurrLedState = RTW_LED_OFF; /* Current LED state. */ - pLed->bLedOn = false; /* true if LED is ON, false if LED is OFF. */ + pLed->led_on = false; /* true if LED is ON, false if LED is OFF. */ pLed->bLedBlinkInProgress = false; /* true if it is blinking, false o.w.. */ pLed->bLedWPSBlinkInProgress = false; @@ -92,15 +92,10 @@ static void SwLedBlink1(struct LED_871x *pLed) struct mlme_priv *pmlmepriv = &padapter->mlmepriv; /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == RTW_LED_ON) { + if (pLed->BlinkingLedState == RTW_LED_ON) sw_led_on(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_, _drv_info_, - ("Blinktimes (%d): turn on\n", pLed->BlinkTimes)); - } else { + else sw_led_off(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_, _drv_info_, - ("Blinktimes (%d): turn off\n", pLed->BlinkTimes)); - } if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) { sw_led_off(padapter, pLed); @@ -110,7 +105,7 @@ static void SwLedBlink1(struct LED_871x *pLed) switch (pLed->CurrLedState) { case LED_BLINK_SLOWLY: - if (pLed->bLedOn) + if (pLed->led_on) pLed->BlinkingLedState = RTW_LED_OFF; else pLed->BlinkingLedState = RTW_LED_ON; @@ -118,7 +113,7 @@ static void SwLedBlink1(struct LED_871x *pLed) msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); break; case LED_BLINK_NORMAL: - if (pLed->bLedOn) + if (pLed->led_on) pLed->BlinkingLedState = RTW_LED_OFF; else pLed->BlinkingLedState = RTW_LED_ON; @@ -131,27 +126,25 @@ static void SwLedBlink1(struct LED_871x *pLed) if (check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->bLedLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_NORMAL; - if (pLed->bLedOn) + if (pLed->led_on) pLed->BlinkingLedState = RTW_LED_OFF; else pLed->BlinkingLedState = RTW_LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); - RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState)); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; - if (pLed->bLedOn) + if (pLed->led_on) pLed->BlinkingLedState = RTW_LED_OFF; else pLed->BlinkingLedState = RTW_LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); - RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState)); } pLed->bLedScanBlinkInProgress = false; } else { - if (pLed->bLedOn) + if (pLed->led_on) pLed->BlinkingLedState = RTW_LED_OFF; else pLed->BlinkingLedState = RTW_LED_ON; @@ -165,27 +158,25 @@ static void SwLedBlink1(struct LED_871x *pLed) if (check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->bLedLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_NORMAL; - if (pLed->bLedOn) + if (pLed->led_on) pLed->BlinkingLedState = RTW_LED_OFF; else pLed->BlinkingLedState = RTW_LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); - RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState)); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; - if (pLed->bLedOn) + if (pLed->led_on) pLed->BlinkingLedState = RTW_LED_OFF; else pLed->BlinkingLedState = RTW_LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); - RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState)); } pLed->bLedBlinkInProgress = false; } else { - if (pLed->bLedOn) + if (pLed->led_on) pLed->BlinkingLedState = RTW_LED_OFF; else pLed->BlinkingLedState = RTW_LED_ON; @@ -194,7 +185,7 @@ static void SwLedBlink1(struct LED_871x *pLed) } break; case LED_BLINK_WPS: - if (pLed->bLedOn) + if (pLed->led_on) pLed->BlinkingLedState = RTW_LED_OFF; else pLed->BlinkingLedState = RTW_LED_ON; @@ -205,13 +196,12 @@ static void SwLedBlink1(struct LED_871x *pLed) if (pLed->BlinkingLedState != RTW_LED_ON) { pLed->bLedLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_NORMAL; - if (pLed->bLedOn) + if (pLed->led_on) pLed->BlinkingLedState = RTW_LED_OFF; else pLed->BlinkingLedState = RTW_LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); - RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState)); pLed->bLedWPSBlinkInProgress = false; } else { @@ -251,7 +241,7 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct } pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; - if (pLed->bLedOn) + if (pLed->led_on) pLed->BlinkingLedState = RTW_LED_OFF; else pLed->BlinkingLedState = RTW_LED_ON; @@ -274,7 +264,7 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct } pLed->bLedLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_NORMAL; - if (pLed->bLedOn) + if (pLed->led_on) pLed->BlinkingLedState = RTW_LED_OFF; else pLed->BlinkingLedState = RTW_LED_ON; @@ -304,7 +294,7 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct pLed->bLedScanBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SCAN; pLed->BlinkTimes = 24; - if (pLed->bLedOn) + if (pLed->led_on) pLed->BlinkingLedState = RTW_LED_OFF; else pLed->BlinkingLedState = RTW_LED_ON; @@ -329,7 +319,7 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct pLed->bLedBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_TXRX; pLed->BlinkTimes = 2; - if (pLed->bLedOn) + if (pLed->led_on) pLed->BlinkingLedState = RTW_LED_OFF; else pLed->BlinkingLedState = RTW_LED_ON; @@ -358,7 +348,7 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct } pLed->bLedWPSBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_WPS; - if (pLed->bLedOn) + if (pLed->led_on) pLed->BlinkingLedState = RTW_LED_OFF; else pLed->BlinkingLedState = RTW_LED_ON; @@ -387,7 +377,7 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct else pLed->bLedWPSBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_WPS_STOP; - if (pLed->bLedOn) { + if (pLed->led_on) { pLed->BlinkingLedState = RTW_LED_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); @@ -404,7 +394,7 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct } pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; - if (pLed->bLedOn) + if (pLed->led_on) pLed->BlinkingLedState = RTW_LED_OFF; else pLed->BlinkingLedState = RTW_LED_ON; @@ -439,9 +429,6 @@ static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAct default: break; } - - RT_TRACE(_module_rtl8712_led_c_, _drv_info_, - ("Led %d\n", pLed->CurrLedState)); } void blink_handler(struct LED_871x *pLed) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index b6ac5b8915b1..71d205f3d73d 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -19,6 +19,7 @@ #include <wlan_bssdef.h> #include <rtw_ioctl_set.h> #include <linux/vmalloc.h> +#include <linux/etherdevice.h> extern const u8 MCS_rate_1R[16]; @@ -32,8 +33,6 @@ int rtw_init_mlme_priv(struct adapter *padapter) /* We don't need to memset padapter->XXX to zero, because adapter is allocated by vzalloc(). */ - pmlmepriv->nic_hdl = (u8 *)padapter; - pmlmepriv->pscanned = NULL; pmlmepriv->fw_state = 0; pmlmepriv->cur_network.network.InfrastructureMode = Ndis802_11AutoUnknown; @@ -118,8 +117,6 @@ struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv) list_del_init(&pnetwork->list); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("rtw_alloc_network: ptr=%p\n", &pnetwork->list)); pnetwork->network_type = 0; pnetwork->fixed = false; pnetwork->last_scanned = jiffies; @@ -181,20 +178,16 @@ struct wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr) { struct list_head *phead, *plist; struct wlan_network *pnetwork = NULL; - u8 zero_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; - if (!memcmp(zero_addr, addr, ETH_ALEN)) { + if (is_zero_ether_addr(addr)) { pnetwork = NULL; goto exit; } phead = get_list_head(scanned_queue); - plist = phead->next; - - while (plist != phead) { - pnetwork = container_of(plist, struct wlan_network, list); + list_for_each(plist, phead) { + pnetwork = list_entry(plist, struct wlan_network, list); if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN)) break; - plist = plist->next; } if (plist == phead) pnetwork = NULL; @@ -204,23 +197,17 @@ exit: void rtw_free_network_queue(struct adapter *padapter, u8 isfreeall) { - struct list_head *phead, *plist; - struct wlan_network *pnetwork; + struct list_head *phead; + struct wlan_network *pnetwork, *temp; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct __queue *scanned_queue = &pmlmepriv->scanned_queue; spin_lock_bh(&scanned_queue->lock); phead = get_list_head(scanned_queue); - plist = phead->next; - - while (phead != plist) { - pnetwork = container_of(plist, struct wlan_network, list); - - plist = plist->next; - + list_for_each_entry_safe(pnetwork, temp, phead, list) _rtw_free_network(pmlmepriv, pnetwork, isfreeall); - } + spin_unlock_bh(&scanned_queue->lock); } @@ -229,15 +216,10 @@ int rtw_if_up(struct adapter *padapter) int res; if (padapter->bDriverStopped || padapter->bSurpriseRemoved || - !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("%s:bDriverStopped(%d) OR bSurpriseRemoved(%d)", - __func__, padapter->bDriverStopped, - padapter->bSurpriseRemoved)); + !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) res = false; - } else { + else res = true; - } return res; } @@ -400,17 +382,14 @@ void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *t spin_lock_bh(&queue->lock); phead = get_list_head(queue); - plist = phead->next; - - while (phead != plist) { - pnetwork = container_of(plist, struct wlan_network, list); + list_for_each(plist, phead) { + pnetwork = list_entry(plist, struct wlan_network, list); if (is_same_network(&pnetwork->network, target)) break; if ((oldest == ((struct wlan_network *)0)) || time_after(oldest->last_scanned, pnetwork->last_scanned)) oldest = pnetwork; - plist = plist->next; } /* If we didn't find a match, then get a new network slot to initialize * with this beacon's information @@ -440,11 +419,8 @@ void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *t pnetwork = rtw_alloc_network(pmlmepriv); /* will update scan_time */ - if (!pnetwork) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - ("\n\n\nsomething wrong here\n\n\n")); + if (!pnetwork) goto exit; - } bssid_ex_sz = get_wlan_bssid_ex_sz(target); target->Length = bssid_ex_sz; @@ -520,10 +496,8 @@ static int rtw_is_desired_network(struct adapter *adapter, struct wlan_network * bselected = false; } - if ((desired_encmode != Ndis802_11EncryptionDisabled) && (privacy == 0)) { - DBG_88E("desired_encmode: %d, privacy: %d\n", desired_encmode, privacy); + if ((desired_encmode != Ndis802_11EncryptionDisabled) && (privacy == 0)) bselected = false; - } if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode) @@ -533,12 +507,6 @@ static int rtw_is_desired_network(struct adapter *adapter, struct wlan_network * return bselected; } -/* TODO: Perry: For Power Management */ -void rtw_atimdone_event_callback(struct adapter *adapter, u8 *pbuf) -{ - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("receive atimdone_event\n")); -} - void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf) { u32 len; @@ -547,15 +515,9 @@ void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf) pnetwork = (struct wlan_bssid_ex *)pbuf; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("%s, ssid=%s\n", __func__, pnetwork->ssid.ssid)); - len = get_wlan_bssid_ex_sz(pnetwork); - if (len > (sizeof(struct wlan_bssid_ex))) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - ("\n****%s: return a wrong bss ***\n", __func__)); + if (len > (sizeof(struct wlan_bssid_ex))) return; - } spin_lock_bh(&pmlmepriv->lock); /* update IBSS_network 's timestamp */ @@ -598,14 +560,9 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf) pmlmepriv->wps_probe_req_ie = NULL; } - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("%s: fw_state:%x\n\n", __func__, get_fwstate(pmlmepriv))); - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) { del_timer_sync(&pmlmepriv->scan_to_timer); _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); - } else { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("nic status=%x, survey done event comes too late!\n", get_fwstate(pmlmepriv))); } rtw_set_signal_stat_timer(&adapter->recvpriv); @@ -624,8 +581,6 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf) _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("switching to adhoc master\n")); - memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid)); rtw_update_registrypriv_dev_network(adapter); @@ -633,8 +588,7 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf) pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE; - if (rtw_createbss_cmd(adapter) != _SUCCESS) - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Error=>rtw_createbss_cmd status FAIL\n")); + rtw_createbss_cmd(adapter); pmlmepriv->to_join = false; } } @@ -651,7 +605,6 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf) _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); rtw_indicate_connect(adapter); } else { - DBG_88E("try_to_join, but select scanning queue fail, to_roaming:%d\n", pmlmepriv->to_roaming); if (pmlmepriv->to_roaming != 0) { if (--pmlmepriv->to_roaming == 0 || rtw_sitesurvey_cmd(adapter, &pmlmepriv->assoc_ssid, 1, NULL, 0) != _SUCCESS) { @@ -688,7 +641,6 @@ static void free_scanqueue(struct mlme_priv *pmlmepriv) struct __queue *scan_queue = &pmlmepriv->scanned_queue; struct list_head *plist, *phead, *ptemp; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+%s\n", __func__)); spin_lock_bh(&scan_queue->lock); spin_lock_bh(&free_queue->lock); @@ -728,11 +680,6 @@ void rtw_free_assoc_resources_locked(struct adapter *adapter) struct sta_priv *pstapriv = &adapter->stapriv; struct wlan_network *tgt_network = &pmlmepriv->cur_network; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_free_assoc_resources\n")); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("tgt_network->network.MacAddress=%pM ssid=%s\n", - tgt_network->network.MacAddress, tgt_network->network.ssid.ssid)); - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE)) { struct sta_info *psta; @@ -759,8 +706,6 @@ void rtw_free_assoc_resources_locked(struct adapter *adapter) pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress); if (pwlan) pwlan->fixed = false; - else - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_assoc_resources:pwlan==NULL\n\n")); if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) && (adapter->stapriv.asoc_sta_count == 1))) rtw_free_network_nolock(pmlmepriv, pwlan); @@ -775,8 +720,6 @@ void rtw_indicate_connect(struct adapter *padapter) { struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+%s\n", __func__)); - pmlmepriv->to_join = false; if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { @@ -790,8 +733,6 @@ void rtw_indicate_connect(struct adapter *padapter) pmlmepriv->to_roaming = 0; rtw_set_scan_deny(padapter, 3000); - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("-%s: fw_state=0x%08x\n", __func__, get_fwstate(pmlmepriv))); } /* @@ -801,8 +742,6 @@ void rtw_indicate_disconnect(struct adapter *padapter) { struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+%s\n", __func__)); - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING | WIFI_UNDER_WPS); if (pmlmepriv->to_roaming > 0) @@ -837,7 +776,6 @@ static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, str psta = rtw_alloc_stainfo(pstapriv, pnetwork->network.MacAddress); if (psta) { /* update ptarget_sta */ - DBG_88E("%s\n", __func__); psta->aid = pnetwork->join_res; psta->mac_id = 0; /* sta mode */ @@ -900,12 +838,6 @@ static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_net struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct wlan_network *cur_network = &pmlmepriv->cur_network; - DBG_88E("%s\n", __func__); - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("\nfw_state:%x, BSSID:%pM\n", - get_fwstate(pmlmepriv), pnetwork->network.MacAddress)); - /* why not use ptarget_wlan?? */ memcpy(&cur_network->network, &pnetwork->network, pnetwork->network.Length); /* some ies in pnetwork is wrong, so we should use ptarget_wlan ies */ @@ -934,7 +866,6 @@ static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_net break; default: pmlmepriv->fw_state = WIFI_NULL_STATE; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Invalid network_mode\n")); break; } @@ -961,27 +892,16 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf) struct wlan_network *pcur_wlan = NULL, *ptarget_wlan = NULL; unsigned int the_same_macaddr = false; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("joinbss event call back received with res=%d\n", pnetwork->join_res)); - rtw_get_encrypt_decrypt_from_registrypriv(adapter); - if (pmlmepriv->assoc_ssid.ssid_length == 0) - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("@@@@@ joinbss event call back for Any SSid\n")); - else - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("@@@@@ rtw_joinbss_event_callback for SSid:%s\n", pmlmepriv->assoc_ssid.ssid)); - the_same_macaddr = !memcmp(pnetwork->network.MacAddress, cur_network->network.MacAddress, ETH_ALEN); pnetwork->network.Length = get_wlan_bssid_ex_sz(&pnetwork->network); - if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex)) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n\n ***joinbss_evt_callback return a wrong bss ***\n\n")); + if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex)) return; - } spin_lock_bh(&pmlmepriv->lock); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\nrtw_joinbss_event_callback!! _enter_critical\n")); - if (pnetwork->join_res > 0) { spin_lock_bh(&pmlmepriv->scanned_queue.lock); if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { @@ -1019,7 +939,6 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf) if (ptarget_wlan) { rtw_joinbss_update_network(adapter, ptarget_wlan, pnetwork); } else { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Can't find ptarget_wlan when joinbss_event callback\n")); spin_unlock_bh(&pmlmepriv->scanned_queue.lock); goto ignore_joinbss_callback; } @@ -1028,7 +947,6 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf) if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { ptarget_sta = rtw_joinbss_update_stainfo(adapter, pnetwork); if (!ptarget_sta) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Can't update stainfo when joinbss_event callback\n")); spin_unlock_bh(&pmlmepriv->scanned_queue.lock); goto ignore_joinbss_callback; } @@ -1037,18 +955,11 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf) /* s4. indicate connect */ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { rtw_indicate_connect(adapter); - } else { - /* adhoc mode will rtw_indicate_connect when rtw_stassoc_event_callback */ - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("adhoc mode, fw_state:%x", get_fwstate(pmlmepriv))); } /* s5. Cancel assoc_timer */ del_timer_sync(&pmlmepriv->assoc_timer); - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("Cancel assoc_timer\n")); - } else { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_joinbss_event_callback err: fw_state:%x", get_fwstate(pmlmepriv))); spin_unlock_bh(&pmlmepriv->scanned_queue.lock); goto ignore_joinbss_callback; } @@ -1060,10 +971,8 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf) mod_timer(&pmlmepriv->assoc_timer, jiffies + msecs_to_jiffies(1)); - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("fail! clear _FW_UNDER_LINKING ^^^fw_state=%x\n", get_fwstate(pmlmepriv))); + if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - } } else { /* if join_res < 0 (join fails), then try again */ mod_timer(&pmlmepriv->assoc_timer, jiffies + msecs_to_jiffies(1)); @@ -1150,23 +1059,16 @@ void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf) #endif /* for AD-HOC mode */ psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr); - if (psta) { + if (psta) /* the sta have been in sta_info_queue => do nothing */ - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - ("Error: %s: sta has been in sta_hash_queue\n", - __func__)); return; /* between drv has received this event before and fw have not yet to set key to CAM_ENTRY) */ - } psta = rtw_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr); - if (!psta) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - ("Can't alloc sta_info when %s\n", __func__)); + if (!psta) return; - } + /* to do: init sta_info variable */ psta->qos_option = 0; psta->mac_id = (uint)pstassoc->cam_id; - DBG_88E("%s\n", __func__); /* for ad-hoc mode */ rtw_hal_set_odm_var(adapter, HAL_ODM_STA_INFO, psta, true); rtw_stassoc_hw_rpt(adapter, psta); @@ -1208,8 +1110,6 @@ void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf) else mac_id = pstadel->mac_id; - DBG_88E("%s(mac_id=%d)=%pM\n", __func__, mac_id, pstadel->macaddr); - if (mac_id >= 0) { u16 media_status; @@ -1280,18 +1180,12 @@ void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf) _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE); } - if (rtw_createbss_cmd(adapter) != _SUCCESS) - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("***Error=>stadel_event_callback: rtw_createbss_cmd status FAIL***\n ")); + rtw_createbss_cmd(adapter); } } spin_unlock_bh(&pmlmepriv->lock); } -void rtw_cpwm_event_callback(struct adapter *padapter, u8 *pbuf) -{ - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+%s !!!\n", __func__)); -} - /* * _rtw_join_timeout_handler - Timeout/failure handler for CMD JoinBss * @adapter: pointer to struct adapter structure @@ -1302,8 +1196,6 @@ void _rtw_join_timeout_handler (struct timer_list *t) struct mlme_priv *pmlmepriv = &adapter->mlmepriv; int do_join_r; - DBG_88E("%s, fw_state=%x\n", __func__, get_fwstate(pmlmepriv)); - if (adapter->bDriverStopped || adapter->bSurpriseRemoved) return; @@ -1313,15 +1205,11 @@ void _rtw_join_timeout_handler (struct timer_list *t) while (1) { pmlmepriv->to_roaming--; if (pmlmepriv->to_roaming != 0) { /* try another , */ - DBG_88E("%s try another roaming\n", __func__); do_join_r = rtw_do_join(adapter); - if (do_join_r != _SUCCESS) { - DBG_88E("%s roaming do_join return %d\n", __func__, do_join_r); + if (do_join_r != _SUCCESS) continue; - } break; } - DBG_88E("%s We've try roaming but fail\n", __func__); rtw_indicate_disconnect(adapter); break; } @@ -1342,7 +1230,6 @@ void rtw_scan_timeout_handler (struct timer_list *t) mlmepriv.scan_to_timer); struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - DBG_88E(FUNC_ADPT_FMT" fw_state=%x\n", FUNC_ADPT_ARG(adapter), get_fwstate(pmlmepriv)); spin_lock_bh(&pmlmepriv->lock); _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); spin_unlock_bh(&pmlmepriv->lock); @@ -1357,7 +1244,6 @@ static void rtw_auto_scan_handler(struct adapter *padapter) if (pmlmepriv->scan_interval > 0) { pmlmepriv->scan_interval--; if (pmlmepriv->scan_interval == 0) { - DBG_88E("%s\n", __func__); rtw_set_802_11_bssid_list_scan(padapter, NULL, 0); pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */ } @@ -1431,15 +1317,6 @@ static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv *candidate = competitor; updated = true; } - if (updated) { - DBG_88E("[by_bssid:%u][assoc_ssid:%s]new candidate: %s(%pM rssi:%d\n", - pmlmepriv->assoc_by_bssid, - pmlmepriv->assoc_ssid.ssid, - (*candidate)->network.ssid.ssid, - (*candidate)->network.MacAddress, - (int)(*candidate)->network.Rssi); - DBG_88E("[to_roaming:%u]\n", pmlmepriv->to_roaming); - } exit: return updated; @@ -1456,7 +1333,7 @@ int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv) { int ret; struct list_head *phead; - struct adapter *adapter; + struct adapter *adapter = container_of(pmlmepriv, struct adapter, mlmepriv); struct __queue *queue = &pmlmepriv->scanned_queue; struct wlan_network *pnetwork = NULL; struct wlan_network *candidate = NULL; @@ -1464,32 +1341,18 @@ int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv) spin_lock_bh(&pmlmepriv->scanned_queue.lock); phead = get_list_head(queue); - adapter = (struct adapter *)pmlmepriv->nic_hdl; - pmlmepriv->pscanned = phead->next; - while (phead != pmlmepriv->pscanned) { - pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list); - if (!pnetwork) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s return _FAIL:(pnetwork==NULL)\n", __func__)); - ret = _FAIL; - goto exit; - } - pmlmepriv->pscanned = pmlmepriv->pscanned->next; + list_for_each(pmlmepriv->pscanned, phead) { + pnetwork = list_entry(pmlmepriv->pscanned, + struct wlan_network, list); rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork); } if (!candidate) { - DBG_88E("%s: return _FAIL(candidate==NULL)\n", __func__); ret = _FAIL; goto exit; - } else { - DBG_88E("%s: candidate: %s(%pM ch:%u)\n", __func__, - candidate->network.ssid.ssid, candidate->network.MacAddress, - candidate->network.Configuration.DSConfig); } /* check for situation of _FW_LINKED */ if (check_fwstate(pmlmepriv, _FW_LINKED)) { - DBG_88E("%s: _FW_LINKED while ask_for_joinbss!!!\n", __func__); - rtw_disassoc_cmd(adapter, 0, true); rtw_indicate_disconnect(adapter); rtw_free_assoc_resources_locked(adapter); @@ -1500,10 +1363,6 @@ int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv) u8 cur_ant; rtw_hal_get_def_var(adapter, HAL_DEF_CURRENT_ANTENNA, &(cur_ant)); - DBG_88E("#### Opt_Ant_(%s), cur_Ant(%s)\n", - (candidate->network.PhyInfo.Optimum_antenna == 2) ? "A" : "B", - (cur_ant == 2) ? "A" : "B" - ); } ret = rtw_joinbss_cmd(adapter, candidate); @@ -1539,9 +1398,6 @@ int rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv) pcmd->rsp = NULL; pcmd->rspsz = 0; INIT_LIST_HEAD(&pcmd->list); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - ("after enqueue set_auth_cmd, auth_mode=%x\n", - psecuritypriv->dot11AuthAlgrthm)); res = rtw_enqueue_cmd(pcmdpriv, pcmd); exit: return res; @@ -1566,26 +1422,13 @@ int rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, in goto err_free_cmd; } - if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { + if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) psetkeyparm->algorithm = (unsigned char)psecuritypriv->dot118021XGrpPrivacy; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - ("\n %s: psetkeyparm->algorithm=(unsigned char)psecuritypriv->dot118021XGrpPrivacy=%d\n", - __func__, psetkeyparm->algorithm)); - } else { + else psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - ("\n %s: psetkeyparm->algorithm=(u8)psecuritypriv->dot11PrivacyAlgrthm=%d\n", - __func__, psetkeyparm->algorithm)); - } psetkeyparm->keyid = (u8)keyid;/* 0~3 */ psetkeyparm->set_tx = set_tx; pmlmepriv->key_mask |= BIT(psetkeyparm->keyid); - DBG_88E("==> %s algorithm(%x), keyid(%x), key_mask(%x)\n", - __func__, psetkeyparm->algorithm, psetkeyparm->keyid, - pmlmepriv->key_mask); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - ("\n %s: psetkeyparm->algorithm=%d psetkeyparm->keyid=(u8)keyid=%d\n", - __func__, psetkeyparm->algorithm, keyid)); switch (psetkeyparm->algorithm) { case _WEP40_: @@ -1609,9 +1452,6 @@ int rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, in psetkeyparm->grpkey = 1; break; default: - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - ("\n %s:psecuritypriv->dot11PrivacyAlgrthm=%x (must be 1 or 2 or 4 or 5)\n", - __func__, psecuritypriv->dot11PrivacyAlgrthm)); res = _FAIL; goto err_free_parm; } @@ -1717,11 +1557,6 @@ int rtw_restruct_sec_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_ struct mlme_priv *pmlmepriv = &adapter->mlmepriv; struct security_priv *psecuritypriv = &adapter->securitypriv; uint ndisauthmode = psecuritypriv->ndisauthtype; - uint ndissecuritytype = psecuritypriv->ndisencryptstatus; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, - ("+%s: ndisauthmode=%d ndissecuritytype=%d\n", __func__, - ndisauthmode, ndissecuritytype)); /* copy fixed ie only */ memcpy(out_ie, in_ie, 12); @@ -1801,9 +1636,6 @@ void rtw_update_registrypriv_dev_network(struct adapter *adapter) } pdev_network->Configuration.DSConfig = pregistrypriv->channel; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("pregistrypriv->channel=%d, pdev_network->Configuration.DSConfig=0x%x\n", - pregistrypriv->channel, pdev_network->Configuration.DSConfig)); if (cur_network->network.InfrastructureMode == Ndis802_11IBSS) pdev_network->Configuration.ATIMWindow = 0; @@ -1936,8 +1768,6 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len) if ((!pmlmeinfo->HT_info_enable) || (!pmlmeinfo->HT_caps_enable)) return; - DBG_88E("+%s()\n", __func__); - /* maybe needs check if ap supports rx ampdu. */ if ((!phtpriv->ampdu_enable) && (pregistrypriv->ampdu_enable == 1)) { if (pregistrypriv->wifi_spec == 1) @@ -1974,8 +1804,6 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len) /* Config SM Power Save setting */ pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & 0x0C) >> 2; - if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC) - DBG_88E("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__); /* Config current HT Protection mode. */ pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3; @@ -2010,7 +1838,6 @@ void rtw_issue_addbareq_cmd(struct adapter *padapter, struct xmit_frame *pxmitfr issued |= (phtpriv->candidate_tid_bitmap >> priority) & 0x1; if (issued == 0) { - DBG_88E("%s, p=%d\n", __func__, priority); psta->htpriv.candidate_tid_bitmap |= BIT((u8)priority); rtw_addbareq_cmd(padapter, (u8)priority, pattrib->ra); } @@ -2038,9 +1865,6 @@ void _rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network) pnetwork = &pmlmepriv->cur_network; if (pmlmepriv->to_roaming > 0) { - DBG_88E("roaming from %s(%pM length:%d\n", - pnetwork->network.ssid.ssid, pnetwork->network.MacAddress, - pnetwork->network.ssid.ssid_length); memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.ssid, sizeof(struct ndis_802_11_ssid)); pmlmepriv->assoc_by_bssid = false; @@ -2050,13 +1874,11 @@ void _rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network) if (do_join_r == _SUCCESS) break; - DBG_88E("roaming do_join return %d\n", do_join_r); pmlmepriv->to_roaming--; if (pmlmepriv->to_roaming > 0) { continue; } else { - DBG_88E("%s(%d) -to roaming fail, indicate_disconnect\n", __func__, __LINE__); rtw_indicate_disconnect(padapter); break; } diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 50d3c3631be0..25653ebfaafd 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -7,6 +7,7 @@ #define _RTW_MLME_EXT_C_ #include <linux/ieee80211.h> +#include <linux/etherdevice.h> #include <asm/unaligned.h> #include <osdep_service.h> @@ -148,14 +149,11 @@ struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv) struct xmit_buf *pxmitbuf; pmgntframe = rtw_alloc_xmitframe(pxmitpriv); - if (!pmgntframe) { - DBG_88E("%s, alloc xmitframe fail\n", __func__); + if (!pmgntframe) return NULL; - } pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv); if (!pxmitbuf) { - DBG_88E("%s, alloc xmitbuf fail\n", __func__); rtw_free_xmitframe(pxmitpriv, pmgntframe); return NULL; } @@ -177,7 +175,6 @@ void update_mgnt_tx_rate(struct adapter *padapter, u8 rate) struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; pmlmeext->tx_rate = rate; - DBG_88E("%s(): rate = %x\n", __func__, rate); } void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib) @@ -314,13 +311,10 @@ static void issue_beacon(struct adapter *padapter, int timeout_ms) struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) { - DBG_88E("%s, alloc mgnt frame fail\n", __func__); + if (!pmgntframe) return; - } #if defined(CONFIG_88EU_AP_MODE) spin_lock_bh(&pmlmepriv->bcn_update_lock); #endif @@ -338,13 +332,13 @@ static void issue_beacon(struct adapter *padapter, int timeout_ms) fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; - ether_addr_copy(pwlanhdr->addr1, bc_addr); + eth_broadcast_addr(pwlanhdr->addr1); ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv)); ether_addr_copy(pwlanhdr->addr3, cur_network->MacAddress); SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); /* pmlmeext->mgnt_seq++; */ - SetFrameSubType(pframe, WIFI_BEACON); + SetFrameSubType(pframe, IEEE80211_STYPE_BEACON); pframe += sizeof(struct ieee80211_hdr_3addr); pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); @@ -428,14 +422,11 @@ _issue_bcn: spin_unlock_bh(&pmlmepriv->bcn_update_lock); #endif - if ((pattrib->pktlen + TXDESC_SIZE) > 512) { - DBG_88E("beacon frame too large\n"); + if ((pattrib->pktlen + TXDESC_SIZE) > 512) return; - } pattrib->last_txcmdsz = pattrib->pktlen; - /* DBG_88E("issue bcn_sz=%d\n", pattrib->last_txcmdsz); */ if (timeout_ms > 0) dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms); else @@ -462,10 +453,8 @@ static void issue_probersp(struct adapter *padapter, unsigned char *da) unsigned int rate_len; pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (!pmgntframe) { - DBG_88E("%s, alloc mgnt frame fail\n", __func__); + if (!pmgntframe) return; - } /* update attribute */ pattrib = &pmgntframe->attrib; @@ -487,7 +476,7 @@ static void issue_probersp(struct adapter *padapter, unsigned char *da) SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; - SetFrameSubType(fctrl, WIFI_PROBERSP); + SetFrameSubType(fctrl, IEEE80211_STYPE_PROBE_RESP); pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); pattrib->pktlen = pattrib->hdrlen; @@ -604,9 +593,6 @@ static int issue_probereq(struct adapter *padapter, struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; int bssrate_len = 0; - u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+%s\n", __func__)); pmgntframe = alloc_mgtxmitframe(pxmitpriv); if (!pmgntframe) @@ -632,15 +618,15 @@ static int issue_probereq(struct adapter *padapter, ether_addr_copy(pwlanhdr->addr3, da); } else { /* broadcast probe request frame */ - ether_addr_copy(pwlanhdr->addr1, bc_addr); - ether_addr_copy(pwlanhdr->addr3, bc_addr); + eth_broadcast_addr(pwlanhdr->addr1); + eth_broadcast_addr(pwlanhdr->addr3); } ether_addr_copy(pwlanhdr->addr2, mac); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_PROBEREQ); + SetFrameSubType(pframe, IEEE80211_STYPE_PROBE_REQ); pframe += sizeof(struct ieee80211_hdr_3addr); pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); @@ -668,9 +654,6 @@ static int issue_probereq(struct adapter *padapter, pattrib->last_txcmdsz = pattrib->pktlen; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, - ("issuing probe_req, tx_len=%d\n", pattrib->last_txcmdsz)); - if (wait_ack) { ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); } else { @@ -688,7 +671,6 @@ static int issue_probereq_ex(struct adapter *padapter, { int ret; int i = 0; - unsigned long start = jiffies; do { ret = issue_probereq(padapter, pssid, da, wait_ms > 0); @@ -707,19 +689,6 @@ static int issue_probereq_ex(struct adapter *padapter, ret = _SUCCESS; goto exit; } - - if (try_cnt && wait_ms) { - if (da) - DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n", - FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - else - DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n", - FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - } exit: return ret; } @@ -762,7 +731,7 @@ static void issue_auth(struct adapter *padapter, struct sta_info *psta, SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_AUTH); + SetFrameSubType(pframe, IEEE80211_STYPE_AUTH); pframe += sizeof(struct ieee80211_hdr_3addr); pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); @@ -865,7 +834,6 @@ static void issue_auth(struct adapter *padapter, struct sta_info *psta, pattrib->last_txcmdsz = pattrib->pktlen; rtw_wep_encrypt(padapter, pmgntframe); - DBG_88E("%s\n", __func__); dump_mgntframe(padapter, pmgntframe); } @@ -887,8 +855,6 @@ static void issue_asocrsp(struct adapter *padapter, unsigned short status, u8 *ie = pnetwork->ies; __le16 lestatus, leval; - DBG_88E("%s\n", __func__); - pmgntframe = alloc_mgtxmitframe(pxmitpriv); if (!pmgntframe) return; @@ -912,7 +878,7 @@ static void issue_asocrsp(struct adapter *padapter, unsigned short status, SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; - if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP)) + if ((pkt_type == IEEE80211_STYPE_ASSOC_RESP) || (pkt_type == IEEE80211_STYPE_REASSOC_RESP)) SetFrameSubType(pwlanhdr, pkt_type); else return; @@ -1034,7 +1000,7 @@ static void issue_assocreq(struct adapter *padapter) SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_ASSOCREQ); + SetFrameSubType(pframe, IEEE80211_STYPE_ASSOC_REQ); pframe += sizeof(struct ieee80211_hdr_3addr); pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); @@ -1066,7 +1032,6 @@ static void issue_assocreq(struct adapter *padapter) for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { if (pmlmeinfo->network.SupportedRates[i] == 0) break; - DBG_88E("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]); } for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { @@ -1081,17 +1046,12 @@ static void issue_assocreq(struct adapter *padapter) break; } - if (j == sta_bssrate_len) { - /* the rate is not supported by STA */ - DBG_88E("%s(): the rate[%d]=%02X is not supported by STA!\n", __func__, i, pmlmeinfo->network.SupportedRates[i]); - } else { + if (j != sta_bssrate_len) /* the rate is supported by STA */ bssrate[index++] = pmlmeinfo->network.SupportedRates[i]; - } } bssrate_len = index; - DBG_88E("bssrate_len=%d\n", bssrate_len); if (bssrate_len == 0) { rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf); @@ -1226,7 +1186,7 @@ static int _issue_nulldata(struct adapter *padapter, unsigned char *da, SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_DATA_NULL); + SetFrameSubType(pframe, IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC); pframe += sizeof(struct ieee80211_hdr_3addr); pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); @@ -1251,7 +1211,6 @@ int issue_nulldata(struct adapter *padapter, unsigned char *da, { int ret; int i = 0; - unsigned long start = jiffies; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; @@ -1276,19 +1235,6 @@ int issue_nulldata(struct adapter *padapter, unsigned char *da, ret = _SUCCESS; goto exit; } - - if (try_cnt && wait_ms) { - if (da) - DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n", - FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - else - DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n", - FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - } exit: return ret; } @@ -1309,8 +1255,6 @@ static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - DBG_88E("%s\n", __func__); - pmgntframe = alloc_mgtxmitframe(pxmitpriv); if (!pmgntframe) goto exit; @@ -1355,7 +1299,7 @@ static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_QOS_DATA_NULL); + SetFrameSubType(pframe, IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC); pframe += sizeof(struct ieee80211_qos_hdr); pattrib->pktlen = sizeof(struct ieee80211_qos_hdr); @@ -1380,7 +1324,6 @@ int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, { int ret; int i = 0; - unsigned long start = jiffies; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; @@ -1405,19 +1348,6 @@ int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, ret = _SUCCESS; goto exit; } - - if (try_cnt && wait_ms) { - if (da) - DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n", - FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - else - DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n", - FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - } exit: return ret; } @@ -1460,7 +1390,7 @@ static int _issue_deauth(struct adapter *padapter, unsigned char *da, SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_DEAUTH); + SetFrameSubType(pframe, IEEE80211_STYPE_DEAUTH); pframe += sizeof(struct ieee80211_hdr_3addr); pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); @@ -1485,7 +1415,6 @@ exit: int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason) { - DBG_88E("%s to %pM\n", __func__, da); return _issue_deauth(padapter, da, reason, false); } @@ -1495,7 +1424,6 @@ static int issue_deauth_ex(struct adapter *padapter, u8 *da, { int ret; int i = 0; - unsigned long start = jiffies; do { ret = _issue_deauth(padapter, da, reason, wait_ms > 0); @@ -1513,19 +1441,6 @@ static int issue_deauth_ex(struct adapter *padapter, u8 *da, ret = _SUCCESS; goto exit; } - - if (try_cnt && wait_ms) { - if (da) - DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n", - FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - else - DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n", - FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - } exit: return ret; } @@ -1554,8 +1469,6 @@ static void issue_action_BA(struct adapter *padapter, unsigned char *raddr, struct registry_priv *pregpriv = &padapter->registrypriv; struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - DBG_88E("%s, category=%d, action=%d, status=%d\n", __func__, category, action, status); - pmgntframe = alloc_mgtxmitframe(pxmitpriv); if (!pmgntframe) return; @@ -1578,7 +1491,7 @@ static void issue_action_BA(struct adapter *padapter, unsigned char *raddr, SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_ACTION); + SetFrameSubType(pframe, IEEE80211_STYPE_ACTION); pframe += sizeof(struct ieee80211_hdr_3addr); pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); @@ -1608,8 +1521,6 @@ static void issue_action_BA(struct adapter *padapter, unsigned char *raddr, if (psta) { start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07] & 0xfff) + 1; - DBG_88E("BA_starting_seqctrl=%d for TID=%d\n", start_seq, status & 0x07); - psta->BA_starting_seqctrl[status & 0x07] = start_seq; BA_starting_seqctrl = start_seq << 4; @@ -1708,8 +1619,6 @@ static void issue_action_BSSCoexistPacket(struct adapter *padapter) if (pmlmeinfo->bwmode_updated) return; - DBG_88E("%s\n", __func__); - category = RTW_WLAN_CATEGORY_PUBLIC; action = ACT_PUBLIC_BSSCOEXIST; @@ -1735,7 +1644,7 @@ static void issue_action_BSSCoexistPacket(struct adapter *padapter) SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_ACTION); + SetFrameSubType(pframe, IEEE80211_STYPE_ACTION); pframe += sizeof(struct ieee80211_hdr_3addr); pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); @@ -1760,16 +1669,13 @@ static void issue_action_BSSCoexistPacket(struct adapter *padapter) spin_lock_bh(&pmlmepriv->scanned_queue.lock); phead = get_list_head(queue); - plist = phead->next; - - while (phead != plist) { + list_for_each(plist, phead) { uint len; u8 *p; struct wlan_bssid_ex *pbss_network; - pnetwork = container_of(plist, struct wlan_network, list); - - plist = plist->next; + pnetwork = list_entry(plist, struct wlan_network, + list); pbss_network = &pnetwork->network; @@ -1833,8 +1739,7 @@ unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr) if (initiator == 0) { /* recipient */ for (tid = 0; tid < MAXTID; tid++) { if (psta->recvreorder_ctrl[tid].enable) { - DBG_88E("rx agg disable tid(%d)\n", tid); - issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator) & 0x1F)); + issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator) & 0x1F)); psta->recvreorder_ctrl[tid].enable = false; psta->recvreorder_ctrl[tid].indicate_seq = 0xffff; } @@ -1842,8 +1747,7 @@ unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr) } else if (initiator == 1) { /* originator */ for (tid = 0; tid < MAXTID; tid++) { if (psta->htpriv.agg_enable_bitmap & BIT(tid)) { - DBG_88E("tx agg disable tid(%d)\n", tid); - issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator) & 0x1F)); + issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator) & 0x1F)); psta->htpriv.agg_enable_bitmap &= ~BIT(tid); psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); } @@ -1858,8 +1762,6 @@ unsigned int send_beacon(struct adapter *padapter) u8 bxmitok = false; int issue = 0; int poll = 0; - unsigned long start = jiffies; - u32 passing_time; rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL); do { @@ -1874,17 +1776,9 @@ unsigned int send_beacon(struct adapter *padapter) if (padapter->bSurpriseRemoved || padapter->bDriverStopped) return _FAIL; - if (!bxmitok) { - DBG_88E("%s fail! %u ms\n", __func__, - jiffies_to_msecs(jiffies - start)); + if (!bxmitok) return _FAIL; - } - passing_time = jiffies_to_msecs(jiffies - start); - if (passing_time > 100 || issue > 3) - DBG_88E("%s success, issue:%d, poll:%d, %u ms\n", - __func__, issue, poll, - jiffies_to_msecs(jiffies - start)); return _SUCCESS; } @@ -2024,15 +1918,15 @@ static u8 collect_bss_info(struct adapter *padapter, subtype = GetFrameSubType(pframe); - if (subtype == WIFI_BEACON) { + if (subtype == IEEE80211_STYPE_BEACON) { bssid->Reserved[0] = 1; ie_offset = _BEACON_IE_OFFSET_; } else { /* FIXME : more type */ - if (subtype == WIFI_PROBEREQ) { + if (subtype == IEEE80211_STYPE_PROBE_REQ) { ie_offset = _PROBEREQ_IE_OFFSET_; bssid->Reserved[0] = 2; - } else if (subtype == WIFI_PROBERSP) { + } else if (subtype == IEEE80211_STYPE_PROBE_RESP) { ie_offset = _PROBERSP_IE_OFFSET_; bssid->Reserved[0] = 3; } else { @@ -2055,16 +1949,12 @@ static u8 collect_bss_info(struct adapter *padapter, /* checking SSID */ p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_SSID, &len, bssid->ie_length - ie_offset); - if (!p) { - DBG_88E("marc: cannot find SSID for survey event\n"); + if (!p) return _FAIL; - } if (len) { - if (len > NDIS_802_11_LENGTH_SSID) { - DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len); + if (len > NDIS_802_11_LENGTH_SSID) return _FAIL; - } memcpy(bssid->ssid.ssid, (p + 2), len); bssid->ssid.ssid_length = len; } else { @@ -2077,20 +1967,16 @@ static u8 collect_bss_info(struct adapter *padapter, i = 0; p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_SUPP_RATES, &len, bssid->ie_length - ie_offset); if (p) { - if (len > NDIS_802_11_LENGTH_RATES_EX) { - DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len); + if (len > NDIS_802_11_LENGTH_RATES_EX) return _FAIL; - } memcpy(bssid->SupportedRates, (p + 2), len); i = len; } p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_EXT_SUPP_RATES, &len, bssid->ie_length - ie_offset); if (p) { - if (len > (NDIS_802_11_LENGTH_RATES_EX - i)) { - DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len); + if (len > (NDIS_802_11_LENGTH_RATES_EX - i)) return _FAIL; - } memcpy(bssid->SupportedRates + i, (p + 2), len); } @@ -2120,7 +2006,7 @@ static u8 collect_bss_info(struct adapter *padapter, } } - if (subtype == WIFI_PROBEREQ) { + if (subtype == IEEE80211_STYPE_PROBE_REQ) { /* FIXME */ bssid->InfrastructureMode = Ndis802_11Infrastructure; ether_addr_copy(bssid->MacAddress, GetAddr2Ptr(pframe)); @@ -2204,8 +2090,6 @@ static void start_create_ibss(struct adapter *padapter) /* issue beacon */ if (send_beacon(padapter) == _FAIL) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("issuing beacon frame fail....\n")); - report_join_res(padapter, -1); pmlmeinfo->state = WIFI_FW_NULL_STATE; } else { @@ -2217,7 +2101,6 @@ static void start_create_ibss(struct adapter *padapter) pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; } } else { - DBG_88E("%s, invalid cap:%x\n", __func__, caps); return; } } @@ -2300,7 +2183,6 @@ static void start_clnt_auth(struct adapter *padapter) /* For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */ issue_deauth(padapter, (&pmlmeinfo->network)->MacAddress, WLAN_REASON_DEAUTH_LEAVING); - DBG_88E_LEVEL(_drv_info_, "start auth\n"); issue_auth(padapter, NULL, 0); set_link_timer(pmlmeext, REAUTH_TO); @@ -2333,8 +2215,6 @@ static unsigned int receive_disconnect(struct adapter *padapter, if (memcmp(MacAddr, pnetwork->MacAddress, ETH_ALEN)) return _SUCCESS; - DBG_88E("%s\n", __func__); - if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) { if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { pmlmeinfo->state = WIFI_FW_NULL_STATE; @@ -2382,9 +2262,6 @@ static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid memset(country, 0, 4); memcpy(country, p, 3); p += 3; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, - ("%s: 802.11d country =%s\n", __func__, country)); - i = 0; while ((ie - p) >= 3) { fcn = *(p++); @@ -2478,12 +2355,8 @@ static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid i = 0; while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) { if (chplan_new[i].ChannelNum == channel) { - if (chplan_new[i].ScanType == SCAN_PASSIVE) { + if (chplan_new[i].ScanType == SCAN_PASSIVE) chplan_new[i].ScanType = SCAN_ACTIVE; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, - ("%s: change channel %d scan type from passive to active\n", - __func__, channel)); - } break; } i++; @@ -2593,7 +2466,6 @@ static unsigned int OnBeacon(struct adapter *padapter, if (psta) { ret = rtw_check_bcn_info(padapter, pframe, len); if (!ret) { - DBG_88E_LEVEL(_drv_info_, "ap has changed, disconnect now\n "); receive_disconnect(padapter, pmlmeinfo->network.MacAddress, 65535); return _SUCCESS; } @@ -2656,25 +2528,18 @@ static unsigned int OnAuth(struct adapter *padapter, if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE) return _FAIL; - DBG_88E("+%s\n", __func__); - sa = GetAddr2Ptr(pframe); auth_mode = psecuritypriv->dot11AuthAlgrthm; seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + 2)); algorithm = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN)); - DBG_88E("auth alg=%x, seq=%X\n", algorithm, seq); - if (auth_mode == 2 && psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ && psecuritypriv->dot11PrivacyAlgrthm != _WEP104_) auth_mode = 0; if ((algorithm > 0 && auth_mode == 0) || /* rx a shared-key auth but shared not enabled */ (algorithm == 0 && auth_mode == 1)) { /* rx a open-system auth but shared-key is enabled */ - DBG_88E("auth rejected due to bad alg [alg=%d, auth_mib=%d] %02X%02X%02X%02X%02X%02X\n", - algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); - status = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; goto auth_fail; @@ -2688,10 +2553,8 @@ static unsigned int OnAuth(struct adapter *padapter, pstat = rtw_get_stainfo(pstapriv, sa); if (!pstat) { /* allocate a new one */ - DBG_88E("going to alloc stainfo for sa=%pM\n", sa); pstat = rtw_alloc_stainfo(pstapriv, sa); if (!pstat) { - DBG_88E(" Exceed the upper limit of supported clients...\n"); status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; goto auth_fail; } @@ -2722,8 +2585,6 @@ static unsigned int OnAuth(struct adapter *padapter, pstat->expire_to = pstapriv->auth_to; if ((pstat->auth_seq + 1) != seq) { - DBG_88E("(1)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", - seq, pstat->auth_seq + 1); status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; goto auth_fail; } @@ -2735,8 +2596,6 @@ static unsigned int OnAuth(struct adapter *padapter, pstat->expire_to = pstapriv->assoc_to; pstat->authalg = algorithm; } else { - DBG_88E("(2)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", - seq, pstat->auth_seq + 1); status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; goto auth_fail; } @@ -2750,13 +2609,10 @@ static unsigned int OnAuth(struct adapter *padapter, pstat->auth_seq = 2; } else if (seq == 3) { /* checking for challenging txt... */ - DBG_88E("checking for challenging txt...\n"); - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, WLAN_EID_CHALLENGE, &ie_len, len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4); if (!p || ie_len <= 0) { - DBG_88E("auth rejected because challenge failure!(1)\n"); status = WLAN_STATUS_CHALLENGE_FAIL; goto auth_fail; } @@ -2767,13 +2623,10 @@ static unsigned int OnAuth(struct adapter *padapter, /* challenging txt is correct... */ pstat->expire_to = pstapriv->assoc_to; } else { - DBG_88E("auth rejected because challenge failure!\n"); status = WLAN_STATUS_CHALLENGE_FAIL; goto auth_fail; } } else { - DBG_88E("(3)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", - seq, pstat->auth_seq + 1); status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; goto auth_fail; } @@ -2816,8 +2669,6 @@ static unsigned int OnAuthClient(struct adapter *padapter, u8 *pframe = precv_frame->pkt->data; uint pkt_len = precv_frame->pkt->len; - DBG_88E("%s\n", __func__); - /* check A1 matches or not */ if (memcmp(myid(&padapter->eeprompriv), ieee80211_get_DA((struct ieee80211_hdr *)pframe), ETH_ALEN)) return _SUCCESS; @@ -2831,7 +2682,6 @@ static unsigned int OnAuthClient(struct adapter *padapter, status = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 4)); if (status != 0) { - DBG_88E("clnt auth fail, status: %d\n", status); if (status == 13) { /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */ if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; @@ -2872,7 +2722,6 @@ static unsigned int OnAuthClient(struct adapter *padapter, } if (go2asoc) { - DBG_88E_LEVEL(_drv_info_, "auth success, start assoc\n"); start_clnt_assoc(padapter); return _SUCCESS; } @@ -2887,7 +2736,7 @@ static unsigned int OnAssocReq(struct adapter *padapter, u16 capab_info; struct rtw_ieee802_11_elems elems; struct sta_info *pstat; - unsigned char reassoc, *p, *pos, *wpa_ie; + unsigned char *p, *pos, *wpa_ie; unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; int i, wpa_ie_len, left; unsigned char supportRate[16]; @@ -2907,19 +2756,13 @@ static unsigned int OnAssocReq(struct adapter *padapter, return _FAIL; frame_type = GetFrameSubType(pframe); - if (frame_type == WIFI_ASSOCREQ) { - reassoc = 0; + if (frame_type == IEEE80211_STYPE_ASSOC_REQ) ie_offset = _ASOCREQ_IE_OFFSET_; - } else { /* WIFI_REASSOCREQ */ - reassoc = 1; + else /* IEEE80211_STYPE_REASSOC_REQ */ ie_offset = _REASOCREQ_IE_OFFSET_; - } - if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset) { - DBG_88E("handle_assoc(reassoc=%d) - too short payload (len=%lu)" - "\n", reassoc, (unsigned long)pkt_len); + if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset) return _FAIL; - } pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); if (!pstat) { @@ -2932,8 +2775,6 @@ static unsigned int OnAssocReq(struct adapter *padapter, left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset); pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset); - DBG_88E("%s\n", __func__); - /* check if this stat has been successfully authenticated/assocated */ if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) { if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) { @@ -2951,8 +2792,6 @@ static unsigned int OnAssocReq(struct adapter *padapter, /* now parse all ieee802_11 ie to point to elems */ if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed || !elems.ssid) { - DBG_88E("STA %pM sent invalid association request\n", - pstat->hwaddr); status = WLAN_STATUS_UNSPECIFIED_FAILURE; goto OnAssocReqFail; } @@ -2981,7 +2820,6 @@ static unsigned int OnAssocReq(struct adapter *padapter, /* check if the supported rate is ok */ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_SUPP_RATES, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); if (!p) { - DBG_88E("Rx a sta assoc-req which supported rate is empty!\n"); /* use our own rate set as statoin used */ /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */ /* supportRateNum = AP_BSSRATE_LEN; */ @@ -3072,17 +2910,11 @@ static unsigned int OnAssocReq(struct adapter *padapter, pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); if (!wpa_ie) { if (elems.wps_ie) { - DBG_88E("STA included WPS IE in " - "(Re)Association Request - assume WPS is " - "used\n"); pstat->flags |= WLAN_STA_WPS; /* wpabuf_free(sta->wps_ie); */ /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */ /* elems.wps_ie_len - 4); */ } else { - DBG_88E("STA did not include WPA/RSN IE " - "in (Re)Association Request - possible WPS " - "use\n"); pstat->flags |= WLAN_STA_MAYBE_WPS; } @@ -3095,8 +2927,6 @@ static unsigned int OnAssocReq(struct adapter *padapter, rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL); if (!selected_registrar) { - DBG_88E("selected_registrar is false , or AP is not ready to do WPS\n"); - status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; goto OnAssocReqFail; @@ -3107,18 +2937,12 @@ static unsigned int OnAssocReq(struct adapter *padapter, int copy_len; if (psecuritypriv->wpa_psk == 0) { - DBG_88E("STA %pM: WPA/RSN IE in association " - "request, but AP don't support WPA/RSN\n", pstat->hwaddr); - status = WLAN_STATUS_INVALID_IE; goto OnAssocReqFail; } if (elems.wps_ie) { - DBG_88E("STA included WPS IE in " - "(Re)Association Request - WPS is " - "used\n"); pstat->flags |= WLAN_STA_WPS; copy_len = 0; } else { @@ -3202,16 +3026,6 @@ static unsigned int OnAssocReq(struct adapter *padapter, goto OnAssocReqFail; } - if ((pstat->flags & WLAN_STA_HT) && - ((pstat->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) || - (pstat->wpa_pairwise_cipher & WPA_CIPHER_TKIP))) { - DBG_88E("HT: %pM tried to " - "use TKIP with HT association\n", pstat->hwaddr); - - /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */ - /* goto OnAssocReqFail; */ - } - pstat->flags |= WLAN_STA_NONERP; for (i = 0; i < pstat->bssratelen; i++) { if ((pstat->bssrateset[i] & 0x7f) > 22) { @@ -3235,9 +3049,7 @@ static unsigned int OnAssocReq(struct adapter *padapter, /* Customer proprietary IE */ /* get a unique AID */ - if (pstat->aid > 0) { - DBG_88E(" old AID %d\n", pstat->aid); - } else { + if (pstat->aid <= 0) { for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++) if (!pstapriv->sta_aid[pstat->aid - 1]) break; @@ -3246,14 +3058,11 @@ static unsigned int OnAssocReq(struct adapter *padapter, if (pstat->aid > pstapriv->max_num_sta) { pstat->aid = 0; - DBG_88E(" no room for more AIDs\n"); - status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; goto OnAssocReqFail; } else { pstapriv->sta_aid[pstat->aid - 1] = pstat; - DBG_88E("allocate new AID=(%d)\n", pstat->aid); } } @@ -3282,13 +3091,12 @@ static unsigned int OnAssocReq(struct adapter *padapter, sta_info_update(padapter, pstat); /* issue assoc rsp before notify station join event. */ - if (frame_type == WIFI_ASSOCREQ) - issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP); + if (frame_type == IEEE80211_STYPE_ASSOC_REQ) + issue_asocrsp(padapter, status, pstat, IEEE80211_STYPE_ASSOC_RESP); else - issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP); + issue_asocrsp(padapter, status, pstat, IEEE80211_STYPE_REASSOC_RESP); /* 2 - report to upper layer */ - DBG_88E("indicate_sta_join_event to upper layer - hostapd\n"); rtw_indicate_sta_assoc_event(padapter, pstat); /* 3-(1) report sta add event */ @@ -3306,10 +3114,10 @@ asoc_class2_error: OnAssocReqFail: pstat->aid = 0; - if (frame_type == WIFI_ASSOCREQ) - issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP); + if (frame_type == IEEE80211_STYPE_ASSOC_REQ) + issue_asocrsp(padapter, status, pstat, IEEE80211_STYPE_ASSOC_RESP); else - issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP); + issue_asocrsp(padapter, status, pstat, IEEE80211_STYPE_REASSOC_RESP); #endif /* CONFIG_88EU_AP_MODE */ @@ -3329,8 +3137,6 @@ static unsigned int OnAssocRsp(struct adapter *padapter, u8 *pframe = precv_frame->pkt->data; uint pkt_len = precv_frame->pkt->len; - DBG_88E("%s\n", __func__); - /* check A1 matches or not */ if (memcmp(myid(&padapter->eeprompriv), ieee80211_get_DA((struct ieee80211_hdr *)pframe), ETH_ALEN)) return _SUCCESS; @@ -3346,7 +3152,6 @@ static unsigned int OnAssocRsp(struct adapter *padapter, /* status */ status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2)); if (status > 0) { - DBG_88E("assoc reject, status code: %d\n", status); pmlmeinfo->state = WIFI_FW_NULL_STATE; res = -4; goto report_assoc_result; @@ -3381,6 +3186,7 @@ static unsigned int OnAssocRsp(struct adapter *padapter, break; case WLAN_EID_ERP_INFO: ERP_IE_handler(padapter, pIE); + break; default: break; } @@ -3420,16 +3226,11 @@ static unsigned int OnDeAuth(struct adapter *padapter, reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); - DBG_88E("%s Reason code(%d)\n", __func__, reason); - #ifdef CONFIG_88EU_AP_MODE if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { struct sta_info *psta; struct sta_priv *pstapriv = &padapter->stapriv; - DBG_88E_LEVEL(_drv_always_, "ap recv deauth reason code(%d) sta:%pM\n", - reason, GetAddr2Ptr(pframe)); - psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); if (psta) { u8 updated = 0; @@ -3448,9 +3249,6 @@ static unsigned int OnDeAuth(struct adapter *padapter, return _SUCCESS; } #endif - DBG_88E_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM\n", - reason, GetAddr3Ptr(pframe)); - receive_disconnect(padapter, GetAddr3Ptr(pframe), reason); pmlmepriv->LinkDetectInfo.bBusyTraffic = false; @@ -3473,16 +3271,11 @@ static unsigned int OnDisassoc(struct adapter *padapter, reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); - DBG_88E("%s Reason code(%d)\n", __func__, reason); - #ifdef CONFIG_88EU_AP_MODE if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { struct sta_info *psta; struct sta_priv *pstapriv = &padapter->stapriv; - DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n", - reason, GetAddr2Ptr(pframe)); - psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); if (psta) { u8 updated = 0; @@ -3501,9 +3294,6 @@ static unsigned int OnDisassoc(struct adapter *padapter, return _SUCCESS; } #endif - DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n", - reason, GetAddr3Ptr(pframe)); - receive_disconnect(padapter, GetAddr3Ptr(pframe), reason); pmlmepriv->LinkDetectInfo.bBusyTraffic = false; @@ -3513,7 +3303,6 @@ static unsigned int OnDisassoc(struct adapter *padapter, static unsigned int OnAtim(struct adapter *padapter, struct recv_frame *precv_frame) { - DBG_88E("%s\n", __func__); return _SUCCESS; } @@ -3527,8 +3316,6 @@ static unsigned int on_action_spct(struct adapter *padapter, u8 category; u8 action; - DBG_88E(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev)); - psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); if (!psta) @@ -3575,7 +3362,7 @@ static unsigned int OnAction_back(struct adapter *padapter, struct recv_reorder_ctrl *preorder_ctrl; unsigned char *frame_body; unsigned char category, action; - unsigned short tid, status, reason_code = 0; + unsigned short tid, status; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; u8 *pframe = precv_frame->pkt->data; @@ -3586,8 +3373,6 @@ static unsigned int OnAction_back(struct adapter *padapter, ETH_ALEN))/* for if1, sta/ap mode */ return _SUCCESS; - DBG_88E("%s\n", __func__); - if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE) if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) return _SUCCESS; @@ -3605,40 +3390,36 @@ static unsigned int OnAction_back(struct adapter *padapter, if (!pmlmeinfo->HT_enable) return _SUCCESS; action = frame_body[1]; - DBG_88E("%s, action=%d\n", __func__, action); switch (action) { - case RTW_WLAN_ACTION_ADDBA_REQ: /* ADDBA request */ + case WLAN_ACTION_ADDBA_REQ: memcpy(&pmlmeinfo->ADDBA_req, &frame_body[2], sizeof(struct ADDBA_request)); process_addba_req(padapter, (u8 *)&pmlmeinfo->ADDBA_req, addr); /* 37 = reject ADDBA Req */ issue_action_BA(padapter, addr, - RTW_WLAN_ACTION_ADDBA_RESP, + WLAN_ACTION_ADDBA_RESP, pmlmeinfo->accept_addba_req ? 0 : 37); break; - case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */ + case WLAN_ACTION_ADDBA_RESP: status = get_unaligned_le16(&frame_body[3]); tid = (frame_body[5] >> 2) & 0x7; if (status == 0) { /* successful */ - DBG_88E("agg_enable for TID=%d\n", tid); psta->htpriv.agg_enable_bitmap |= 1 << tid; psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); } else { psta->htpriv.agg_enable_bitmap &= ~BIT(tid); } break; - case RTW_WLAN_ACTION_DELBA: /* DELBA */ + case WLAN_ACTION_DELBA: if ((frame_body[3] & BIT(3)) == 0) { psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf)); psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf)); - reason_code = get_unaligned_le16(&frame_body[4]); } else if ((frame_body[3] & BIT(3)) == BIT(3)) { tid = (frame_body[3] >> 4) & 0x0F; preorder_ctrl = &psta->recvreorder_ctrl[tid]; preorder_ctrl->enable = false; preorder_ctrl->indicate_seq = 0xffff; } - DBG_88E("%s(): DELBA: %x(%x)\n", __func__, pmlmeinfo->agg_enable_bitmap, reason_code); /* todo: how to notify the host while receiving DELETE BA */ break; default: @@ -3658,17 +3439,11 @@ static s32 rtw_action_public_decache(struct recv_frame *recv_frame, s32 token) if (GetRetry(frame)) { if (token >= 0) { - if ((seq_ctrl == mlmeext->action_public_rxseq) && (token == mlmeext->action_public_dialog_token)) { - DBG_88E(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x, token:%d\n", - FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token); + if ((seq_ctrl == mlmeext->action_public_rxseq) && (token == mlmeext->action_public_dialog_token)) return _FAIL; - } } else { - if (seq_ctrl == mlmeext->action_public_rxseq) { - DBG_88E(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x\n", - FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq); + if (seq_ctrl == mlmeext->action_public_rxseq) return _FAIL; - } } } @@ -3822,20 +3597,20 @@ Following are the initialization functions for WiFi MLME *****************************************************************************/ static struct mlme_handler mlme_sta_tbl[] = { - {WIFI_ASSOCREQ, "OnAssocReq", &OnAssocReq}, - {WIFI_ASSOCRSP, "OnAssocRsp", &OnAssocRsp}, - {WIFI_REASSOCREQ, "OnReAssocReq", &OnAssocReq}, - {WIFI_REASSOCRSP, "OnReAssocRsp", &OnAssocRsp}, - {WIFI_PROBEREQ, "OnProbeReq", &OnProbeReq}, - {WIFI_PROBERSP, "OnProbeRsp", &OnProbeRsp}, - {0, "DoReserved", &DoReserved}, - {0, "DoReserved", &DoReserved}, - {WIFI_BEACON, "OnBeacon", &OnBeacon}, - {WIFI_ATIM, "OnATIM", &OnAtim}, - {WIFI_DISASSOC, "OnDisassoc", &OnDisassoc}, - {WIFI_AUTH, "OnAuth", &OnAuthClient}, - {WIFI_DEAUTH, "OnDeAuth", &OnDeAuth}, - {WIFI_ACTION, "OnAction", &OnAction}, + {IEEE80211_STYPE_ASSOC_REQ, "OnAssocReq", &OnAssocReq}, + {IEEE80211_STYPE_ASSOC_RESP, "OnAssocRsp", &OnAssocRsp}, + {IEEE80211_STYPE_REASSOC_REQ, "OnReAssocReq", &OnAssocReq}, + {IEEE80211_STYPE_REASSOC_RESP, "OnReAssocRsp", &OnAssocRsp}, + {IEEE80211_STYPE_PROBE_REQ, "OnProbeReq", &OnProbeReq}, + {IEEE80211_STYPE_PROBE_RESP, "OnProbeRsp", &OnProbeRsp}, + {0, "DoReserved", &DoReserved}, + {0, "DoReserved", &DoReserved}, + {IEEE80211_STYPE_BEACON, "OnBeacon", &OnBeacon}, + {IEEE80211_STYPE_ATIM, "OnATIM", &OnAtim}, + {IEEE80211_STYPE_DISASSOC, "OnDisassoc", &OnDisassoc}, + {IEEE80211_STYPE_AUTH, "OnAuth", &OnAuthClient}, + {IEEE80211_STYPE_DEAUTH, "OnDeAuth", &OnDeAuth}, + {IEEE80211_STYPE_ACTION, "OnAction", &OnAction}, }; int init_hw_mlme_ext(struct adapter *padapter) @@ -3971,10 +3746,8 @@ static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, memset(channel_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM); - if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) { - DBG_88E("ChannelPlan ID %x error !!!!!\n", ChannelPlan); + if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) return chanset_size; - } if (padapter->registrypriv.wireless_mode & WIRELESS_11G) { b2_4GBand = true; @@ -4017,8 +3790,6 @@ int init_mlme_ext_priv(struct adapter *padapter) struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - pmlmeext->padapter = padapter; - init_mlme_ext_priv_value(padapter); pmlmeinfo->accept_addba_req = pregistrypriv->accept_addba_req; @@ -4041,10 +3812,7 @@ int init_mlme_ext_priv(struct adapter *padapter) void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext) { - struct adapter *padapter = pmlmeext->padapter; - - if (!padapter) - return; + struct adapter *padapter = container_of(pmlmeext, struct adapter, mlmeextpriv); if (padapter->bDriverStopped) { del_timer_sync(&pmlmeext->survey_timer); @@ -4056,13 +3824,12 @@ static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptable, struct recv_frame *precv_frame) { - u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; u8 *pframe = precv_frame->pkt->data; if (ptable->func) { /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */ if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) && - memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) + !is_broadcast_ether_addr(GetAddr1Ptr(pframe))) return; ptable->func(padapter, precv_frame); } @@ -4075,63 +3842,48 @@ void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame) #ifdef CONFIG_88EU_AP_MODE struct mlme_priv *pmlmepriv = &padapter->mlmepriv; #endif - u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; u8 *pframe = precv_frame->pkt->data; struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe)); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("+%s: type(0x%x) subtype(0x%x)\n", __func__, - (unsigned int)GetFrameType(pframe), - (unsigned int)GetFrameSubType(pframe))); - - if (GetFrameType(pframe) != WIFI_MGT_TYPE) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - ("%s: type(0x%x) error!\n", __func__, - (unsigned int)GetFrameType(pframe))); + if (GetFrameType(pframe) != WIFI_MGT_TYPE) return; - } /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */ if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) && - memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) + !is_broadcast_ether_addr(GetAddr1Ptr(pframe))) return; ptable = mlme_sta_tbl; index = GetFrameSubType(pframe) >> 4; - if (index > 13) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Currently we do not support reserved sub-fr-type=%d\n", index)); + if (index > 13) return; - } ptable += index; if (psta) { if (GetRetry(pframe)) { if (precv_frame->attrib.seq_num == - psta->RxMgmtFrameSeqNum) { + psta->RxMgmtFrameSeqNum) /* drop the duplicate management frame */ - DBG_88E("Drop duplicate management frame with seq_num=%d.\n", - precv_frame->attrib.seq_num); return; - } } psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num; } #ifdef CONFIG_88EU_AP_MODE switch (GetFrameSubType(pframe)) { - case WIFI_AUTH: + case IEEE80211_STYPE_AUTH: if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) ptable->func = &OnAuth; else ptable->func = &OnAuthClient; fallthrough; - case WIFI_ASSOCREQ: - case WIFI_REASSOCREQ: - case WIFI_PROBEREQ: - case WIFI_BEACON: - case WIFI_ACTION: + case IEEE80211_STYPE_ASSOC_REQ: + case IEEE80211_STYPE_REASSOC_REQ: + case IEEE80211_STYPE_PROBE_REQ: + case IEEE80211_STYPE_BEACON: + case IEEE80211_STYPE_ACTION: _mgt_dispatcher(padapter, ptable, precv_frame); break; default: @@ -4244,8 +3996,6 @@ void report_surveydone_event(struct adapter *padapter) psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt; - DBG_88E("survey done event(%x)\n", psurveydone_evt->bss_cnt); - rtw_enqueue_cmd(pcmdpriv, pcmd_obj); } @@ -4290,8 +4040,6 @@ void report_join_res(struct adapter *padapter, int res) pjoinbss_evt->network.join_res = res; pjoinbss_evt->network.aid = res; - DBG_88E("%s(%d)\n", __func__, res); - rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network); rtw_enqueue_cmd(pcmdpriv, pcmd_obj); @@ -4347,8 +4095,6 @@ void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, pdel_sta_evt->mac_id = mac_id; - DBG_88E("%s: delete STA, mac_id =%d\n", __func__, mac_id); - rtw_enqueue_cmd(pcmdpriv, pcmd_obj); } @@ -4392,8 +4138,6 @@ void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, ether_addr_copy((unsigned char *)(&padd_sta_evt->macaddr), MacAddr); padd_sta_evt->cam_id = cam_idx; - DBG_88E("%s: add STA\n", __func__); - rtw_enqueue_cmd(pcmdpriv, pcmd_obj); } @@ -4462,7 +4206,7 @@ void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res) /* restore to initial setting. */ update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode); - goto exit_mlmeext_joinbss_event_callback; + return; } if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) { @@ -4518,10 +4262,6 @@ void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res) correct_TSF(padapter, pmlmeext); } rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0); - -exit_mlmeext_joinbss_event_callback: - - DBG_88E("=>%s\n", __func__); } void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta) @@ -4530,8 +4270,6 @@ void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *p struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; u8 join_type; - DBG_88E("%s\n", __func__); - if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) { if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {/* adhoc master or sta_count>1 */ /* nothing to do */ @@ -4683,8 +4421,6 @@ void linked_status_chk(struct adapter *padapter) if (rx_chk == _FAIL) { pmlmeext->retry++; if (pmlmeext->retry > rx_chk_limit) { - DBG_88E_LEVEL(_drv_always_, FUNC_ADPT_FMT" disconnect or roaming\n", - FUNC_ADPT_ARG(padapter)); receive_disconnect(padapter, pmlmeinfo->network.MacAddress, WLAN_REASON_EXPIRATION_CHK); return; @@ -4744,8 +4480,6 @@ void survey_timer_hdl(struct timer_list *t) if (pmlmeext->scan_abort) { pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num; - DBG_88E("%s idx:%d\n", __func__ - , pmlmeext->sitesurvey_res.channel_idx); pmlmeext->scan_abort = false;/* reset */ } @@ -4776,7 +4510,6 @@ void link_timer_hdl(struct timer_list *t) struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { - DBG_88E("%s:no beacon while connecting\n", __func__); pmlmeinfo->state = WIFI_FW_NULL_STATE; report_join_res(padapter, -3); } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) { @@ -4787,7 +4520,6 @@ void link_timer_hdl(struct timer_list *t) return; } - DBG_88E("%s: auth timeout and try again\n", __func__); pmlmeinfo->auth_seq = 1; issue_auth(padapter, NULL, 0); set_link_timer(pmlmeext, REAUTH_TO); @@ -4799,7 +4531,6 @@ void link_timer_hdl(struct timer_list *t) return; } - DBG_88E("%s: assoc timeout and try again\n", __func__); issue_assocreq(padapter); set_link_timer(pmlmeext, REASSOC_TO); } @@ -4991,9 +4722,8 @@ u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf) default: pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; break; - } + } - DBG_88E("set ch/bw before connected\n"); } } break; @@ -5204,8 +4934,6 @@ u8 setkey_hdl(struct adapter *padapter, u8 *pbuf) /* write cam */ ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid; - DBG_88E_LEVEL(_drv_info_, "set group key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) " - "keyid:%d\n", pparm->algorithm, pparm->keyid); write_cam(padapter, pparm->keyid, ctrl, null_sta, pparm->key); return H2C_SUCCESS; @@ -5234,8 +4962,6 @@ u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf) cam_id = 4; - DBG_88E_LEVEL(_drv_info_, "set pairwise key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) camid:%d\n", - pparm->algorithm, cam_id); if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { struct sta_info *psta; struct sta_priv *pstapriv = &padapter->stapriv; @@ -5249,24 +4975,16 @@ u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf) if (psta) { ctrl = BIT(15) | ((pparm->algorithm) << 2); - DBG_88E("r871x_set_stakey_hdl(): enc_algorithm=%d\n", pparm->algorithm); - - if ((psta->mac_id < 1) || (psta->mac_id > (NUM_STA - 4))) { - DBG_88E("r871x_set_stakey_hdl():set_stakey failed, mac_id(aid)=%d\n", psta->mac_id); + if ((psta->mac_id < 1) || (psta->mac_id > (NUM_STA - 4))) return H2C_REJECTED; - } cam_id = psta->mac_id + 3;/* 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */ - DBG_88E("Write CAM, mac_addr =%pM, cam_entry=%d\n", - pparm->addr, cam_id); - write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key); return H2C_SUCCESS_RSP; } - DBG_88E("r871x_set_stakey_hdl(): sta has been free\n"); return H2C_REJECTED; } @@ -5294,7 +5012,7 @@ u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf) if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) { - issue_action_BA(padapter, pparm->addr, RTW_WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid); + issue_action_BA(padapter, pparm->addr, WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid); mod_timer(&psta->addba_retry_timer, jiffies + msecs_to_jiffies(ADDBA_TO)); } else { @@ -5352,19 +5070,13 @@ u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf) evt_code = (u8)((*peventbuf >> 16) & 0xff); /* checking if event code is valid */ - if (evt_code >= MAX_C2HEVT) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent Code(%d) mismatch!\n", evt_code)); + if (evt_code >= MAX_C2HEVT) goto _abort_event_; - } /* checking if event size match the event parm size */ if ((wlanevents[evt_code].parmsize != 0) && - (wlanevents[evt_code].parmsize != evt_sz)) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - ("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n", - evt_code, wlanevents[evt_code].parmsize, evt_sz)); + (wlanevents[evt_code].parmsize != evt_sz)) goto _abort_event_; - } peventbuf += 2; @@ -5379,15 +5091,13 @@ _abort_event_: u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf) { - if (send_beacon(padapter) == _FAIL) { - DBG_88E("issue_beacon, fail!\n"); + if (send_beacon(padapter) == _FAIL) return H2C_PARAMETERS_ERROR; - } #ifdef CONFIG_88EU_AP_MODE else { /* tx bc/mc frames after update TIM */ struct sta_info *psta_bmc; - struct list_head *xmitframe_plist, *xmitframe_phead; - struct xmit_frame *pxmitframe = NULL; + struct list_head *xmitframe_phead; + struct xmit_frame *pxmitframe, *n; struct sta_priv *pstapriv = &padapter->stapriv; /* for BC/MC Frames */ @@ -5400,13 +5110,8 @@ u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf) spin_lock_bh(&psta_bmc->sleep_q.lock); xmitframe_phead = get_list_head(&psta_bmc->sleep_q); - xmitframe_plist = xmitframe_phead->next; - - while (xmitframe_phead != xmitframe_plist) { - pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list); - - xmitframe_plist = xmitframe_plist->next; - + list_for_each_entry_safe(pxmitframe, n, xmitframe_phead, + list) { list_del_init(&pxmitframe->list); psta_bmc->sleepq_len--; @@ -5441,10 +5146,6 @@ u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf) set_ch_parm = (struct set_ch_parm *)pbuf; - DBG_88E(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n", - FUNC_NDEV_ARG(padapter->pnetdev), - set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset); - pmlmeext->cur_channel = set_ch_parm->ch; pmlmeext->cur_ch_offset = set_ch_parm->ch_offset; pmlmeext->cur_bwmode = set_ch_parm->bw; diff --git a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c index 4d507d9faec2..cbb34b920ab9 100644 --- a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c +++ b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c @@ -18,17 +18,12 @@ static int rtw_hw_suspend(struct adapter *padapter) struct net_device *pnetdev = padapter->pnetdev; if ((!padapter->bup) || (padapter->bDriverStopped) || - (padapter->bSurpriseRemoved)) { - DBG_88E("padapter->bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n", - padapter->bup, padapter->bDriverStopped, - padapter->bSurpriseRemoved); + (padapter->bSurpriseRemoved)) goto error_exit; - } /* system suspend */ LeaveAllPowerSaveMode(padapter); - DBG_88E("==> %s\n", __func__); mutex_lock(&pwrpriv->mutex_lock); pwrpriv->bips_processing = true; /* s1. */ @@ -69,7 +64,6 @@ static int rtw_hw_suspend(struct adapter *padapter) return 0; error_exit: - DBG_88E("%s, failed\n", __func__); return -1; } @@ -79,7 +73,6 @@ static int rtw_hw_resume(struct adapter *padapter) struct net_device *pnetdev = padapter->pnetdev; /* system resume */ - DBG_88E("==> %s\n", __func__); mutex_lock(&pwrpriv->mutex_lock); pwrpriv->bips_processing = true; rtw_reset_drv_sw(padapter); @@ -107,7 +100,6 @@ static int rtw_hw_resume(struct adapter *padapter) return 0; error_exit: - DBG_88E("%s, Open net dev failed\n", __func__); return -1; } @@ -120,12 +112,8 @@ void ips_enter(struct adapter *padapter) return; if (pxmit_priv->free_xmitbuf_cnt != NR_XMITBUFF || - pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) { - DBG_88E_LEVEL(_drv_info_, "There are some pkts to transmit\n"); - DBG_88E_LEVEL(_drv_info_, "free_xmitbuf_cnt: %d, free_xmit_extbuf_cnt: %d\n", - pxmit_priv->free_xmitbuf_cnt, pxmit_priv->free_xmit_extbuf_cnt); + pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) return; - } mutex_lock(&pwrpriv->mutex_lock); @@ -135,10 +123,8 @@ void ips_enter(struct adapter *padapter) pwrpriv->ips_mode = pwrpriv->ips_mode_req; pwrpriv->ips_enter_cnts++; - DBG_88E("==>%s:%d\n", __func__, pwrpriv->ips_enter_cnts); if (rf_off == pwrpriv->change_rfpwrstate) { pwrpriv->bpower_saving = true; - DBG_88E_LEVEL(_drv_info_, "nolinked power save enter\n"); if (pwrpriv->ips_mode == IPS_LEVEL_2) pwrpriv->bkeepfwalive = true; @@ -165,16 +151,12 @@ int ips_leave(struct adapter *padapter) pwrpriv->bips_processing = true; pwrpriv->change_rfpwrstate = rf_on; pwrpriv->ips_leave_cnts++; - DBG_88E("==>%s:%d\n", __func__, pwrpriv->ips_leave_cnts); result = rtw_ips_pwr_up(padapter); if (result == _SUCCESS) pwrpriv->rf_pwrstate = rf_on; - DBG_88E_LEVEL(_drv_info_, "nolinked power save leave\n"); - if ((psecuritypriv->dot11PrivacyAlgrthm == _WEP40_) || (psecuritypriv->dot11PrivacyAlgrthm == _WEP104_)) { - DBG_88E("==>%s, channel(%d), processing(%x)\n", __func__, padapter->mlmeextpriv.cur_channel, pwrpriv->bips_processing); set_channel_bwmode(padapter, padapter->mlmeextpriv.cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); for (keyid = 0; keyid < 4; keyid++) { if (pmlmepriv->key_mask & BIT(keyid)) { @@ -186,7 +168,6 @@ int ips_leave(struct adapter *padapter) } } - DBG_88E("==> %s.....LED(0x%08x)...\n", __func__, usb_read32(padapter, 0x4c)); pwrpriv->bips_processing = false; pwrpriv->bkeepfwalive = false; @@ -217,7 +198,6 @@ static bool rtw_pwr_unassociated_idle(struct adapter *adapter) void rtw_ps_processor(struct adapter *padapter) { struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; enum rt_rf_power_state rfpwrstate; pwrpriv->ps_processing = true; @@ -227,7 +207,6 @@ void rtw_ps_processor(struct adapter *padapter) if (padapter->pwrctrlpriv.bHWPwrPindetect) { rfpwrstate = RfOnOffDetect(padapter); - DBG_88E("@@@@- #2 %s==> rfstate:%s\n", __func__, (rfpwrstate == rf_on) ? "rf_on" : "rf_off"); if (rfpwrstate != pwrpriv->rf_pwrstate) { if (rfpwrstate == rf_off) { @@ -238,7 +217,6 @@ void rtw_ps_processor(struct adapter *padapter) pwrpriv->change_rfpwrstate = rf_on; rtw_hw_resume(padapter); } - DBG_88E("current rf_pwrstate(%s)\n", (pwrpriv->rf_pwrstate == rf_off) ? "rf_off" : "rf_on"); } pwrpriv->pwr_state_check_cnts++; } @@ -250,7 +228,6 @@ void rtw_ps_processor(struct adapter *padapter) goto exit; if ((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts % 4) == 0)) { - DBG_88E("==>%s .fw_state(%x)\n", __func__, get_fwstate(pmlmepriv)); pwrpriv->change_rfpwrstate = rf_off; ips_enter(padapter); @@ -288,37 +265,22 @@ void rtw_set_rpwm(struct adapter *padapter, u8 pslv) pslv = PS_STATE_S3; } - if (pwrpriv->rpwm == pslv) { - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, - ("%s: Already set rpwm[0x%02X], new=0x%02X!\n", __func__, pwrpriv->rpwm, pslv)); + if (pwrpriv->rpwm == pslv) return; - } if ((padapter->bSurpriseRemoved) || (!padapter->hw_init_completed)) { - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, - ("%s: SurpriseRemoved(%d) hw_init_completed(%d)\n", - __func__, padapter->bSurpriseRemoved, padapter->hw_init_completed)); - pwrpriv->cpwm = PS_STATE_S4; return; } if (padapter->bDriverStopped) { - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, - ("%s: change power state(0x%02X) when DriverStopped\n", __func__, pslv)); - - if (pslv < PS_STATE_S2) { - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, - ("%s: Reject to enter PS_STATE(0x%02X) lower than S2 when DriverStopped!!\n", __func__, pslv)); + if (pslv < PS_STATE_S2) return; - } } rpwm = pslv | pwrpriv->tog; - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, - ("%s: rpwm=0x%02x cpwm=0x%02x\n", __func__, rpwm, pwrpriv->cpwm)); pwrpriv->rpwm = pslv; @@ -349,10 +311,8 @@ static u8 PS_RDY_CHECK(struct adapter *padapter) if (pwrpriv->bInSuspend) return false; if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && - !padapter->securitypriv.binstallGrpkey) { - DBG_88E("Group handshake still in progress !!!\n"); + !padapter->securitypriv.binstallGrpkey) return false; - } return true; } @@ -360,14 +320,8 @@ void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_a { struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, - ("%s: PowerMode=%d Smart_PS=%d\n", - __func__, ps_mode, smart_ps)); - - if (ps_mode > PM_Card_Disable) { - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("ps_mode:%d error\n", ps_mode)); + if (ps_mode > PM_Card_Disable) return; - } if (pwrpriv->pwr_mode == ps_mode) { if (ps_mode == PS_MODE_ACTIVE) @@ -381,7 +335,6 @@ void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_a /* if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) */ if (ps_mode == PS_MODE_ACTIVE) { if (PS_RDY_CHECK(padapter)) { - DBG_88E("%s: Enter 802.11 power save\n", __func__); pwrpriv->bFwCurrentInPSMode = true; pwrpriv->pwr_mode = ps_mode; pwrpriv->smart_ps = smart_ps; @@ -412,13 +365,11 @@ s32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms) if (padapter->bSurpriseRemoved) { err = -2; - DBG_88E("%s: device surprise removed!!\n", __func__); break; } if (jiffies_to_msecs(jiffies - start_time) > delay_ms) { err = -1; - DBG_88E("%s: Wait for FW LPS leave more than %u ms!!!\n", __func__, delay_ms); break; } msleep(1); @@ -443,7 +394,6 @@ void LPS_Enter(struct adapter *padapter) if (pwrpriv->LpsIdleCount >= 2) { /* 4 Sec */ if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) { pwrpriv->bpower_saving = true; - DBG_88E("%s smart_ps:%d\n", __func__, pwrpriv->smart_ps); /* For Tenda W311R IOT issue */ rtw_set_ps_mode(padapter, pwrpriv->power_mgnt, pwrpriv->smart_ps, 0); } @@ -549,14 +499,9 @@ int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *cal start = jiffies; if (pwrpriv->ps_processing) { - DBG_88E("%s wait ps_processing...\n", __func__); while (pwrpriv->ps_processing && jiffies_to_msecs(jiffies - start) <= 3000) udelay(1500); - if (pwrpriv->ps_processing) - DBG_88E("%s wait ps_processing timeout\n", __func__); - else - DBG_88E("%s wait ps_processing done\n", __func__); } /* System suspend is not allowed to wakeup */ @@ -577,9 +522,7 @@ int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *cal goto exit; } if (rf_off == pwrpriv->rf_pwrstate) { - DBG_88E("%s call ips_leave....\n", __func__); if (ips_leave(padapter) == _FAIL) { - DBG_88E("======> ips_leave fail.............\n"); ret = _FAIL; goto exit; } @@ -588,11 +531,6 @@ int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *cal /* TODO: the following checking need to be merged... */ if (padapter->bDriverStopped || !padapter->bup || !padapter->hw_init_completed) { - DBG_88E("%s: bDriverStopped=%d, bup=%d, hw_init_completed =%u\n" - , caller - , padapter->bDriverStopped - , padapter->bup - , padapter->hw_init_completed); ret = false; goto exit; } @@ -631,11 +569,9 @@ int rtw_pm_set_ips(struct adapter *padapter, u8 mode) if (mode == IPS_NORMAL || mode == IPS_LEVEL_2) { rtw_ips_mode_req(pwrctrlpriv, mode); - DBG_88E("%s %s\n", __func__, mode == IPS_NORMAL ? "IPS_NORMAL" : "IPS_LEVEL_2"); return 0; } else if (mode == IPS_NONE) { rtw_ips_mode_req(pwrctrlpriv, mode); - DBG_88E("%s %s\n", __func__, "IPS_NONE"); if ((padapter->bSurpriseRemoved == 0) && (rtw_pwr_wakeup(padapter) == _FAIL)) return -EFAULT; } else { diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index b2fe448d999d..ff2ef36604e1 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -7,6 +7,7 @@ #define _RTW_RECV_C_ #include <linux/ieee80211.h> +#include <linux/if_ether.h> #include <osdep_service.h> #include <drv_types.h> @@ -15,9 +16,9 @@ #include <mon.h> #include <wifi.h> #include <linux/vmalloc.h> +#include <linux/etherdevice.h> #include <net/cfg80211.h> -#define ETHERNET_HEADER_SIZE 14 /* Ethernet Header Length */ #define LLC_HEADER_SIZE 6 /* LLC Header Length */ static u8 SNAP_ETH_TYPE_IPX[2] = {0x81, 0x37}; @@ -114,11 +115,11 @@ struct recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue) return precvframe; } -int rtw_free_recvframe(struct recv_frame *precvframe, - struct __queue *pfree_recv_queue) +void rtw_free_recvframe(struct recv_frame *precvframe, struct __queue *pfree_recv_queue) { if (!precvframe) - return _FAIL; + return; + if (precvframe->pkt) { dev_kfree_skb_any(precvframe->pkt);/* free skb by driver */ precvframe->pkt = NULL; @@ -131,8 +132,6 @@ int rtw_free_recvframe(struct recv_frame *precvframe, list_add_tail(&precvframe->list, get_list_head(pfree_recv_queue)); spin_unlock_bh(&pfree_recv_queue->lock); - - return _SUCCESS; } int _rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue) @@ -190,7 +189,6 @@ u32 rtw_free_uc_swdec_pending_queue(struct adapter *adapter) while ((pending_frame = rtw_alloc_recvframe(&adapter->recvpriv.uc_swdec_pending_queue))) { rtw_free_recvframe(pending_frame, &adapter->recvpriv.free_recv_queue); - DBG_88E("%s: dequeue uc_swdec_pending_queue\n", __func__); cnt++; } @@ -216,31 +214,16 @@ static int recvframe_chkmic(struct adapter *adapter, stainfo = rtw_get_stainfo(&adapter->stapriv, &prxattrib->ta[0]); if (prxattrib->encrypt == _TKIP_) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - ("\n %s: prxattrib->encrypt==_TKIP_\n", __func__)); - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - ("\n %s: da=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", - __func__, prxattrib->ra[0], prxattrib->ra[1], prxattrib->ra[2], - prxattrib->ra[3], prxattrib->ra[4], prxattrib->ra[5])); - /* calculate mic code */ if (stainfo) { if (is_multicast_ether_addr(prxattrib->ra)) { if (!psecuritypriv) { res = _FAIL; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - ("\n %s: didn't install group key!!!!!!!!!!\n", __func__)); - DBG_88E("\n %s: didn't install group key!!!!!!!!!!\n", __func__); goto exit; } mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0]; - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - ("\n %s: bcmc key\n", __func__)); } else { mickey = &stainfo->dot11tkiprxmickey.skey[0]; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - ("\n %s: unicast key\n", __func__)); } /* icv_len included the mic code */ @@ -249,7 +232,6 @@ static int recvframe_chkmic(struct adapter *adapter, pframe = precvframe->pkt->data; payload = pframe + prxattrib->hdrlen + prxattrib->iv_len; - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n prxattrib->iv_len=%d prxattrib->icv_len=%d\n", prxattrib->iv_len, prxattrib->icv_len)); rtw_seccalctkipmic(mickey, pframe, payload, datalen, &miccode[0], (unsigned char)prxattrib->priority); /* care the length of the data */ @@ -258,83 +240,25 @@ static int recvframe_chkmic(struct adapter *adapter, bmic_err = false; for (i = 0; i < 8; i++) { - if (miccode[i] != *(pframemic + i)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - ("%s: miccode[%d](%02x)!=*(pframemic+%d)(%02x) ", - __func__, i, miccode[i], i, *(pframemic + i))); + if (miccode[i] != *(pframemic + i)) bmic_err = true; - } } if (bmic_err) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - ("\n *(pframemic-8)-*(pframemic-1)=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", - *(pframemic - 8), *(pframemic - 7), *(pframemic - 6), - *(pframemic - 5), *(pframemic - 4), *(pframemic - 3), - *(pframemic - 2), *(pframemic - 1))); - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - ("\n *(pframemic-16)-*(pframemic-9)=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", - *(pframemic - 16), *(pframemic - 15), *(pframemic - 14), - *(pframemic - 13), *(pframemic - 12), *(pframemic - 11), - *(pframemic - 10), *(pframemic - 9))); - { - uint i; - - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - ("\n ======demp packet (len=%d)======\n", - precvframe->pkt->len)); - for (i = 0; i < precvframe->pkt->len; i += 8) { - RT_TRACE(_module_rtl871x_recv_c_, - _drv_err_, - ("0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x", - *(precvframe->pkt->data + i), - *(precvframe->pkt->data + i + 1), - *(precvframe->pkt->data + i + 2), - *(precvframe->pkt->data + i + 3), - *(precvframe->pkt->data + i + 4), - *(precvframe->pkt->data + i + 5), - *(precvframe->pkt->data + i + 6), - *(precvframe->pkt->data + i + 7))); - } - RT_TRACE(_module_rtl871x_recv_c_, - _drv_err_, - ("\n ====== demp packet end [len=%d]======\n", - precvframe->pkt->len)); - RT_TRACE(_module_rtl871x_recv_c_, - _drv_err_, - ("\n hrdlen=%d,\n", - prxattrib->hdrlen)); - } - - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - ("ra=0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x psecuritypriv->binstallGrpkey=%d ", - prxattrib->ra[0], prxattrib->ra[1], prxattrib->ra[2], - prxattrib->ra[3], prxattrib->ra[4], prxattrib->ra[5], psecuritypriv->binstallGrpkey)); - /* double check key_index for some timing issue , */ /* cannot compare with psecuritypriv->dot118021XGrpKeyid also cause timing issue */ if (is_multicast_ether_addr(prxattrib->ra) && prxattrib->key_index != pmlmeinfo->key_index) brpt_micerror = false; - if ((prxattrib->bdecrypted) && (brpt_micerror)) { + if ((prxattrib->bdecrypted) && (brpt_micerror)) rtw_handle_tkip_mic_err(adapter, (u8)is_multicast_ether_addr(prxattrib->ra)); - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" mic error :prxattrib->bdecrypted=%d ", prxattrib->bdecrypted)); - DBG_88E(" mic error :prxattrib->bdecrypted=%d\n", prxattrib->bdecrypted); - } else { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" mic error :prxattrib->bdecrypted=%d ", prxattrib->bdecrypted)); - DBG_88E(" mic error :prxattrib->bdecrypted=%d\n", prxattrib->bdecrypted); - } res = _FAIL; } else { /* mic checked ok */ - if (!psecuritypriv->bcheck_grpkey && is_multicast_ether_addr(prxattrib->ra)) { + if (!psecuritypriv->bcheck_grpkey && + is_multicast_ether_addr(prxattrib->ra)) psecuritypriv->bcheck_grpkey = true; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("psecuritypriv->bcheck_grpkey = true")); - } } - } else { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - ("%s: rtw_get_stainfo==NULL!!!\n", __func__)); } skb_trim(precvframe->pkt, precvframe->pkt->len - 8); @@ -354,16 +278,12 @@ static struct recv_frame *decryptor(struct adapter *padapter, struct recv_frame *return_packet = precv_frame; u32 res = _SUCCESS; - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("prxstat->decrypted=%x prxattrib->encrypt=0x%03x\n", prxattrib->bdecrypted, prxattrib->encrypt)); - if (prxattrib->encrypt > 0) { u8 *iv = precv_frame->pkt->data + prxattrib->hdrlen; prxattrib->key_index = (((iv[3]) >> 6) & 0x3); if (prxattrib->key_index > WEP_KEYS) { - DBG_88E("prxattrib->key_index(%d)>WEP_KEYS\n", prxattrib->key_index); - switch (prxattrib->encrypt) { case _WEP40_: case _WEP104_: @@ -434,8 +354,6 @@ static struct recv_frame *portctrl(struct adapter *adapter, prtnframe = NULL; - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########%s:adapter->securitypriv.dot11AuthAlgrthm=%d\n", __func__, adapter->securitypriv.dot11AuthAlgrthm)); - if (auth_alg == 2) { /* get ether_type */ ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE + pfhdr->attrib.iv_len; @@ -445,8 +363,6 @@ static struct recv_frame *portctrl(struct adapter *adapter, if (psta && (psta->ieee8021x_blocked)) { /* blocked */ /* only accept EAPOL frame */ - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########%s:psta->ieee8021x_blocked==1\n", __func__)); - if (ether_type == eapol_type) { prtnframe = precv_frame; } else { @@ -457,24 +373,11 @@ static struct recv_frame *portctrl(struct adapter *adapter, } else { /* allowed */ /* check decryption status, and decrypt the frame if needed */ - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########%s:psta->ieee8021x_blocked==0\n", __func__)); - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - ("%s:precv_frame->hdr.attrib.privacy=%x\n", - __func__, precv_frame->attrib.privacy)); - - if (pattrib->bdecrypted == 0) - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("%s:prxstat->decrypted=%x\n", __func__, pattrib->bdecrypted)); - prtnframe = precv_frame; /* check is the EAPOL frame or not (Rekey) */ - if (ether_type == eapol_type) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("########%s:ether_type==0x888e\n", __func__)); + if (ether_type == eapol_type) /* check Rekey */ - prtnframe = precv_frame; - } else { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########%s:ether_type=0x%04x\n", __func__, ether_type)); - } } } else { prtnframe = precv_frame; @@ -491,19 +394,11 @@ static int recv_decache(struct recv_frame *precv_frame, u8 bretry, u16 seq_ctrl = ((precv_frame->attrib.seq_num & 0xffff) << 4) | (precv_frame->attrib.frag_num & 0xf); - if (tid > 15) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("%s, (tid>15)! seq_ctrl=0x%x, tid=0x%x\n", __func__, seq_ctrl, tid)); - + if (tid > 15) return _FAIL; - } - if (1) {/* if (bretry) */ - if (seq_ctrl == prxcache->tid_rxseq[tid]) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("%s, seq_ctrl=0x%x, tid=0x%x, tid_rxseq=0x%x\n", __func__, seq_ctrl, tid, prxcache->tid_rxseq[tid])); - - return _FAIL; - } - } + if (seq_ctrl == prxcache->tid_rxseq[tid]) + return _FAIL; prxcache->tid_rxseq[tid] = seq_ctrl; @@ -641,7 +536,6 @@ static int sta2sta_data_frame(struct adapter *adapter, check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { /* filter packets that SA is myself or multicast or broadcast */ if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" SA==myself\n")); ret = _FAIL; goto exit; } @@ -651,8 +545,8 @@ static int sta2sta_data_frame(struct adapter *adapter, goto exit; } - if (!memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) || - !memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) || + if (is_zero_ether_addr(pattrib->bssid) || + is_zero_ether_addr(mybssid) || memcmp(pattrib->bssid, mybssid, ETH_ALEN)) { ret = _FAIL; goto exit; @@ -662,7 +556,6 @@ static int sta2sta_data_frame(struct adapter *adapter, } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { /* For Station mode, sa and bssid should always be BSSID, and DA is my mac-address */ if (memcmp(pattrib->bssid, pattrib->src, ETH_ALEN)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("bssid!=TA under STATION_MODE; drop pkt\n")); ret = _FAIL; goto exit; } @@ -693,7 +586,6 @@ static int sta2sta_data_frame(struct adapter *adapter, *psta = rtw_get_stainfo(pstapriv, sta_addr); /* get ap_info */ if (!*psta) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under %s ; drop pkt\n", __func__)); ret = _FAIL; goto exit; } @@ -720,31 +612,22 @@ static int ap2sta_data_frame(struct adapter *adapter, check_fwstate(pmlmepriv, _FW_UNDER_LINKING))) { /* filter packets that SA is myself or multicast or broadcast */ if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" SA==myself\n")); ret = _FAIL; goto exit; } /* da should be for me */ if (memcmp(myhwaddr, pattrib->dst, ETH_ALEN) && !mcast) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - (" %s: compare DA fail; DA=%pM\n", __func__, (pattrib->dst))); ret = _FAIL; goto exit; } /* check BSSID */ - if (!memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) || - !memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) || - (memcmp(pattrib->bssid, mybssid, ETH_ALEN))) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - (" %s: compare BSSID fail ; BSSID=%pM\n", __func__, (pattrib->bssid))); - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("mybssid=%pM\n", (mybssid))); - - if (!mcast) { - DBG_88E("issue_deauth to the nonassociated ap=%pM for the reason(7)\n", (pattrib->bssid)); + if (is_zero_ether_addr(pattrib->bssid) || + is_zero_ether_addr(mybssid) || + (memcmp(pattrib->bssid, mybssid, ETH_ALEN))) { + if (!mcast) issue_deauth(adapter, pattrib->bssid, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - } ret = _FAIL; goto exit; @@ -756,7 +639,6 @@ static int ap2sta_data_frame(struct adapter *adapter, *psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get ap_info */ if (!*psta) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("ap2sta: can't get psta under STATION_MODE ; drop pkt\n")); ret = _FAIL; goto exit; } @@ -777,11 +659,8 @@ static int ap2sta_data_frame(struct adapter *adapter, } else { if (!memcmp(myhwaddr, pattrib->dst, ETH_ALEN) && !mcast) { *psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get sta_info */ - if (!*psta) { - DBG_88E("issue_deauth to the ap =%pM for the reason(7)\n", (pattrib->bssid)); - + if (!*psta) issue_deauth(adapter, pattrib->bssid, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - } } ret = _FAIL; @@ -812,9 +691,6 @@ static int sta2ap_data_frame(struct adapter *adapter, *psta = rtw_get_stainfo(pstapriv, pattrib->src); if (!*psta) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under AP_MODE; drop pkt\n")); - DBG_88E("issue_deauth to sta=%pM for the reason(7)\n", (pattrib->src)); - issue_deauth(adapter, pattrib->src, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); ret = RTW_RX_HANDLED; @@ -839,7 +715,6 @@ static int sta2ap_data_frame(struct adapter *adapter, ret = RTW_RX_HANDLED; goto exit; } - DBG_88E("issue_deauth to sta=%pM for the reason(7)\n", (pattrib->src)); issue_deauth(adapter, pattrib->src, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); ret = RTW_RX_HANDLED; goto exit; @@ -866,7 +741,7 @@ static int validate_recv_ctrl_frame(struct adapter *padapter, return _FAIL; /* only handle ps-poll */ - if (GetFrameSubType(pframe) == WIFI_PSPOLL) { + if (GetFrameSubType(pframe) == (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL)) { u16 aid; u8 wmmps_ac = 0; struct sta_info *psta = NULL; @@ -904,7 +779,6 @@ static int validate_recv_ctrl_frame(struct adapter *padapter, return _FAIL; if (psta->state & WIFI_STA_ALIVE_CHK_STATE) { - DBG_88E("%s alive check-rx ps-poll\n", __func__); psta->expire_to = pstapriv->expire_to; psta->state ^= WIFI_STA_ALIVE_CHK_STATE; } @@ -948,15 +822,11 @@ static int validate_recv_ctrl_frame(struct adapter *padapter, } } else { if (pstapriv->tim_bitmap & BIT(psta->aid)) { - if (psta->sleepq_len == 0) { - DBG_88E("no buffered packets to xmit\n"); - + if (psta->sleepq_len == 0) /* issue nulldata with More data bit = 0 to indicate we have no buffered packets */ issue_nulldata(padapter, psta->hwaddr, 0, 0, 0); - } else { - DBG_88E("error!psta->sleepq_len=%d\n", psta->sleepq_len); + else psta->sleepq_len = 0; - } pstapriv->tim_bitmap &= ~BIT(psta->aid); @@ -983,25 +853,20 @@ static int validate_recv_mgnt_frame(struct adapter *padapter, { struct sta_info *psta; - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("+%s\n", __func__)); - precv_frame = recvframe_chk_defrag(padapter, precv_frame); - if (!precv_frame) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - ("%s: fragment packet\n", __func__)); + if (!precv_frame) return _SUCCESS; - } /* for rx pkt statistics */ psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(precv_frame->pkt->data)); if (psta) { psta->sta_stats.rx_mgnt_pkts++; - if (GetFrameSubType(precv_frame->pkt->data) == WIFI_BEACON) { + if (GetFrameSubType(precv_frame->pkt->data) == IEEE80211_STYPE_BEACON) { psta->sta_stats.rx_beacon_pkts++; - } else if (GetFrameSubType(precv_frame->pkt->data) == WIFI_PROBEREQ) { + } else if (GetFrameSubType(precv_frame->pkt->data) == IEEE80211_STYPE_PROBE_REQ) { psta->sta_stats.rx_probereq_pkts++; - } else if (GetFrameSubType(precv_frame->pkt->data) == WIFI_PROBERSP) { + } else if (GetFrameSubType(precv_frame->pkt->data) == IEEE80211_STYPE_PROBE_RESP) { if (!memcmp(padapter->eeprompriv.mac_addr, GetAddr1Ptr(precv_frame->pkt->data), ETH_ALEN)) psta->sta_stats.rx_probersp_pkts++; @@ -1063,7 +928,6 @@ static int validate_recv_data_frame(struct adapter *adapter, memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN); memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN); ret = _FAIL; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" case 3\n")); break; default: ret = _FAIL; @@ -1076,7 +940,6 @@ static int validate_recv_data_frame(struct adapter *adapter, goto exit; if (!psta) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" after to_fr_ds_chk; psta==NULL\n")); ret = _FAIL; goto exit; } @@ -1108,19 +971,12 @@ static int validate_recv_data_frame(struct adapter *adapter, /* decache, drop duplicate recv packets */ if (recv_decache(precv_frame, bretry, &psta->sta_recvpriv.rxcache) == _FAIL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("decache : drop pkt\n")); ret = _FAIL; goto exit; } if (pattrib->privacy) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("%s:pattrib->privacy=%x\n", __func__, pattrib->privacy)); - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n ^^^^^^^^^^^is_multicast_ether_addr(pattrib->ra(0x%02x))=%d^^^^^^^^^^^^^^^6\n", pattrib->ra[0], is_multicast_ether_addr(pattrib->ra))); - GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, is_multicast_ether_addr(pattrib->ra)); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n pattrib->encrypt=%d\n", pattrib->encrypt)); - SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt); } else { pattrib->encrypt = 0; @@ -1158,7 +1014,6 @@ static int validate_recv_frame(struct adapter *adapter, /* add version chk */ if (ver != 0) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_data_frame fail! (ver!=0)\n")); retval = _FAIL; goto exit; } @@ -1177,41 +1032,14 @@ static int validate_recv_frame(struct adapter *adapter, pattrib->privacy = GetPrivacy(ptr); pattrib->order = GetOrder(ptr); - /* Dump rx packets */ rtw_hal_get_def_var(adapter, HAL_DEF_DBG_DUMP_RXPKT, &(bDumpRxPkt)); - if (bDumpRxPkt == 1) {/* dump all rx packets */ - if (_drv_err_ <= GlobalDebugLevel) { - pr_info(DRIVER_PREFIX "#############################\n"); - print_hex_dump(KERN_INFO, DRIVER_PREFIX, DUMP_PREFIX_NONE, - 16, 1, ptr, 64, false); - pr_info(DRIVER_PREFIX "#############################\n"); - } - } else if (bDumpRxPkt == 2) { - if ((_drv_err_ <= GlobalDebugLevel) && (type == WIFI_MGT_TYPE)) { - pr_info(DRIVER_PREFIX "#############################\n"); - print_hex_dump(KERN_INFO, DRIVER_PREFIX, DUMP_PREFIX_NONE, - 16, 1, ptr, 64, false); - pr_info(DRIVER_PREFIX "#############################\n"); - } - } else if (bDumpRxPkt == 3) { - if ((_drv_err_ <= GlobalDebugLevel) && (type == WIFI_DATA_TYPE)) { - pr_info(DRIVER_PREFIX "#############################\n"); - print_hex_dump(KERN_INFO, DRIVER_PREFIX, DUMP_PREFIX_NONE, - 16, 1, ptr, 64, false); - pr_info(DRIVER_PREFIX "#############################\n"); - } - } switch (type) { case WIFI_MGT_TYPE: /* mgnt */ retval = validate_recv_mgnt_frame(adapter, precv_frame); - if (retval == _FAIL) - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_mgnt_frame fail\n")); retval = _FAIL; /* only data frame return _SUCCESS */ break; case WIFI_CTRL_TYPE: /* ctrl */ retval = validate_recv_ctrl_frame(adapter, precv_frame); - if (retval == _FAIL) - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_ctrl_frame fail\n")); retval = _FAIL; /* only data frame return _SUCCESS */ break; case WIFI_DATA_TYPE: /* data */ @@ -1225,7 +1053,6 @@ static int validate_recv_frame(struct adapter *adapter, } break; default: - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_data_frame fail! type= 0x%x\n", type)); retval = _FAIL; break; } @@ -1282,9 +1109,6 @@ static int wlanhdr_to_ethhdr(struct recv_frame *precvframe) rmv_len = pattrib->hdrlen + pattrib->iv_len + (bsnaphdr ? SNAP_SIZE : 0); len = precvframe->pkt->len - rmv_len; - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - ("\n===pattrib->hdrlen: %x, pattrib->iv_len:%x===\n\n", pattrib->hdrlen, pattrib->iv_len)); - memcpy(&be_tmp, ptr + rmv_len, 2); eth_type = ntohs(be_tmp); /* pattrib->ether_type */ pattrib->eth_type = eth_type; @@ -1373,8 +1197,6 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter, /* free the defrag_q queue and return the prframe */ rtw_free_recvframe_queue(defrag_q, pfree_recv_queue); - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("Performance defrag!!!!!\n")); - return prframe; } @@ -1436,14 +1258,11 @@ struct recv_frame *recvframe_chk_defrag(struct adapter *padapter, phead = get_list_head(pdefrag_q); list_add_tail(&pfhdr->list, phead); - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("Enqueuq: ismfrag=%d, fragnum=%d\n", ismfrag, fragnum)); - prtnframe = NULL; } else { /* can't find this ta's defrag_queue, so free this recv_frame */ rtw_free_recvframe(precv_frame, pfree_recv_queue); prtnframe = NULL; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("Free because pdefrag_q==NULL: ismfrag=%d, fragnum=%d\n", ismfrag, fragnum)); } } @@ -1455,21 +1274,18 @@ struct recv_frame *recvframe_chk_defrag(struct adapter *padapter, list_add_tail(&pfhdr->list, phead); /* call recvframe_defrag to defrag */ - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("defrag: ismfrag=%d, fragnum=%d\n", ismfrag, fragnum)); precv_frame = recvframe_defrag(padapter, pdefrag_q); prtnframe = precv_frame; } else { /* can't find this ta's defrag_queue, so free this recv_frame */ rtw_free_recvframe(precv_frame, pfree_recv_queue); prtnframe = NULL; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("Free because pdefrag_q==NULL: ismfrag=%d, fragnum=%d\n", ismfrag, fragnum)); } } if (prtnframe && (prtnframe->attrib.privacy)) { /* after defrag we must check tkip mic code */ if (recvframe_chkmic(padapter, prtnframe) == _FAIL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvframe_chkmic(padapter, prtnframe)==_FAIL\n")); rtw_free_recvframe(prtnframe, pfree_recv_queue); prtnframe = NULL; } @@ -1505,10 +1321,8 @@ static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe) /* Offset 12 denote 2 mac address */ nSubframe_Length = get_unaligned_be16(pdata + 12); - if (a_len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) { - DBG_88E("nRemain_Length is %d and nSubframe_Length is : %d\n", a_len, nSubframe_Length); + if (a_len < (ETH_HLEN + nSubframe_Length)) goto exit; - } /* move the data point to data content */ pdata += ETH_HLEN; @@ -1516,20 +1330,16 @@ static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe) /* Allocate new skb for releasing to upper layer */ sub_skb = dev_alloc_skb(nSubframe_Length + 12); - if (!sub_skb) { - DBG_88E("dev_alloc_skb() Fail!!! , nr_subframes=%d\n", nr_subframes); + if (!sub_skb) break; - } skb_reserve(sub_skb, 12); skb_put_data(sub_skb, pdata, nSubframe_Length); subframes[nr_subframes++] = sub_skb; - if (nr_subframes >= MAX_SUBFRAME_COUNT) { - DBG_88E("ParseSubframe(): Too many Subframes! Packets dropped!\n"); + if (nr_subframes >= MAX_SUBFRAME_COUNT) break; - } pdata += nSubframe_Length; a_len -= nSubframe_Length; @@ -1674,9 +1484,6 @@ static int recv_indicatepkts_in_order(struct adapter *padapter, struct recv_reor pattrib = &prframe->attrib; if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - ("%s: indicate=%d seq=%d amsdu=%d\n", - __func__, preorder_ctrl->indicate_seq, pattrib->seq_num, pattrib->amsdu)); plist = plist->next; list_del_init(&prframe->list); @@ -1723,8 +1530,6 @@ static int recv_indicatepkt_reorder(struct adapter *padapter, (pattrib->ack_policy != 0)) { if ((!padapter->bDriverStopped) && (!padapter->bSurpriseRemoved)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("@@@@ %s -recv_func recv_indicatepkt\n", __func__)); - rtw_recv_indicatepkt(padapter, prframe); return _SUCCESS; } @@ -1754,10 +1559,6 @@ static int recv_indicatepkt_reorder(struct adapter *padapter, spin_lock_bh(&ppending_recvframe_queue->lock); - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - ("%s: indicate=%d seq=%d\n", __func__, - preorder_ctrl->indicate_seq, pattrib->seq_num)); - /* s2. check if winstart_b(indicate_seq) needs to been updated */ if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num)) { rtw_recv_indicatepkt(padapter, prframe); @@ -1838,22 +1639,15 @@ static int process_recv_indicatepkts(struct adapter *padapter, } } else { /* B/G mode */ retval = wlanhdr_to_ethhdr(prframe); - if (retval != _SUCCESS) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("wlanhdr_to_ethhdr: drop pkt\n")); + if (retval != _SUCCESS) return retval; - } if ((!padapter->bDriverStopped) && - (!padapter->bSurpriseRemoved)) { + (!padapter->bSurpriseRemoved)) /* indicate this recv_frame */ - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("@@@@ %s- recv_func recv_indicatepkt\n", __func__)); rtw_recv_indicatepkt(padapter, prframe); - } else { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("@@@@ %s- recv_func free_indicatepkt\n", __func__)); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("recv_func:bDriverStopped(%d) OR bSurpriseRemoved(%d)", padapter->bDriverStopped, padapter->bSurpriseRemoved)); + else return _FAIL; - } } return retval; @@ -1868,7 +1662,6 @@ static int recv_func_prehandle(struct adapter *padapter, /* check the frame crtl field and decache */ ret = validate_recv_frame(padapter, rframe); if (ret != _SUCCESS) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("recv_func: validate_recv_frame fail! drop pkt\n")); rtw_free_recvframe(rframe, pfree_recv_queue);/* free this recv_frame */ goto exit; } @@ -1890,20 +1683,16 @@ static int recv_func_posthandle(struct adapter *padapter, prframe = decryptor(padapter, prframe); if (!prframe) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("decryptor: drop pkt\n")); ret = _FAIL; goto _recv_data_drop; } prframe = recvframe_chk_defrag(padapter, prframe); - if (!prframe) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvframe_chk_defrag: drop pkt\n")); + if (!prframe) goto _recv_data_drop; - } prframe = portctrl(padapter, prframe); if (!prframe) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("portctrl: drop pkt\n")); ret = _FAIL; goto _recv_data_drop; } @@ -1912,7 +1701,6 @@ static int recv_func_posthandle(struct adapter *padapter, ret = process_recv_indicatepkts(padapter, prframe); if (ret != _SUCCESS) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recv_func: process_recv_indicatepkts fail!\n")); rtw_free_recvframe(orig_prframe, pfree_recv_queue);/* free this recv_frame */ goto _recv_data_drop; } @@ -1934,10 +1722,8 @@ static int recv_func(struct adapter *padapter, struct recv_frame *rframe) if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && psecuritypriv->busetkipkey) { struct recv_frame *pending_frame; - while ((pending_frame = rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue))) { - if (recv_func_posthandle(padapter, pending_frame) == _SUCCESS) - DBG_88E("%s: dequeue uc_swdec_pending_queue\n", __func__); - } + while ((pending_frame = rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue))) + recv_func_posthandle(padapter, pending_frame); } ret = recv_func_prehandle(padapter, rframe); @@ -1951,7 +1737,6 @@ static int recv_func(struct adapter *padapter, struct recv_frame *rframe) !is_wep_enc(psecuritypriv->dot11PrivacyAlgrthm) && !psecuritypriv->busetkipkey) { rtw_enqueue_recvframe(rframe, &padapter->recvpriv.uc_swdec_pending_queue); - DBG_88E("%s: no key, enqueue uc_swdec_pending_queue\n", __func__); goto exit; } @@ -1971,8 +1756,6 @@ int rtw_recv_entry(struct recv_frame *precvframe) ret = recv_func(padapter, precvframe); if (ret == _SUCCESS) precvpriv->rx_pkts++; - else - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("%s: recv_func return fail!!!\n", __func__)); return ret; } diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c index 617f89842c81..1b2cb6196463 100644 --- a/drivers/staging/rtl8188eu/core/rtw_security.c +++ b/drivers/staging/rtl8188eu/core/rtw_security.c @@ -465,8 +465,9 @@ static const unsigned short Sbox1[2][256] = { /* Sbox for hash (can be in ROM) /** * phase1() - generate P1K, given TA, TK, IV32 - * @tk[]: temporal key [128 bits] - * @ta[]: transmitter's MAC address [ 48 bits] + * @p1k: placeholder for the returned phase 1 key + * @tk: temporal key [128 bits] + * @ta: transmitter's MAC address [ 48 bits] * @iv32: upper 32 bits of IV [ 32 bits] * * This function only needs to be called every 2**16 packets, @@ -498,8 +499,9 @@ static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32) /** * phase2() - generate RC4KEY, given TK, P1K, IV16 - * @tk[]: Temporal key [128 bits] - * @p1k[]: Phase 1 output key [ 80 bits] + * @rc4key: Placeholder for the returned key + * @tk: Temporal key [128 bits] + * @p1k: Phase 1 output key [ 80 bits] * @iv16: low 16 bits of IV counter [ 16 bits] * * The value {TA, IV32, IV16} for Phase1/Phase2 must be unique @@ -589,8 +591,6 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe) stainfo = rtw_get_stainfo(&padapter->stapriv, &pattrib->ra[0]); if (stainfo) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("%s: stainfo!= NULL!!!\n", __func__)); - if (is_multicast_ether_addr(pattrib->ra)) prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey; else @@ -609,9 +609,6 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe) if ((curfragnum + 1) == pattrib->nr_frags) { /* 4 the last fragment */ length = pattrib->last_txcmdsz - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; - RT_TRACE(_module_rtl871x_security_c_, _drv_info_, - ("pattrib->iv_len=%x, pattrib->icv_len=%x\n", - pattrib->iv_len, pattrib->icv_len)); *((__le32 *)crc) = getcrc32(payload, length);/* modified by Amy*/ arcfour_init(&mycontext, rc4key, 16); @@ -629,7 +626,6 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe) } } } else { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("%s: stainfo==NULL!!!\n", __func__)); res = _FAIL; } } @@ -662,12 +658,10 @@ u32 rtw_tkip_decrypt(struct adapter *padapter, struct recv_frame *precvframe) if (is_multicast_ether_addr(prxattrib->ra)) { if (!psecuritypriv->binstallGrpkey) { res = _FAIL; - DBG_88E("%s:rx bc/mc packets, but didn't install group key!!!!!!!!!!\n", __func__); goto exit; } prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey; } else { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("%s: stainfo!= NULL!!!\n", __func__)); prwskey = &stainfo->dot118021x_UncstKey.skey[0]; } @@ -693,14 +687,9 @@ u32 rtw_tkip_decrypt(struct adapter *padapter, struct recv_frame *precvframe) if (crc[3] != payload[length - 1] || crc[2] != payload[length - 2] || crc[1] != payload[length - 3] || - crc[0] != payload[length - 4]) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - ("rtw_wep_decrypt:icv error crc (%4ph)!=payload (%4ph)\n", - &crc, &payload[length - 4])); + crc[0] != payload[length - 4]) res = _FAIL; - } } else { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("%s: stainfo==NULL!!!\n", __func__)); res = _FAIL; } } @@ -742,10 +731,8 @@ u32 rtw_aes_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe) else stainfo = rtw_get_stainfo(&padapter->stapriv, &pattrib->ra[0]); - if (!stainfo) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("%s: stainfo==NULL!!!\n", __func__)); + if (!stainfo) return _FAIL; - } crypto_ops = lib80211_get_crypto_ops("CCMP"); @@ -770,8 +757,6 @@ u32 rtw_aes_encrypt(struct adapter *padapter, struct xmit_frame *pxmitframe) goto exit_crypto_ops_deinit; } - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("%s: stainfo!= NULL!!!\n", __func__)); - for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { if (curfragnum + 1 == pattrib->nr_frags) length = pattrib->last_txcmdsz; @@ -834,7 +819,6 @@ u32 rtw_aes_decrypt(struct adapter *padapter, struct recv_frame *precvframe) /* in concurrent we should use sw descrypt in group key, so we remove this message */ if (!psecuritypriv->binstallGrpkey) { res = _FAIL; - DBG_88E("%s:rx bc/mc packets, but didn't install group key!!!!!!!!!!\n", __func__); goto exit; } key_idx = psecuritypriv->dot118021XGrpKeyid; @@ -877,7 +861,6 @@ exit_lib80211_ccmp: if (crypto_ops && crypto_private) crypto_ops->deinit(crypto_private); } else { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_aes_encrypt: stainfo==NULL!!!\n")); res = _FAIL; } } diff --git a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c index 3c03141e25b1..19eddf573fd8 100644 --- a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c +++ b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c @@ -114,17 +114,11 @@ inline int rtw_stainfo_offset(struct sta_priv *stapriv, struct sta_info *sta) { int offset = (((u8 *)sta) - stapriv->pstainfo_buf) / sizeof(struct sta_info); - if (!stainfo_offset_valid(offset)) - DBG_88E("%s invalid offset(%d), out of range!!!", __func__, offset); - return offset; } inline struct sta_info *rtw_get_stainfo_by_offset(struct sta_priv *stapriv, int offset) { - if (!stainfo_offset_valid(offset)) - DBG_88E("%s invalid offset(%d), out of range!!!", __func__, offset); - return (struct sta_info *)(stapriv->pstainfo_buf + offset * sizeof(struct sta_info)); } @@ -142,13 +136,10 @@ u32 _rtw_free_sta_priv(struct sta_priv *pstapriv) spin_lock_bh(&pstapriv->sta_hash_lock); for (index = 0; index < NUM_STA; index++) { phead = &pstapriv->sta_hash[index]; - plist = phead->next; - - while (phead != plist) { + list_for_each(plist, phead) { int i; - psta = container_of(plist, struct sta_info, hash_list); - plist = plist->next; + psta = list_entry(plist, struct sta_info, hash_list); for (i = 0; i < 16; i++) { preorder_ctrl = &psta->recvreorder_ctrl[i]; @@ -188,13 +179,8 @@ struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) _rtw_init_stainfo(psta); memcpy(psta->hwaddr, hwaddr, ETH_ALEN); index = wifi_mac_hash(hwaddr); - RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_, - ("%s: index=%x", __func__, index)); - if (index >= NUM_STA) { - RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, - ("ERROR => %s: index >= NUM_STA", __func__)); + if (index >= NUM_STA) return NULL; - } phash_list = &pstapriv->sta_hash[index]; spin_lock_bh(&pstapriv->sta_hash_lock); @@ -214,10 +200,6 @@ struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i], &wRxSeqInitialValue, 2); - RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_, - ("alloc number_%d stainfo with hwaddr = %pM\n", - pstapriv->asoc_sta_count, hwaddr)); - init_addba_retry_timer(pstapriv->padapter, psta); /* for A-MPDU Rx reordering buffer control */ @@ -288,11 +270,6 @@ u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta) spin_unlock_bh(&pxmitpriv->lock); list_del_init(&psta->hash_list); - RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, - ("\n free number_%d stainfo with hwaddr=0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", - pstapriv->asoc_sta_count, psta->hwaddr[0], psta->hwaddr[1], - psta->hwaddr[2], psta->hwaddr[3], psta->hwaddr[4], - psta->hwaddr[5])); pstapriv->asoc_sta_count--; /* re-init sta_info; 20061114 */ @@ -382,9 +359,9 @@ exit: /* free all stainfo which in sta_hash[all] */ void rtw_free_all_stainfo(struct adapter *padapter) { - struct list_head *plist, *phead; + struct list_head *phead; s32 index; - struct sta_info *psta = NULL; + struct sta_info *psta, *temp; struct sta_priv *pstapriv = &padapter->stapriv; struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo(padapter); @@ -395,13 +372,7 @@ void rtw_free_all_stainfo(struct adapter *padapter) for (index = 0; index < NUM_STA; index++) { phead = &pstapriv->sta_hash[index]; - plist = phead->next; - - while (phead != plist) { - psta = container_of(plist, struct sta_info, hash_list); - - plist = plist->next; - + list_for_each_entry_safe(psta, temp, phead, hash_list) { if (pbcmc_stainfo != psta) rtw_free_stainfo(padapter, psta); } @@ -431,17 +402,14 @@ struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) spin_lock_bh(&pstapriv->sta_hash_lock); phead = &pstapriv->sta_hash[index]; - plist = phead->next; - - while (phead != plist) { - psta = container_of(plist, struct sta_info, hash_list); + list_for_each(plist, phead) { + psta = list_entry(plist, struct sta_info, hash_list); if (!memcmp(psta->hwaddr, addr, ETH_ALEN)) { /* if found the matched address */ break; } psta = NULL; - plist = plist->next; } spin_unlock_bh(&pstapriv->sta_hash_lock); @@ -456,11 +424,8 @@ u32 rtw_init_bcmc_stainfo(struct adapter *padapter) psta = rtw_alloc_stainfo(pstapriv, bc_addr); - if (!psta) { - RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, - ("rtw_alloc_stainfo fail")); + if (!psta) return _FAIL; - } /* default broadcast & multicast use macid 1 */ psta->mac_id = 1; @@ -489,10 +454,8 @@ bool rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr) spin_lock_bh(&pacl_node_q->lock); phead = get_list_head(pacl_node_q); - plist = phead->next; - while (phead != plist) { - paclnode = container_of(plist, struct rtw_wlan_acl_node, list); - plist = plist->next; + list_for_each(plist, phead) { + paclnode = list_entry(plist, struct rtw_wlan_acl_node, list); if (!memcmp(paclnode->addr, mac_addr, ETH_ALEN)) { if (paclnode->valid) { diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 7015db16dcf8..2d4776debb97 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -521,8 +521,6 @@ void WMMOnAssocRsp(struct adapter *padapter) edca[XMIT_VO_QUEUE] = acParm; break; } - - DBG_88E("WMM(%x): %x, %x\n", ACI, ACM, acParm); } if (padapter->registrypriv.acm_method == 1) @@ -556,10 +554,8 @@ void WMMOnAssocRsp(struct adapter *padapter) } } - for (i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) pxmitpriv->wmm_para_seq[i] = inx[i]; - DBG_88E("wmm_para_seq(%d): %d\n", i, pxmitpriv->wmm_para_seq[i]); - } } static void bwmode_update_check(struct adapter *padapter, struct ndis_802_11_var_ie *pIE) @@ -708,8 +704,6 @@ void HTOnAssocRsp(struct adapter *padapter) struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - DBG_88E("%s\n", __func__); - if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable)) { pmlmeinfo->HT_enable = 1; } else { @@ -803,16 +797,11 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) len = packet_len - sizeof(struct ieee80211_hdr_3addr); - if (len > MAX_IE_SZ) { - DBG_88E("%s IE too long for survey event\n", __func__); + if (len > MAX_IE_SZ) return _FAIL; - } - if (memcmp(cur_network->network.MacAddress, pbssid, 6)) { - DBG_88E("Oops: rtw_check_network_encrypt linked but recv other bssid bcn\n%pM %pM\n", - (pbssid), (cur_network->network.MacAddress)); + if (memcmp(cur_network->network.MacAddress, pbssid, 6)) return true; - } bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC); if (!bssid) @@ -820,7 +809,7 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) subtype = GetFrameSubType(pframe) >> 4; - if (subtype == WIFI_BEACON) + if (subtype == IEEE80211_STYPE_BEACON) bssid->Reserved[0] = 1; bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len; @@ -850,11 +839,6 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) } if (ht_cap_info != cur_network->BcnInfo.ht_cap_info || ((ht_info_infos_0 & 0x03) != (cur_network->BcnInfo.ht_info_infos_0 & 0x03))) { - DBG_88E("%s bcn now: ht_cap_info:%x ht_info_infos_0:%x\n", __func__, - ht_cap_info, ht_info_infos_0); - DBG_88E("%s bcn link: ht_cap_info:%x ht_info_infos_0:%x\n", __func__, - cur_network->BcnInfo.ht_cap_info, cur_network->BcnInfo.ht_info_infos_0); - DBG_88E("%s bw mode change, disconnect\n", __func__); /* bcn_info_update */ cur_network->BcnInfo.ht_cap_info = ht_cap_info; cur_network->BcnInfo.ht_info_infos_0 = ht_info_infos_0; @@ -868,18 +852,13 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) bcn_channel = *(p + 2); } else {/* In 5G, some ap do not have DSSET IE checking HT info for channel */ p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_HT_OPERATION, &len, bssid->ie_length - _FIXED_IE_LENGTH_); - if (pht_info) { + if (pht_info) bcn_channel = pht_info->primary_channel; - } else { /* we don't find channel IE, so don't check it */ - DBG_88E("Oops: %s we don't find channel IE, so don't check it\n", __func__); + else /* we don't find channel IE, so don't check it */ bcn_channel = Adapter->mlmeextpriv.cur_channel; - } } - if (bcn_channel != Adapter->mlmeextpriv.cur_channel) { - DBG_88E("%s beacon channel:%d cur channel:%d disconnect\n", __func__, - bcn_channel, Adapter->mlmeextpriv.cur_channel); + if (bcn_channel != Adapter->mlmeextpriv.cur_channel) goto _mismatch; - } /* checking SSID */ ssid_len = 0; @@ -892,17 +871,10 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) memcpy(bssid->ssid.ssid, (p + 2), ssid_len); bssid->ssid.ssid_length = ssid_len; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s bssid.ssid.ssid:%s bssid.ssid.ssid_length:%d " - "cur_network->network.ssid.ssid:%s len:%d\n", __func__, bssid->ssid.ssid, - bssid->ssid.ssid_length, cur_network->network.ssid.ssid, - cur_network->network.ssid.ssid_length)); - if (memcmp(bssid->ssid.ssid, cur_network->network.ssid.ssid, 32) || bssid->ssid.ssid_length != cur_network->network.ssid.ssid_length) { - if (bssid->ssid.ssid[0] != '\0' && bssid->ssid.ssid_length != 0) { /* not hidden ssid */ - DBG_88E("%s(), SSID is not match return FAIL\n", __func__); + if (bssid->ssid.ssid[0] != '\0' && bssid->ssid.ssid_length != 0) /* not hidden ssid */ goto _mismatch; - } } /* check encryption info */ @@ -913,13 +885,8 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) else bssid->Privacy = 0; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("%s(): cur_network->network.Privacy is %d, bssid.Privacy is %d\n", - __func__, cur_network->network.Privacy, bssid->Privacy)); - if (cur_network->network.Privacy != bssid->Privacy) { - DBG_88E("%s(), privacy is not match return FAIL\n", __func__); + if (cur_network->network.Privacy != bssid->Privacy) goto _mismatch; - } rtw_get_sec_ie(bssid->ies, bssid->ie_length, NULL, &rsn_len, NULL, &wpa_len); @@ -932,46 +899,29 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) encryp_protocol = ENCRYP_PROTOCOL_WEP; } - if (cur_network->BcnInfo.encryp_protocol != encryp_protocol) { - DBG_88E("%s(): encryption protocol is not match , return FAIL\n", __func__); + if (cur_network->BcnInfo.encryp_protocol != encryp_protocol) goto _mismatch; - } if (encryp_protocol == ENCRYP_PROTOCOL_WPA || encryp_protocol == ENCRYP_PROTOCOL_WPA2) { pbuf = rtw_get_wpa_ie(&bssid->ies[12], &wpa_ielen, bssid->ie_length - 12); if (pbuf && (wpa_ielen > 0)) { - if (rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is_8021x) == _SUCCESS) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("%s pnetwork->pairwise_cipher: %d, group_cipher is %d, is_8021x is %d\n", __func__, - pairwise_cipher, group_cipher, is_8021x)); - } + rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher, + &pairwise_cipher, &is_8021x); } else { pbuf = rtw_get_wpa2_ie(&bssid->ies[12], &wpa_ielen, bssid->ie_length - 12); - if (pbuf && (wpa_ielen > 0)) { - if (rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is_8021x) == _SUCCESS) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("%s pnetwork->pairwise_cipher: %d, pnetwork->group_cipher is %d, is_802x is %d\n", - __func__, pairwise_cipher, group_cipher, is_8021x)); - } - } + if (pbuf && (wpa_ielen > 0)) + rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher, + &pairwise_cipher, &is_8021x); } - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - ("%s cur_network->group_cipher is %d: %d\n", __func__, cur_network->BcnInfo.group_cipher, group_cipher)); - if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher || group_cipher != cur_network->BcnInfo.group_cipher) { - DBG_88E("%s pairwise_cipher(%x:%x) or group_cipher(%x:%x) is not match , return FAIL\n", __func__, - pairwise_cipher, cur_network->BcnInfo.pairwise_cipher, - group_cipher, cur_network->BcnInfo.group_cipher); + if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher || group_cipher != cur_network->BcnInfo.group_cipher) goto _mismatch; - } - if (is_8021x != cur_network->BcnInfo.is_8021x) { - DBG_88E("%s authentication is not match , return FAIL\n", __func__); + if (is_8021x != cur_network->BcnInfo.is_8021x) goto _mismatch; - } } kfree(bssid); @@ -1029,6 +979,7 @@ unsigned int is_ap_in_tkip(struct adapter *padapter) case WLAN_EID_RSN: if (!memcmp((pIE->data + 8), RSN_TKIP_CIPHER, 4)) return true; + break; default: break; } @@ -1191,41 +1142,31 @@ unsigned char check_assoc_AP(u8 *pframe, uint len) case WLAN_EID_VENDOR_SPECIFIC: if ((!memcmp(pIE->data, ARTHEROS_OUI1, 3)) || (!memcmp(pIE->data, ARTHEROS_OUI2, 3))) { - DBG_88E("link to Artheros AP\n"); return HT_IOT_PEER_ATHEROS; } else if ((!memcmp(pIE->data, BROADCOM_OUI1, 3)) || (!memcmp(pIE->data, BROADCOM_OUI2, 3))) { - DBG_88E("link to Broadcom AP\n"); return HT_IOT_PEER_BROADCOM; } else if (!memcmp(pIE->data, MARVELL_OUI, 3)) { - DBG_88E("link to Marvell AP\n"); return HT_IOT_PEER_MARVELL; } else if (!memcmp(pIE->data, RALINK_OUI, 3)) { - if (!ralink_vendor_flag) { + if (!ralink_vendor_flag) ralink_vendor_flag = 1; - } else { - DBG_88E("link to Ralink AP\n"); + else return HT_IOT_PEER_RALINK; - } } else if (!memcmp(pIE->data, CISCO_OUI, 3)) { - DBG_88E("link to Cisco AP\n"); return HT_IOT_PEER_CISCO; } else if (!memcmp(pIE->data, REALTEK_OUI, 3)) { - DBG_88E("link to Realtek 96B\n"); return HT_IOT_PEER_REALTEK; } else if (!memcmp(pIE->data, AIRGOCAP_OUI, 3)) { - DBG_88E("link to Airgo Cap\n"); return HT_IOT_PEER_AIRGO; } else if (!memcmp(pIE->data, EPIGRAM_OUI, 3)) { epigram_vendor_flag = 1; - if (ralink_vendor_flag) { - DBG_88E("link to Tenda W311R AP\n"); + if (ralink_vendor_flag) return HT_IOT_PEER_TENDA; - } - DBG_88E("Capture EPIGRAM_OUI\n"); } else { break; } + break; default: break; @@ -1233,14 +1174,10 @@ unsigned char check_assoc_AP(u8 *pframe, uint len) i += (pIE->Length + 2); } - if (ralink_vendor_flag && !epigram_vendor_flag) { - DBG_88E("link to Ralink AP\n"); + if (ralink_vendor_flag && !epigram_vendor_flag) return HT_IOT_PEER_RALINK; - } else if (ralink_vendor_flag && epigram_vendor_flag) { - DBG_88E("link to Tenda W311R AP\n"); + else if (ralink_vendor_flag && epigram_vendor_flag) return HT_IOT_PEER_TENDA; - } - DBG_88E("link to new AP\n"); return HT_IOT_PEER_UNKNOWN; } diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index 99e44b2c6f36..d5fc59417ec6 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -75,7 +75,6 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) if (!pxmitpriv->pallocated_frame_buf) { pxmitpriv->pxmit_frame_buf = NULL; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_frame fail!\n")); res = _FAIL; goto exit; } @@ -110,7 +109,6 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) pxmitpriv->pallocated_xmitbuf = vzalloc(NR_XMITBUFF * sizeof(struct xmit_buf) + 4); if (!pxmitpriv->pallocated_xmitbuf) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_buf fail!\n")); res = _FAIL; goto exit; } @@ -149,7 +147,6 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) pxmitpriv->pallocated_xmit_extbuf = vzalloc(num_xmit_extbuf * sizeof(struct xmit_buf) + 4); if (!pxmitpriv->pallocated_xmit_extbuf) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_extbuf fail!\n")); res = _FAIL; goto exit; } @@ -364,8 +361,6 @@ u8 qos_acm(u8 acm_mask, u8 priority) change_priority = 5; break; default: - DBG_88E("%s(): invalid pattrib->priority: %d!!!\n", - __func__, priority); break; } @@ -444,14 +439,11 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p ((tmp[21] == 67) && (tmp[23] == 68))) { /* 68 : UDP BOOTP client */ /* 67 : UDP BOOTP server */ - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("====================== %s: get DHCP Packet\n", __func__)); /* Use low rate to send DHCP packet. */ pattrib->dhcp_pkt = 1; } } } - } else if (pattrib->ether_type == ETH_P_PAE) { - DBG_88E_LEVEL(_drv_info_, "send eapol packet\n"); } if ((pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1)) @@ -469,7 +461,6 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p } else { psta = rtw_get_stainfo(pstapriv, pattrib->ra); if (!psta) { /* if we cannot get psta => drrp the pkt */ - RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, ("\nupdate_attrib => get sta_info fail, ra: %pM\n", (pattrib->ra))); res = _FAIL; goto exit; } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) && @@ -481,11 +472,9 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p if (psta) { pattrib->mac_id = psta->mac_id; - /* DBG_88E("%s ==> mac_id(%d)\n", __func__, pattrib->mac_id); */ pattrib->psta = psta; } else { /* if we cannot get psta => drop the pkt */ - RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, ("\nupdate_attrib => get sta_info fail, ra:%pM\n", (pattrib->ra))); res = _FAIL; goto exit; } @@ -510,12 +499,9 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p } if (psta->ieee8021x_blocked) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("\n psta->ieee8021x_blocked == true\n")); - pattrib->encrypt = 0; if (pattrib->ether_type != ETH_P_PAE) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("\npsta->ieee8021x_blocked == true, pattrib->ether_type(%.4x) != ETH_P_PAE\n", pattrib->ether_type)); res = _FAIL; goto exit; } @@ -551,15 +537,11 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p pattrib->icv_len = 4; if (padapter->securitypriv.busetkipkey == _FAIL) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - ("\npadapter->securitypriv.busetkipkey(%d) == _FAIL drop packet\n", - padapter->securitypriv.busetkipkey)); res = _FAIL; goto exit; } break; case _AES_: - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("pattrib->encrypt=%d (_AES_)\n", pattrib->encrypt)); pattrib->iv_len = 8; pattrib->icv_len = 8; break; @@ -569,18 +551,10 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p break; } - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - ("%s: encrypt=%d\n", __func__, pattrib->encrypt)); - - if (pattrib->encrypt && !psecuritypriv->hw_decrypted) { + if (pattrib->encrypt && !psecuritypriv->hw_decrypted) pattrib->bswenc = true; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - ("%s: encrypt=%d bswenc = true\n", __func__, - pattrib->encrypt)); - } else { + else pattrib->bswenc = false; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("%s: bswenc = false\n", __func__)); - } update_attrib_phy_info(pattrib, psta); @@ -649,17 +623,8 @@ static s32 xmitframe_addmic(struct adapter *padapter, struct xmit_frame *pxmitfr for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { payload = (u8 *)round_up((size_t)(payload), 4); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - ("=== curfragnum=%d, pframe = 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x,!!!\n", - curfragnum, *payload, *(payload + 1), - *(payload + 2), *(payload + 3), - *(payload + 4), *(payload + 5), - *(payload + 6), *(payload + 7))); payload += pattrib->hdrlen + pattrib->iv_len; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - ("curfragnum=%d pattrib->hdrlen=%d pattrib->iv_len=%d", - curfragnum, pattrib->hdrlen, pattrib->iv_len)); if (curfragnum + 1 == pattrib->nr_frags) { length = pattrib->last_txcmdsz - pattrib->hdrlen - @@ -676,32 +641,16 @@ static s32 xmitframe_addmic(struct adapter *padapter, struct xmit_frame *pxmitfr pattrib->icv_len : 0); rtw_secmicappend(&micdata, payload, length); payload += length + pattrib->icv_len; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("curfragnum=%d length=%d pattrib->icv_len=%d", curfragnum, length, pattrib->icv_len)); } } rtw_secgetmic(&micdata, &mic[0]); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: before add mic code!!!\n", __func__)); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: pattrib->last_txcmdsz=%d!!!\n", __func__, pattrib->last_txcmdsz)); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: mic[0]=0x%.2x , mic[1]=0x%.2x , mic[2]= 0x%.2x, mic[3]=0x%.2x\n\ - mic[4]= 0x%.2x , mic[5]= 0x%.2x , mic[6]= 0x%.2x , mic[7]= 0x%.2x !!!!\n", - __func__, mic[0], mic[1], mic[2], mic[3], mic[4], mic[5], mic[6], mic[7])); /* add mic code and add the mic code length in last_txcmdsz */ memcpy(payload, &mic[0], 8); pattrib->last_txcmdsz += 8; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("\n ======== last pkt ========\n")); payload -= pattrib->last_txcmdsz + 8; - for (curfragnum = 0; curfragnum < pattrib->last_txcmdsz; curfragnum += 8) - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - (" %.2x, %.2x, %.2x, %.2x, %.2x, %.2x, %.2x, %.2x ", - *(payload + curfragnum), *(payload + curfragnum + 1), - *(payload + curfragnum + 2), *(payload + curfragnum + 3), - *(payload + curfragnum + 4), *(payload + curfragnum + 5), - *(payload + curfragnum + 6), *(payload + curfragnum + 7))); - } else { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: rtw_get_stainfo==NULL!!!\n", __func__)); - } + } } return _SUCCESS; @@ -712,7 +661,6 @@ static s32 xmitframe_swencrypt(struct adapter *padapter, struct xmit_frame *pxmi struct pkt_attrib *pattrib = &pxmitframe->attrib; if (pattrib->bswenc) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, ("### %s\n", __func__)); switch (pattrib->encrypt) { case _WEP40_: case _WEP104_: @@ -727,8 +675,6 @@ static s32 xmitframe_swencrypt(struct adapter *padapter, struct xmit_frame *pxmi default: break; } - } else { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_, ("### xmitframe_hwencrypt\n")); } return _SUCCESS; @@ -790,7 +736,6 @@ s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattr if (psta && psta->qos_option) qos_option = true; } else { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("fw_state:%x is not allowed to xmit frame\n", get_fwstate(pmlmepriv))); res = _FAIL; goto exit; } @@ -926,10 +871,8 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct if (!psta) return _FAIL; - if (!pxmitframe->buf_addr) { - DBG_88E("==> %s buf_addr == NULL\n", __func__); + if (!pxmitframe->buf_addr) return _FAIL; - } pbuf_start = pxmitframe->buf_addr; @@ -938,8 +881,6 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct mem_start = pbuf_start + hw_hdr_offset; if (rtw_make_wlanhdr(padapter, mem_start, pattrib) == _FAIL) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: rtw_make_wlanhdr fail; drop pkt\n", __func__)); - DBG_88E("%s: rtw_make_wlanhdr fail; drop pkt\n", __func__); res = _FAIL; goto exit; } @@ -982,13 +923,6 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct memcpy(pframe, pattrib->iv, pattrib->iv_len); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_, - ("%s: keyid=%d pattrib->iv[3]=%.2x pframe=%.2x %.2x %.2x %.2x\n", - __func__, - padapter->securitypriv.dot11PrivacyKeyIndex, - pattrib->iv[3], *pframe, *(pframe + 1), - *(pframe + 2), *(pframe + 3))); - pframe += pattrib->iv_len; mpdu_len -= pattrib->iv_len; @@ -1027,8 +961,6 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct break; } - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: There're still something in packet!\n", __func__)); - addr = (size_t)(pframe); mem_start = (unsigned char *)round_up(addr, 4) + hw_hdr_offset; @@ -1039,8 +971,6 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct rtl88eu_mon_xmit_hook(padapter->pmondev, pxmitframe, frg_len); if (xmitframe_addmic(padapter, pxmitframe) == _FAIL) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n")); - DBG_88E("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n"); res = _FAIL; goto exit; } @@ -1153,10 +1083,8 @@ struct xmit_buf *rtw_alloc_xmitbuf_ext(struct xmit_priv *pxmitpriv) list_del_init(&pxmitbuf->list); pxmitpriv->free_xmit_extbuf_cnt--; pxmitbuf->priv_data = NULL; - if (pxmitbuf->sctx) { - DBG_88E("%s pxmitbuf->sctx is not NULL\n", __func__); + if (pxmitbuf->sctx) rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC); - } } spin_unlock_irqrestore(&pfree_queue->lock, irql); @@ -1197,7 +1125,6 @@ struct xmit_buf *rtw_alloc_xmitbuf(struct xmit_priv *pxmitpriv) pxmitpriv->free_xmitbuf_cnt--; pxmitbuf->priv_data = NULL; if (pxmitbuf->sctx) { - DBG_88E("%s pxmitbuf->sctx is not NULL\n", __func__); rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC); } } @@ -1214,10 +1141,8 @@ s32 rtw_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) if (!pxmitbuf) return _FAIL; - if (pxmitbuf->sctx) { - DBG_88E("%s pxmitbuf->sctx is not NULL\n", __func__); + if (pxmitbuf->sctx) rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_FREE); - } if (pxmitbuf->ext_tag) { rtw_free_xmitbuf_ext(pxmitpriv, pxmitbuf); @@ -1261,20 +1186,12 @@ struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv) spin_lock_bh(&pfree_xmit_queue->lock); pxframe = list_first_entry_or_null(&pfree_xmit_queue->queue, struct xmit_frame, list); - if (!pxframe) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - ("rtw_alloc_xmitframe:%d\n", - pxmitpriv->free_xmitframe_cnt)); - } else { + if (pxframe) { list_del_init(&pxframe->list); /* default value setting */ pxmitpriv->free_xmitframe_cnt--; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - ("rtw_alloc_xmitframe():free_xmitframe_cnt=%d\n", - pxmitpriv->free_xmitframe_cnt)); - pxframe->buf_addr = NULL; pxframe->pxmitbuf = NULL; @@ -1299,10 +1216,8 @@ s32 rtw_free_xmitframe(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitfram struct adapter *padapter = pxmitpriv->adapter; struct sk_buff *pndis_pkt = NULL; - if (!pxmitframe) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("====== %s:pxmitframe == NULL!!!!!!!!!!\n", __func__)); + if (!pxmitframe) goto exit; - } spin_lock_bh(&pfree_xmit_queue->lock); @@ -1316,7 +1231,6 @@ s32 rtw_free_xmitframe(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitfram list_add_tail(&pxmitframe->list, get_list_head(pfree_xmit_queue)); pxmitpriv->free_xmitframe_cnt++; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, ("%s:free_xmitframe_cnt=%d\n", __func__, pxmitpriv->free_xmitframe_cnt)); spin_unlock_bh(&pfree_xmit_queue->lock); @@ -1329,31 +1243,22 @@ exit: void rtw_free_xmitframe_queue(struct xmit_priv *pxmitpriv, struct __queue *pframequeue) { - struct list_head *plist, *phead; - struct xmit_frame *pxmitframe; + struct list_head *phead; + struct xmit_frame *pxmitframe, *temp; spin_lock_bh(&pframequeue->lock); phead = get_list_head(pframequeue); - plist = phead->next; - - while (phead != plist) { - pxmitframe = container_of(plist, struct xmit_frame, list); - - plist = plist->next; - + list_for_each_entry_safe(pxmitframe, temp, phead, list) rtw_free_xmitframe(pxmitpriv, pxmitframe); - } + spin_unlock_bh(&pframequeue->lock); } s32 rtw_xmitframe_enqueue(struct adapter *padapter, struct xmit_frame *pxmitframe) { - if (rtw_xmit_classifier(padapter, pxmitframe) == _FAIL) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - ("%s: drop xmit pkt for classifier fail\n", __func__)); + if (rtw_xmit_classifier(padapter, pxmitframe) == _FAIL) return _FAIL; - } return _SUCCESS; } @@ -1404,10 +1309,9 @@ struct xmit_frame *rtw_dequeue_xframe(struct xmit_priv *pxmitpriv, struct hw_xmi phwxmit = phwxmit_i + inx[i]; sta_phead = get_list_head(phwxmit->sta_queue); - sta_plist = sta_phead->next; - - while (sta_phead != sta_plist) { - ptxservq = container_of(sta_plist, struct tx_servq, tx_pending); + list_for_each(sta_plist, sta_phead) { + ptxservq = list_entry(sta_plist, struct tx_servq, + tx_pending); pframe_queue = &ptxservq->sta_pending; @@ -1421,8 +1325,6 @@ struct xmit_frame *rtw_dequeue_xframe(struct xmit_priv *pxmitpriv, struct hw_xmi list_del_init(&ptxservq->tx_pending); goto exit; } - - sta_plist = sta_plist->next; } } exit: @@ -1440,30 +1342,22 @@ struct tx_servq *rtw_get_sta_pending(struct adapter *padapter, case 2: ptxservq = &psta->sta_xmitpriv.bk_q; *(ac) = 3; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - ("%s : BK\n", __func__)); break; case 4: case 5: ptxservq = &psta->sta_xmitpriv.vi_q; *(ac) = 1; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - ("%s : VI\n", __func__)); break; case 6: case 7: ptxservq = &psta->sta_xmitpriv.vo_q; *(ac) = 0; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - ("%s : VO\n", __func__)); break; case 0: case 3: default: ptxservq = &psta->sta_xmitpriv.be_q; *(ac) = 2; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - ("%s : BE\n", __func__)); break; } @@ -1491,8 +1385,6 @@ s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe) if (!psta) { res = _FAIL; - DBG_88E("%s: psta == NULL\n", __func__); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: psta == NULL\n", __func__)); goto exit; } @@ -1598,16 +1490,12 @@ s32 rtw_xmit(struct adapter *padapter, struct sk_buff **ppkt) s32 res; pxmitframe = rtw_alloc_xmitframe(pxmitpriv); - if (!pxmitframe) { - RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("%s: no more pxmitframe\n", __func__)); - DBG_88E("DBG_TX_DROP_FRAME %s no more pxmitframe\n", __func__); + if (!pxmitframe) return -1; - } res = update_attrib(padapter, *ppkt, &pxmitframe->attrib); if (res == _FAIL) { - RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("%s: update attrib fail\n", __func__)); rtw_free_xmitframe(pxmitpriv, pxmitframe); return -1; } @@ -1738,21 +1626,15 @@ int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_fra static void dequeue_xmitframes_to_sleeping_queue(struct adapter *padapter, struct sta_info *psta, struct __queue *pframequeue) { - struct list_head *plist, *phead; + struct list_head *phead; u8 ac_index; struct tx_servq *ptxservq; struct pkt_attrib *pattrib; - struct xmit_frame *pxmitframe; + struct xmit_frame *pxmitframe, *n; struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits; phead = get_list_head(pframequeue); - plist = phead->next; - - while (phead != plist) { - pxmitframe = container_of(plist, struct xmit_frame, list); - - plist = plist->next; - + list_for_each_entry_safe(pxmitframe, n, phead, list) { xmitframe_enqueue_for_sleeping_sta(padapter, pxmitframe); pattrib = &pxmitframe->attrib; @@ -1811,20 +1693,14 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta) { u8 update_mask = 0, wmmps_ac = 0; struct sta_info *psta_bmc; - struct list_head *xmitframe_plist, *xmitframe_phead; - struct xmit_frame *pxmitframe = NULL; + struct list_head *xmitframe_phead; + struct xmit_frame *pxmitframe, *n; struct sta_priv *pstapriv = &padapter->stapriv; spin_lock_bh(&psta->sleep_q.lock); xmitframe_phead = get_list_head(&psta->sleep_q); - xmitframe_plist = xmitframe_phead->next; - - while (xmitframe_phead != xmitframe_plist) { - pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list); - - xmitframe_plist = xmitframe_plist->next; - + list_for_each_entry_safe(pxmitframe, n, xmitframe_phead, list) { list_del_init(&pxmitframe->list); switch (pxmitframe->attrib.priority) { @@ -1899,13 +1775,7 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta) spin_lock_bh(&psta_bmc->sleep_q.lock); xmitframe_phead = get_list_head(&psta_bmc->sleep_q); - xmitframe_plist = xmitframe_phead->next; - - while (xmitframe_phead != xmitframe_plist) { - pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list); - - xmitframe_plist = xmitframe_plist->next; - + list_for_each_entry_safe(pxmitframe, n, xmitframe_phead, list) { list_del_init(&pxmitframe->list); psta_bmc->sleepq_len--; @@ -1939,20 +1809,14 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta) void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *psta) { u8 wmmps_ac = 0; - struct list_head *xmitframe_plist, *xmitframe_phead; - struct xmit_frame *pxmitframe = NULL; + struct list_head *xmitframe_phead; + struct xmit_frame *pxmitframe, *n; struct sta_priv *pstapriv = &padapter->stapriv; spin_lock_bh(&psta->sleep_q.lock); xmitframe_phead = get_list_head(&psta->sleep_q); - xmitframe_plist = xmitframe_phead->next; - - while (xmitframe_phead != xmitframe_plist) { - pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list); - - xmitframe_plist = xmitframe_plist->next; - + list_for_each_entry_safe(pxmitframe, n, xmitframe_phead, list) { switch (pxmitframe->attrib.priority) { case 1: case 2: @@ -2025,7 +1889,6 @@ int rtw_sctx_wait(struct submit_ctx *sctx) if (!wait_for_completion_timeout(&sctx->done, expire)) { /* timeout, do something?? */ status = RTW_SCTX_DONE_TIMEOUT; - DBG_88E("%s timeout\n", __func__); } else { status = sctx->status; } @@ -2036,26 +1899,9 @@ int rtw_sctx_wait(struct submit_ctx *sctx) return ret; } -static bool rtw_sctx_chk_warning_status(int status) -{ - switch (status) { - case RTW_SCTX_DONE_UNKNOWN: - case RTW_SCTX_DONE_BUF_ALLOC: - case RTW_SCTX_DONE_BUF_FREE: - - case RTW_SCTX_DONE_DRV_STOP: - case RTW_SCTX_DONE_DEV_REMOVE: - return true; - default: - return false; - } -} - void rtw_sctx_done_err(struct submit_ctx **sctx, int status) { if (*sctx) { - if (rtw_sctx_chk_warning_status(status)) - DBG_88E("%s status:%d\n", __func__, status); (*sctx)->status = status; complete(&((*sctx)->done)); *sctx = NULL; @@ -2079,6 +1925,4 @@ void rtw_ack_tx_done(struct xmit_priv *pxmitpriv, int status) if (pxmitpriv->ack_tx) rtw_sctx_done_err(&pack_tx_ops, status); - else - DBG_88E("%s ack_tx not set\n", __func__); } diff --git a/drivers/staging/rtl8188eu/hal/hal8188e_rate_adaptive.c b/drivers/staging/rtl8188eu/hal/hal8188e_rate_adaptive.c index 5792f491b59a..74fff76af16d 100644 --- a/drivers/staging/rtl8188eu/hal/hal8188e_rate_adaptive.c +++ b/drivers/staging/rtl8188eu/hal/hal8188e_rate_adaptive.c @@ -101,9 +101,6 @@ static void odm_SetTxRPTTiming_8188E(struct odm_dm_struct *dm_odm, idx -= 1; } pRaInfo->RptTime = DynamicTxRPTTiming[idx]; - - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, - ("pRaInfo->RptTime = 0x%x\n", pRaInfo->RptTime)); } static int odm_RateDown_8188E(struct odm_dm_struct *dm_odm, @@ -112,20 +109,13 @@ static int odm_RateDown_8188E(struct odm_dm_struct *dm_odm, u8 RateID, LowestRate, HighestRate; u8 i; - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, - ODM_DBG_TRACE, ("=====>%s()\n", __func__)); - if (!pRaInfo) { - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, - ("%s(): pRaInfo is NULL\n", __func__)); + if (!pRaInfo) return -1; - } + RateID = pRaInfo->PreRate; LowestRate = pRaInfo->LowestRate; HighestRate = pRaInfo->HighestRate; - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, - (" RateID =%d LowestRate =%d HighestRate =%d RateSGI =%d\n", - RateID, LowestRate, HighestRate, pRaInfo->RateSGI)); if (RateID > HighestRate) { RateID = HighestRate; } else if (pRaInfo->RateSGI) { @@ -158,15 +148,6 @@ RateDownFinish: pRaInfo->DecisionRate = RateID; odm_SetTxRPTTiming_8188E(dm_odm, pRaInfo, 2); - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, - ODM_DBG_LOUD, ("Rate down, RPT Timing default\n")); - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, - ("RAWaitingCounter %d, RAPendingCounter %d", - pRaInfo->RAWaitingCounter, pRaInfo->RAPendingCounter)); - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, - ("Rate down to RateID %d RateSGI %d\n", RateID, pRaInfo->RateSGI)); - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, - ("<===== %s()\n", __func__)); return 0; } @@ -176,18 +157,11 @@ static int odm_RateUp_8188E(struct odm_dm_struct *dm_odm, u8 RateID, HighestRate; u8 i; - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, - ODM_DBG_TRACE, ("=====>%s()\n", __func__)); - if (!pRaInfo) { - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, - ("%s(): pRaInfo is NULL\n", __func__)); + if (!pRaInfo) return -1; - } + RateID = pRaInfo->PreRate; HighestRate = pRaInfo->HighestRate; - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, - (" RateID =%d HighestRate =%d\n", - RateID, HighestRate)); if (pRaInfo->RAWaitingCounter == 1) { pRaInfo->RAWaitingCounter = 0; pRaInfo->RAPendingCounter = 0; @@ -196,8 +170,6 @@ static int odm_RateUp_8188E(struct odm_dm_struct *dm_odm, goto RateUpfinish; } odm_SetTxRPTTiming_8188E(dm_odm, pRaInfo, 0); - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, - ("%s():Decrease RPT Timing\n", __func__)); if (RateID < HighestRate) { for (i = RateID + 1; i <= HighestRate; i++) { @@ -222,13 +194,6 @@ RateUpfinish: pRaInfo->RAWaitingCounter++; pRaInfo->DecisionRate = RateID; - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, - ("Rate up to RateID %d\n", RateID)); - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, - ("RAWaitingCounter %d, RAPendingCounter %d", - pRaInfo->RAWaitingCounter, pRaInfo->RAPendingCounter)); - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, - ODM_DBG_TRACE, ("<===== %s()\n", __func__)); return 0; } @@ -250,9 +215,6 @@ static void odm_RateDecision_8188E(struct odm_dm_struct *dm_odm, /* u32 pool_retry; */ static u8 DynamicTxRPTTimingCounter; - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, - ("=====>%s()\n", __func__)); - if (pRaInfo->Active && (pRaInfo->TOTAL > 0)) { /* STA used and data packet exits */ if ((pRaInfo->RssiStaRA < (pRaInfo->PreRssiStaRA - 3)) || (pRaInfo->RssiStaRA > (pRaInfo->PreRssiStaRA + 3))) { @@ -270,16 +232,9 @@ static void odm_RateDecision_8188E(struct odm_dm_struct *dm_odm, RtyPtID = 1; PenaltyID1 = RETRY_PENALTY_IDX[RtyPtID][RateID]; /* TODO by page */ - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, - (" NscDown init is %d\n", pRaInfo->NscDown)); - for (i = 0 ; i <= 4 ; i++) pRaInfo->NscDown += pRaInfo->RTY[i] * RETRY_PENALTY[PenaltyID1][i]; - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, - (" NscDown is %d, total*penalty[5] is %d\n", pRaInfo->NscDown, - (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5]))); - if (pRaInfo->NscDown > (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5])) pRaInfo->NscDown -= pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5]; else @@ -287,24 +242,15 @@ static void odm_RateDecision_8188E(struct odm_dm_struct *dm_odm, /* rate up */ PenaltyID2 = RETRY_PENALTY_UP_IDX[RateID]; - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, - (" NscUp init is %d\n", pRaInfo->NscUp)); for (i = 0 ; i <= 4 ; i++) pRaInfo->NscUp += pRaInfo->RTY[i] * RETRY_PENALTY[PenaltyID2][i]; - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, - ("NscUp is %d, total*up[5] is %d\n", - pRaInfo->NscUp, (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID2][5]))); - if (pRaInfo->NscUp > (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID2][5])) pRaInfo->NscUp -= pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID2][5]; else pRaInfo->NscUp = 0; - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE | ODM_COMP_INIT, ODM_DBG_LOUD, - (" RssiStaRa = %d RtyPtID =%d PenaltyID1 = 0x%x PenaltyID2 = 0x%x RateID =%d NscDown =%d NscUp =%d SGI =%d\n", - pRaInfo->RssiStaRA, RtyPtID, PenaltyID1, PenaltyID2, RateID, pRaInfo->NscDown, pRaInfo->NscUp, pRaInfo->RateSGI)); if ((pRaInfo->NscDown < N_THRESHOLD_LOW[RateID]) || (pRaInfo->DROP > DROPING_NECESSARY[RateID])) odm_RateDown_8188E(dm_odm, pRaInfo); @@ -321,8 +267,6 @@ static void odm_RateDecision_8188E(struct odm_dm_struct *dm_odm, if (DynamicTxRPTTimingCounter >= 4) { odm_SetTxRPTTiming_8188E(dm_odm, pRaInfo, 1); - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, - ODM_DBG_LOUD, ("<===== Rate don't change 4 times, Extend RPT Timing\n")); DynamicTxRPTTimingCounter = 0; } @@ -330,8 +274,6 @@ static void odm_RateDecision_8188E(struct odm_dm_struct *dm_odm, odm_ResetRaCounter_8188E(pRaInfo); } - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, - ("<===== %s()\n", __func__)); } static int odm_ARFBRefresh_8188E(struct odm_dm_struct *dm_odm, struct odm_ra_info *pRaInfo) @@ -414,15 +356,9 @@ static int odm_ARFBRefresh_8188E(struct odm_dm_struct *dm_odm, struct odm_ra_inf else pRaInfo->PTModeSS = 0; - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, - ("ODM_ARFBRefresh_8188E(): PTModeSS =%d\n", pRaInfo->PTModeSS)); - if (pRaInfo->DecisionRate > pRaInfo->HighestRate) pRaInfo->DecisionRate = pRaInfo->HighestRate; - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, - ("ODM_ARFBRefresh_8188E(): RateID =%d RateMask =%8.8x RAUseRate =%8.8x HighestRate =%d, DecisionRate =%d\n", - pRaInfo->RateID, pRaInfo->RateMask, pRaInfo->RAUseRate, pRaInfo->HighestRate, pRaInfo->DecisionRate)); return 0; } @@ -518,17 +454,10 @@ static void odm_PTDecision_8188E(struct odm_ra_info *pRaInfo) static void odm_RATxRPTTimerSetting(struct odm_dm_struct *dm_odm, u16 minRptTime) { - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, - (" =====>%s()\n", __func__)); - if (dm_odm->CurrminRptTime != minRptTime) { - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, - (" CurrminRptTime = 0x%04x minRptTime = 0x%04x\n", dm_odm->CurrminRptTime, minRptTime)); rtw_rpt_timer_cfg_cmd(dm_odm->Adapter, minRptTime); dm_odm->CurrminRptTime = minRptTime; } - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, - (" <===== %s()\n", __func__)); } int ODM_RAInfo_Init(struct odm_dm_struct *dm_odm, u8 macid) @@ -549,10 +478,6 @@ int ODM_RAInfo_Init(struct odm_dm_struct *dm_odm, u8 macid) max_rate_idx = 0x03; } - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, - ("%s(): WirelessMode:0x%08x , max_raid_idx:0x%02x\n", - __func__, WirelessMode, max_rate_idx)); - pRaInfo->DecisionRate = max_rate_idx; pRaInfo->PreRate = max_rate_idx; pRaInfo->HighestRate = max_rate_idx; @@ -593,7 +518,6 @@ int ODM_RAInfo_Init_all(struct odm_dm_struct *dm_odm) { u8 macid = 0; - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("=====>\n")); dm_odm->CurrminRptTime = 0; for (macid = 0; macid < ODM_ASSOCIATE_ENTRY_NUM; macid++) @@ -606,8 +530,6 @@ u8 ODM_RA_GetShortGI_8188E(struct odm_dm_struct *dm_odm, u8 macid) { if ((!dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM)) return 0; - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, - ("macid =%d SGI =%d\n", macid, dm_odm->RAInfo[macid].RateSGI)); return dm_odm->RAInfo[macid].RateSGI; } @@ -618,8 +540,6 @@ u8 ODM_RA_GetDecisionRate_8188E(struct odm_dm_struct *dm_odm, u8 macid) if ((!dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM)) return 0; DecisionRate = dm_odm->RAInfo[macid].DecisionRate; - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, - (" macid =%d DecisionRate = 0x%x\n", macid, DecisionRate)); return DecisionRate; } @@ -630,8 +550,6 @@ u8 ODM_RA_GetHwPwrStatus_8188E(struct odm_dm_struct *dm_odm, u8 macid) if ((!dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM)) return 0; PTStage = dm_odm->RAInfo[macid].PTStage; - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, - ("macid =%d PTStage = 0x%x\n", macid, PTStage)); return PTStage; } @@ -641,9 +559,6 @@ void ODM_RA_UpdateRateInfo_8188E(struct odm_dm_struct *dm_odm, u8 macid, u8 Rate if ((!dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM)) return; - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, - ("macid =%d RateID = 0x%x RateMask = 0x%x SGIEnable =%d\n", - macid, RateID, RateMask, SGIEnable)); pRaInfo = &dm_odm->RAInfo[macid]; pRaInfo->RateID = RateID; @@ -658,8 +573,6 @@ void ODM_RA_SetRSSI_8188E(struct odm_dm_struct *dm_odm, u8 macid, u8 Rssi) if ((!dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM)) return; - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, - (" macid =%d Rssi =%d\n", macid, Rssi)); pRaInfo = &dm_odm->RAInfo[macid]; pRaInfo->RssiStaRA = Rssi; @@ -680,10 +593,6 @@ void ODM_RA_TxRPT2Handle_8188E(struct odm_dm_struct *dm_odm, u8 *TxRPT_Buf, u16 u32 valid = 0, ItemNum = 0; u16 minRptTime = 0x927c; - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, - ("=====>%s(): valid0 =%d valid1 =%d BufferLength =%d\n", - __func__, macid_entry0, macid_entry1, TxRPT_Len)); - ItemNum = TxRPT_Len >> 3; pBuffer = TxRPT_Buf; @@ -707,13 +616,6 @@ void ODM_RA_TxRPT2Handle_8188E(struct odm_dm_struct *dm_odm, u8 *TxRPT_Buf, u16 pRAInfo->RTY[2] + pRAInfo->RTY[3] + pRAInfo->RTY[4] + pRAInfo->DROP; if (pRAInfo->TOTAL != 0) { - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, - ("macid =%d Total =%d R0 =%d R1 =%d R2 =%d R3 =%d R4 =%d D0 =%d valid0 =%x valid1 =%x\n", - MacId, pRAInfo->TOTAL, - pRAInfo->RTY[0], pRAInfo->RTY[1], - pRAInfo->RTY[2], pRAInfo->RTY[3], - pRAInfo->RTY[4], pRAInfo->DROP, - macid_entry0, macid_entry1)); if (pRAInfo->PTActive) { if (pRAInfo->RAstage < 5) odm_RateDecision_8188E(dm_odm, pRAInfo); @@ -730,20 +632,6 @@ void ODM_RA_TxRPT2Handle_8188E(struct odm_dm_struct *dm_odm, u8 *TxRPT_Buf, u16 } else { odm_RateDecision_8188E(dm_odm, pRAInfo); } - ODM_RT_TRACE(dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, - ("macid =%d R0 =%d R1 =%d R2 =%d R3 =%d R4 =%d drop =%d valid0 =%x RateID =%d SGI =%d\n", - MacId, - pRAInfo->RTY[0], - pRAInfo->RTY[1], - pRAInfo->RTY[2], - pRAInfo->RTY[3], - pRAInfo->RTY[4], - pRAInfo->DROP, - macid_entry0, - pRAInfo->DecisionRate, - pRAInfo->RateSGI)); - } else { - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, (" TOTAL = 0!!!!\n")); } } @@ -755,7 +643,4 @@ void ODM_RA_TxRPT2Handle_8188E(struct odm_dm_struct *dm_odm, u8 *TxRPT_Buf, u16 } while (MacId < ItemNum); odm_RATxRPTTimerSetting(dm_odm, minRptTime); - - ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, - ("<===== %s()\n", __func__)); } diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c index 9585dffc63a3..f09620c54e69 100644 --- a/drivers/staging/rtl8188eu/hal/hal_intf.c +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -23,12 +23,8 @@ uint rtw_hal_init(struct adapter *adapt) rtw_hal_notch_filter(adapt, 1); } else { adapt->hw_init_completed = false; - DBG_88E("%s: hal__init fail\n", __func__); } - RT_TRACE(_module_hal_init_c_, _drv_err_, - ("-rtl871x_hal_init:status=0x%x\n", status)); - return status; } @@ -40,8 +36,6 @@ uint rtw_hal_deinit(struct adapter *adapt) if (status == _SUCCESS) adapt->hw_init_completed = false; - else - DBG_88E("\n %s: hal_init fail\n", __func__); return status; } diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c index 4d659a812aed..ffc5394d5bb9 100644 --- a/drivers/staging/rtl8188eu/hal/odm.c +++ b/drivers/staging/rtl8188eu/hal/odm.c @@ -5,11 +5,11 @@ * ******************************************************************************/ +#include <linux/etherdevice.h> + #include "odm_precomp.h" #include "phy.h" -u32 GlobalDebugLevel; - /* avoid to warn in FreeBSD ==> To DO modify */ static u32 EDCAParam[HT_IOT_PEER_MAX][3] = { /* UL DL */ @@ -147,13 +147,6 @@ u8 CCKSwingTable_Ch14[CCK_TABLE_SIZE][8] = { #define RxDefaultAnt1 0x65a9 #define RxDefaultAnt2 0x569a -void ODM_InitDebugSetting(struct odm_dm_struct *pDM_Odm) -{ - pDM_Odm->DebugLevel = ODM_DBG_TRACE; - - pDM_Odm->DebugComponents = 0; -} - /* 3 Export Interface */ /* 2011/09/21 MH Add to describe different team necessary resource allocate?? */ @@ -161,7 +154,6 @@ void ODM_DMInit(struct odm_dm_struct *pDM_Odm) { /* 2012.05.03 Luke: For all IC series */ odm_CommonInfoSelfInit(pDM_Odm); - odm_CmnInfoInit_Debug(pDM_Odm); odm_DIGInit(pDM_Odm); odm_RateAdaptiveMaskInit(pDM_Odm); @@ -181,8 +173,6 @@ void ODM_DMInit(struct odm_dm_struct *pDM_Odm) void ODM_DMWatchdog(struct odm_dm_struct *pDM_Odm) { /* 2012.05.03 Luke: For all IC series */ - odm_CmnInfoHook_Debug(pDM_Odm); - odm_CmnInfoUpdate_Debug(pDM_Odm); odm_CommonInfoSelfUpdate(pDM_Odm); odm_FalseAlarmCounterStatistics(pDM_Odm); odm_RSSIMonitorCheck(pDM_Odm); @@ -217,8 +207,6 @@ void odm_CommonInfoSelfInit(struct odm_dm_struct *pDM_Odm) pDM_Odm->bCckHighPower = (bool)phy_query_bb_reg(adapter, 0x824, BIT(9)); pDM_Odm->RFPathRxEnable = (u8)phy_query_bb_reg(adapter, 0xc04, 0x0F); - - ODM_InitDebugSetting(pDM_Odm); } void odm_CommonInfoSelfUpdate(struct odm_dm_struct *pDM_Odm) @@ -247,48 +235,6 @@ void odm_CommonInfoSelfUpdate(struct odm_dm_struct *pDM_Odm) pDM_Odm->bOneEntryOnly = false; } -void odm_CmnInfoInit_Debug(struct odm_dm_struct *pDM_Odm) -{ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("%s==>\n", __func__)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportPlatform=%d\n", pDM_Odm->SupportPlatform)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportAbility=0x%x\n", pDM_Odm->SupportAbility)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportInterface=%d\n", pDM_Odm->SupportInterface)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportICType=0x%x\n", pDM_Odm->SupportICType)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("CutVersion=%d\n", pDM_Odm->CutVersion)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("BoardType=%d\n", pDM_Odm->BoardType)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtLNA=%d\n", pDM_Odm->ExtLNA)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtPA=%d\n", pDM_Odm->ExtPA)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtTRSW=%d\n", pDM_Odm->ExtTRSW)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("PatchID=%d\n", pDM_Odm->PatchID)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bInHctTest=%d\n", pDM_Odm->bInHctTest)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bWIFITest=%d\n", pDM_Odm->bWIFITest)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bDualMacSmartConcurrent=%d\n", pDM_Odm->bDualMacSmartConcurrent)); -} - -void odm_CmnInfoHook_Debug(struct odm_dm_struct *pDM_Odm) -{ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("%s==>\n", __func__)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pNumTxBytesUnicast=%llu\n", *pDM_Odm->pNumTxBytesUnicast)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pNumRxBytesUnicast=%llu\n", *pDM_Odm->pNumRxBytesUnicast)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pWirelessMode=0x%x\n", *pDM_Odm->pWirelessMode)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pSecChOffset=%d\n", *pDM_Odm->pSecChOffset)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pSecurity=%d\n", *pDM_Odm->pSecurity)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pBandWidth=%d\n", *pDM_Odm->pBandWidth)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pChannel=%d\n", *pDM_Odm->pChannel)); - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pbScanInProcess=%d\n", *pDM_Odm->pbScanInProcess)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pbPowerSaving=%d\n", *pDM_Odm->pbPowerSaving)); -} - -void odm_CmnInfoUpdate_Debug(struct odm_dm_struct *pDM_Odm) -{ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("%s==>\n", __func__)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bWIFI_Direct=%d\n", pDM_Odm->bWIFI_Direct)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bWIFI_Display=%d\n", pDM_Odm->bWIFI_Display)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bLinked=%d\n", pDM_Odm->bLinked)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("RSSI_Min=%d\n", pDM_Odm->RSSI_Min)); -} - void ODM_Write_DIG(struct odm_dm_struct *pDM_Odm, u8 CurrentIGI) { struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable; @@ -339,23 +285,15 @@ void odm_DIG(struct odm_dm_struct *pDM_Odm) u8 dm_dig_max, dm_dig_min; u8 CurrentIGI = pDM_DigTable->CurIGValue; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("%s()==>\n", __func__)); - if ((!(pDM_Odm->SupportAbility & ODM_BB_DIG)) || (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT))) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("%s() Return: SupportAbility ODM_BB_DIG or ODM_BB_FA_CNT is disabled\n", __func__)); + if ((!(pDM_Odm->SupportAbility & ODM_BB_DIG)) || (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT))) return; - } - if (*pDM_Odm->pbScanInProcess) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("%s() Return: In Scan Progress\n", __func__)); + if (*pDM_Odm->pbScanInProcess) return; - } /* add by Neil Chen to avoid PSD is processing */ - if (!pDM_Odm->bDMInitialGainEnable) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("%s() Return: PSD is Processing\n", __func__)); + if (!pDM_Odm->bDMInitialGainEnable) return; - } DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0; FirstConnect = (pDM_Odm->bLinked) && (!pDM_DigTable->bMediaConnect_0); @@ -382,33 +320,20 @@ void odm_DIG(struct odm_dm_struct *pDM_Odm) DIG_Dynamic_MIN = DIG_MaxOfMin; else DIG_Dynamic_MIN = pDM_Odm->RSSI_Min; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("%s() : bOneEntryOnly=true, DIG_Dynamic_MIN=0x%x\n", - __func__, DIG_Dynamic_MIN)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("%s() : pDM_Odm->RSSI_Min=%d\n", - __func__, pDM_Odm->RSSI_Min)); } else if (pDM_Odm->SupportAbility & ODM_BB_ANT_DIV) { /* 1 Lower Bound for 88E AntDiv */ - if (pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV) { + if (pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV) DIG_Dynamic_MIN = (u8)pDM_DigTable->AntDiv_RSSI_max; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, - ("%s(): pDM_DigTable->AntDiv_RSSI_max=%d\n", - __func__, pDM_DigTable->AntDiv_RSSI_max)); - } } else { DIG_Dynamic_MIN = dm_dig_min; } } else { pDM_DigTable->rx_gain_range_max = dm_dig_max; DIG_Dynamic_MIN = dm_dig_min; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("%s() : No Link\n", __func__)); } /* 1 Modify DIG lower bound, deal with abnormally large false alarm */ if (pFalseAlmCnt->Cnt_all > 10000) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("dm_DIG(): Abnormally false alarm case.\n")); - if (pDM_DigTable->LargeFAHit != 3) pDM_DigTable->LargeFAHit++; if (pDM_DigTable->ForbiddenIGI < CurrentIGI) { @@ -433,27 +358,20 @@ void odm_DIG(struct odm_dm_struct *pDM_Odm) if ((pDM_DigTable->ForbiddenIGI - 1) < DIG_Dynamic_MIN) { /* DM_DIG_MIN) */ pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN; /* DM_DIG_MIN; */ pDM_DigTable->rx_gain_range_min = DIG_Dynamic_MIN; /* DM_DIG_MIN; */ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("%s(): Normal Case: At Lower Bound\n", __func__)); } else { pDM_DigTable->ForbiddenIGI--; pDM_DigTable->rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 1); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("%s(): Normal Case: Approach Lower Bound\n", __func__)); } } else { pDM_DigTable->LargeFAHit = 0; } } } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("%s(): pDM_DigTable->LargeFAHit=%d\n", - __func__, pDM_DigTable->LargeFAHit)); /* 1 Adjust initial gain by false alarm */ if (pDM_Odm->bLinked) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("%s(): DIG AfterLink\n", __func__)); if (FirstConnect) { CurrentIGI = pDM_Odm->RSSI_Min; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("DIG: First Connect\n")); } else { if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2) CurrentIGI = CurrentIGI + 4;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+2; */ @@ -463,10 +381,8 @@ void odm_DIG(struct odm_dm_struct *pDM_Odm) CurrentIGI = CurrentIGI - 2;/* pDM_DigTable->CurIGValue =pDM_DigTable->PreIGValue-1; */ } } else { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("%s(): DIG BeforeLink\n", __func__)); if (FirstDisConnect) { CurrentIGI = pDM_DigTable->rx_gain_range_min; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("%s(): First DisConnect\n", __func__)); } else { /* 2012.03.30 LukeLee: enable DIG before link but with very high thresholds */ if (pFalseAlmCnt->Cnt_all > 10000) @@ -475,24 +391,15 @@ void odm_DIG(struct odm_dm_struct *pDM_Odm) CurrentIGI = CurrentIGI + 1;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+1; */ else if (pFalseAlmCnt->Cnt_all < 500) CurrentIGI = CurrentIGI - 1;/* pDM_DigTable->CurIGValue =pDM_DigTable->PreIGValue-1; */ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("%s(): England DIG\n", __func__)); } } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("%s(): DIG End Adjust IGI\n", __func__)); /* 1 Check initial gain by upper/lower bound */ if (CurrentIGI > pDM_DigTable->rx_gain_range_max) CurrentIGI = pDM_DigTable->rx_gain_range_max; if (CurrentIGI < pDM_DigTable->rx_gain_range_min) CurrentIGI = pDM_DigTable->rx_gain_range_min; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, - ("%s(): rx_gain_range_max=0x%x, rx_gain_range_min=0x%x\n", - __func__, pDM_DigTable->rx_gain_range_max, pDM_DigTable->rx_gain_range_min)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("%s(): TotalFA=%d\n", __func__, pFalseAlmCnt->Cnt_all)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("%s(): CurIGValue=0x%x\n", __func__, CurrentIGI)); - /* 2 High power RSSI threshold */ - ODM_Write_DIG(pDM_Odm, CurrentIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */ pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked; pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN; @@ -556,20 +463,6 @@ void odm_FalseAlarmCounterStatistics(struct odm_dm_struct *pDM_Odm) FalseAlmCnt->Cnt_Cck_fail); FalseAlmCnt->Cnt_CCA_all = FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA; - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Enter %s\n", __func__)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, - ("Cnt_Fast_Fsync=%d, Cnt_SB_Search_fail=%d\n", - FalseAlmCnt->Cnt_Fast_Fsync, FalseAlmCnt->Cnt_SB_Search_fail)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, - ("Cnt_Parity_Fail=%d, Cnt_Rate_Illegal=%d\n", - FalseAlmCnt->Cnt_Parity_Fail, FalseAlmCnt->Cnt_Rate_Illegal)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, - ("Cnt_Crc8_fail=%d, Cnt_Mcs_fail=%d\n", - FalseAlmCnt->Cnt_Crc8_fail, FalseAlmCnt->Cnt_Mcs_fail)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Cck_fail=%d\n", FalseAlmCnt->Cnt_Cck_fail)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Ofdm_fail=%d\n", FalseAlmCnt->Cnt_Ofdm_fail)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Total False Alarm=%d\n", FalseAlmCnt->Cnt_all)); } /* 3============================================================ */ @@ -750,10 +643,6 @@ u32 ODM_Get_Rate_Bitmap(struct odm_dm_struct *pDM_Odm, u32 macid, u32 ra_mask, u break; } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, - (" ==> rssi_level:0x%02x, WirelessMode:0x%02x, rate_bitmap:0x%08x\n", - rssi_level, WirelessMode, rate_bitmap)); - return rate_bitmap; } @@ -775,26 +664,18 @@ void odm_RefreshRateAdaptiveMaskCE(struct odm_dm_struct *pDM_Odm) u8 i; struct adapter *pAdapter = pDM_Odm->Adapter; - if (pAdapter->bDriverStopped) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_TRACE, ("<---- odm_RefreshRateAdaptiveMask(): driver is going to unload\n")); + if (pAdapter->bDriverStopped) return; - } - if (!pDM_Odm->bUseRAMask) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("<---- odm_RefreshRateAdaptiveMask(): driver does not control rate adaptive mask\n")); + if (!pDM_Odm->bUseRAMask) return; - } for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { struct sta_info *pstat = pDM_Odm->pODM_StaInfo[i]; if (IS_STA_VALID(pstat)) { - if (ODM_RAStateCheck(pDM_Odm, pstat->rssi_stat.UndecoratedSmoothedPWDB, false, &pstat->rssi_level)) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, - ("RSSI:%d, RSSI_LEVEL:%d\n", - pstat->rssi_stat.UndecoratedSmoothedPWDB, pstat->rssi_level)); + if (ODM_RAStateCheck(pDM_Odm, pstat->rssi_stat.UndecoratedSmoothedPWDB, false, &pstat->rssi_level)) rtw_hal_update_ra_mask(pAdapter, i, pstat->rssi_level); - } } } } @@ -808,6 +689,7 @@ bool ODM_RAStateCheck(struct odm_dm_struct *pDM_Odm, s32 RSSI, bool bForceUpdate u8 HighRSSIThreshForRA = pRA->HighRSSIThresh; u8 LowRSSIThreshForRA = pRA->LowRSSIThresh; u8 RATRState; + struct device *dev = dvobj_to_dev(adapter_to_dvobj(pDM_Odm->Adapter)); /* Threshold Adjustment: */ /* when RSSI state trends to go up one or two levels, make sure RSSI is high enough. */ @@ -824,7 +706,7 @@ bool ODM_RAStateCheck(struct odm_dm_struct *pDM_Odm, s32 RSSI, bool bForceUpdate LowRSSIThreshForRA += GoUpGap; break; default: - ODM_RT_ASSERT(pDM_Odm, false, ("wrong rssi level setting %d !", *pRATRState)); + dev_err(dev, "%s(): wrong rssi level setting %d!\n", __func__, *pRATRState); break; } @@ -837,7 +719,6 @@ bool ODM_RAStateCheck(struct odm_dm_struct *pDM_Odm, s32 RSSI, bool bForceUpdate RATRState = DM_RATR_STA_LOW; if (*pRATRState != RATRState || bForceUpdate) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("RSSI Level %d -> %d\n", *pRATRState, RATRState)); *pRATRState = RATRState; return true; } @@ -892,7 +773,6 @@ void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm) u8 sta_cnt = 0; u32 PWDB_rssi[NUM_STA] = {0};/* 0~15]:MACID, [16~31]:PWDB_rssi */ struct sta_info *psta; - u8 bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; if (!check_fwstate(&Adapter->mlmepriv, _FW_LINKED)) return; @@ -901,7 +781,7 @@ void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm) psta = pDM_Odm->pODM_StaInfo[i]; if (IS_STA_VALID(psta) && (psta->state & WIFI_ASOC_STATE) && - memcmp(psta->hwaddr, bcast_addr, ETH_ALEN) && + !is_broadcast_ether_addr(psta->hwaddr) && memcmp(psta->hwaddr, myid(&Adapter->eeprompriv), ETH_ALEN)) { if (psta->rssi_stat.UndecoratedSmoothedPWDB < tmpEntryMinPWDB) tmpEntryMinPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB; @@ -945,7 +825,6 @@ void odm_TXPowerTrackingInit(struct odm_dm_struct *pDM_Odm) pDM_Odm->RFCalibrateInfo.TXPowercount = 0; if (*pDM_Odm->mp_mode != 1) pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = true; - MSG_88E("pDM_Odm TxPowerTrackControl = %d\n", pDM_Odm->RFCalibrateInfo.TxPowerTrackControl); pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = true; } @@ -977,20 +856,16 @@ void ODM_TXPowerTrackingCheck(struct odm_dm_struct *pDM_Odm) void odm_InitHybridAntDiv(struct odm_dm_struct *pDM_Odm) { - if (!(pDM_Odm->SupportAbility & ODM_BB_ANT_DIV)) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Return: Not Support HW AntDiv\n")); + if (!(pDM_Odm->SupportAbility & ODM_BB_ANT_DIV)) return; - } rtl88eu_dm_antenna_div_init(pDM_Odm); } void odm_HwAntDiv(struct odm_dm_struct *pDM_Odm) { - if (!(pDM_Odm->SupportAbility & ODM_BB_ANT_DIV)) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Return: Not Support HW AntDiv\n")); + if (!(pDM_Odm->SupportAbility & ODM_BB_ANT_DIV)) return; - } rtl88eu_dm_antenna_diversity(pDM_Odm); } @@ -1003,11 +878,6 @@ void ODM_EdcaTurboInit(struct odm_dm_struct *pDM_Odm) pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false; pDM_Odm->DM_EDCA_Table.bIsCurRDLState = false; Adapter->recvpriv.bIsAnyNonBEPkts = false; - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Original VO PARAM: 0x%x\n", usb_read32(Adapter, ODM_EDCA_VO_PARAM))); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Original VI PARAM: 0x%x\n", usb_read32(Adapter, ODM_EDCA_VI_PARAM))); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Original BE PARAM: 0x%x\n", usb_read32(Adapter, ODM_EDCA_BE_PARAM))); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Original BK PARAM: 0x%x\n", usb_read32(Adapter, ODM_EDCA_BK_PARAM))); } /* ODM_InitEdcaTurbo */ void odm_EdcaTurboCheck(struct odm_dm_struct *pDM_Odm) @@ -1015,13 +885,10 @@ void odm_EdcaTurboCheck(struct odm_dm_struct *pDM_Odm) /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */ /* at the same time. In the stage2/3, we need to prive universal interface and merge all */ /* HW dynamic mechanism. */ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("%s========================>\n", __func__)); - if (!(pDM_Odm->SupportAbility & ODM_MAC_EDCA_TURBO)) return; odm_EdcaTurboCheckCE(pDM_Odm); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("<========================%s\n", __func__)); } /* odm_CheckEdcaTurbo */ void odm_EdcaTurboCheckCE(struct odm_dm_struct *pDM_Odm) diff --git a/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c b/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c index a55a0d8b9fb7..e29cd35a5811 100644 --- a/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c +++ b/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c @@ -307,11 +307,7 @@ void rtl88eu_dm_antenna_diversity(struct odm_dm_struct *dm_odm) return; if (!dm_odm->bLinked) { - ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, - ("ODM_AntennaDiversity_88E(): No Link.\n")); if (dm_fat_tbl->bBecomeLinked) { - ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, - ("Need to Turn off HW AntDiv\n")); phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0); phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N, BIT(15), 0); @@ -324,8 +320,6 @@ void rtl88eu_dm_antenna_diversity(struct odm_dm_struct *dm_odm) } if (!dm_fat_tbl->bBecomeLinked) { - ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, - ("Need to Turn on HW AntDiv\n")); phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 1); phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N, BIT(15), 1); diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c index a664bff370bb..256f87b9d630 100644 --- a/drivers/staging/rtl8188eu/hal/phy.c +++ b/drivers/staging/rtl8188eu/hal/phy.c @@ -162,18 +162,6 @@ static void get_tx_power_index(struct adapter *adapt, u8 channel, u8 *cck_pwr, } } -static void phy_power_index_check(struct adapter *adapt, u8 channel, - u8 *cck_pwr, u8 *ofdm_pwr, u8 *bw20_pwr, - u8 *bw40_pwr) -{ - struct hal_data_8188e *hal_data = adapt->HalData; - - hal_data->CurrentCckTxPwrIdx = cck_pwr[0]; - hal_data->CurrentOfdm24GTxPwrIdx = ofdm_pwr[0]; - hal_data->CurrentBW2024GTxPwrIdx = bw20_pwr[0]; - hal_data->CurrentBW4024GTxPwrIdx = bw40_pwr[0]; -} - void phy_set_tx_power_level(struct adapter *adapt, u8 channel) { u8 cck_pwr[MAX_TX_COUNT] = {0}; @@ -184,9 +172,6 @@ void phy_set_tx_power_level(struct adapter *adapt, u8 channel) get_tx_power_index(adapt, channel, &cck_pwr[0], &ofdm_pwr[0], &bw20_pwr[0], &bw40_pwr[0]); - phy_power_index_check(adapt, channel, &cck_pwr[0], &ofdm_pwr[0], - &bw20_pwr[0], &bw40_pwr[0]); - rtl88eu_phy_rf6052_set_cck_txpower(adapt, &cck_pwr[0]); rtl88eu_phy_rf6052_set_ofdm_txpower(adapt, &ofdm_pwr[0], &bw20_pwr[0], &bw40_pwr[0], channel); @@ -303,10 +288,6 @@ void rtl88eu_dm_txpower_track_adjust(struct odm_dm_struct *dm_odm, u8 type, u8 pwr_value = 0; /* Tx power tracking BB swing table. */ if (type == 0) { /* For OFDM adjust */ - ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, - ("BbSwingIdxOfdm = %d BbSwingFlagOfdm=%d\n", - dm_odm->BbSwingIdxOfdm, dm_odm->BbSwingFlagOfdm)); - if (dm_odm->BbSwingIdxOfdm <= dm_odm->BbSwingIdxOfdmBase) { *direction = 1; pwr_value = dm_odm->BbSwingIdxOfdmBase - @@ -316,12 +297,7 @@ void rtl88eu_dm_txpower_track_adjust(struct odm_dm_struct *dm_odm, u8 type, pwr_value = dm_odm->BbSwingIdxOfdm - dm_odm->BbSwingIdxOfdmBase; } - } else if (type == 1) { /* For CCK adjust. */ - ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, - ("dm_odm->BbSwingIdxCck = %d dm_odm->BbSwingIdxCckBase = %d\n", - dm_odm->BbSwingIdxCck, dm_odm->BbSwingIdxCckBase)); - if (dm_odm->BbSwingIdxCck <= dm_odm->BbSwingIdxCckBase) { *direction = 1; pwr_value = dm_odm->BbSwingIdxCckBase - @@ -343,8 +319,6 @@ void rtl88eu_dm_txpower_track_adjust(struct odm_dm_struct *dm_odm, u8 type, static void dm_txpwr_track_setpwr(struct odm_dm_struct *dm_odm) { if (dm_odm->BbSwingFlagOfdm || dm_odm->BbSwingFlagCck) { - ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, - ("%s CH=%d\n", __func__, *dm_odm->pChannel)); phy_set_tx_power_level(dm_odm->Adapter, *dm_odm->pChannel); dm_odm->BbSwingFlagOfdm = false; dm_odm->BbSwingFlagCck = false; @@ -557,7 +531,6 @@ static u8 phy_path_a_rx_iqk(struct adapter *adapt, bool configPathB) { u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u4tmp; u8 result = 0x00; - struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv; /* 1 Get TXIMR setting */ /* modify RXIQK mode table */ @@ -610,8 +583,6 @@ static u8 phy_path_a_rx_iqk(struct adapter *adapt, bool configPathB) /* 1 RX IQK */ /* modify RXIQK mode table */ - ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, - ("Path-A Rx IQK modify RXIQK mode table 2!\n")); phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000); phy_set_rf_reg(adapt, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0); phy_set_rf_reg(adapt, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000); @@ -650,9 +621,6 @@ static u8 phy_path_a_rx_iqk(struct adapter *adapt, bool configPathB) (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) && (((reg_eac & 0x03FF0000) >> 16) != 0x36)) result |= 0x02; - else - ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, - ("Path A Rx IQK fail!!\n")); return result; } @@ -661,7 +629,6 @@ static u8 phy_path_b_iqk(struct adapter *adapt) { u32 regeac, regeb4, regebc, regec4, regecc; u8 result = 0x00; - struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv; /* One shot, path B LOK & IQK */ phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000002); @@ -686,9 +653,7 @@ static u8 phy_path_b_iqk(struct adapter *adapt) (((regec4 & 0x03FF0000) >> 16) != 0x132) && (((regecc & 0x03FF0000) >> 16) != 0x36)) result |= 0x02; - else - ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, - ODM_DBG_LOUD, ("Path B Rx IQK fail!!\n")); + return result; } @@ -1055,13 +1020,6 @@ static void phy_iq_calibrate(struct adapter *adapt, s32 result[][8], bMaskDWord) & 0x3FF0000) >> 16; break; } - ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, - ("Path A Rx IQK Fail!!\n")); - } - - if (path_a_ok == 0x00) { - ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, - ("Path A IQK failed!!\n")); } if (is2t) { @@ -1089,11 +1047,6 @@ static void phy_iq_calibrate(struct adapter *adapt, s32 result[][8], bMaskDWord) & 0x3FF0000) >> 16; } } - - if (path_b_ok == 0x00) { - ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, - ("Path B IQK failed!!\n")); - } } /* Back to BB mode, load original value */ @@ -1214,8 +1167,6 @@ void rtl88eu_phy_iq_calibrate(struct adapter *adapt, bool recovery) return; if (recovery) { - ODM_RT_TRACE(dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, - ("phy_iq_calibrate: Return due to recovery!\n")); reload_adda_reg(adapt, iqk_bb_reg_92c, dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9); return; @@ -1280,8 +1231,6 @@ void rtl88eu_phy_iq_calibrate(struct adapter *adapt, bool recovery) pathaok = true; pathbok = true; } else { - ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, - ("IQK: FAIL use default value\n")); dm_odm->RFCalibrateInfo.RegE94 = 0x100; dm_odm->RFCalibrateInfo.RegEB4 = 0x100; dm_odm->RFCalibrateInfo.RegE9C = 0x0; diff --git a/drivers/staging/rtl8188eu/hal/pwrseqcmd.c b/drivers/staging/rtl8188eu/hal/pwrseqcmd.c index 34784943a7d1..cec2ff879f5d 100644 --- a/drivers/staging/rtl8188eu/hal/pwrseqcmd.c +++ b/drivers/staging/rtl8188eu/hal/pwrseqcmd.c @@ -25,27 +25,12 @@ u8 rtl88eu_pwrseqcmdparsing(struct adapter *padapter, u8 cut_vers, do { pwrcfgcmd = pwrseqcmd[aryidx]; - RT_TRACE(_module_hal_init_c_, _drv_info_, - ("%s: offset(%#x) cut_msk(%#x)" - " cmd(%#x)" - "msk(%#x) value(%#x)\n", - __func__, - GET_PWR_CFG_OFFSET(pwrcfgcmd), - GET_PWR_CFG_CUT_MASK(pwrcfgcmd), - GET_PWR_CFG_CMD(pwrcfgcmd), - GET_PWR_CFG_MASK(pwrcfgcmd), - GET_PWR_CFG_VALUE(pwrcfgcmd))); - /* Only Handle the command whose CUT is matched */ if (GET_PWR_CFG_CUT_MASK(pwrcfgcmd) & cut_vers) { switch (GET_PWR_CFG_CMD(pwrcfgcmd)) { case PWR_CMD_READ: - RT_TRACE(_module_hal_init_c_, _drv_info_, - ("%s: PWR_CMD_READ\n", __func__)); break; case PWR_CMD_WRITE: - RT_TRACE(_module_hal_init_c_, _drv_info_, - ("%s: PWR_CMD_WRITE\n", __func__)); offset = GET_PWR_CFG_OFFSET(pwrcfgcmd); /* Read the value from system register */ @@ -59,9 +44,6 @@ u8 rtl88eu_pwrseqcmdparsing(struct adapter *padapter, u8 cut_vers, usb_write8(padapter, offset, value); break; case PWR_CMD_POLLING: - RT_TRACE(_module_hal_init_c_, _drv_info_, - ("%s: PWR_CMD_POLLING\n", __func__)); - poll_bit = false; offset = GET_PWR_CFG_OFFSET(pwrcfgcmd); do { @@ -74,15 +56,11 @@ u8 rtl88eu_pwrseqcmdparsing(struct adapter *padapter, u8 cut_vers, else udelay(10); - if (poll_count++ > max_poll_count) { - DBG_88E("Fail to polling Offset[%#x]\n", offset); + if (poll_count++ > max_poll_count) return false; - } } while (!poll_bit); break; case PWR_CMD_DELAY: - RT_TRACE(_module_hal_init_c_, _drv_info_, - ("%s: PWR_CMD_DELAY\n", __func__)); if (GET_PWR_CFG_VALUE(pwrcfgcmd) == PWRSEQ_DELAY_US) udelay(GET_PWR_CFG_OFFSET(pwrcfgcmd)); else @@ -90,12 +68,8 @@ u8 rtl88eu_pwrseqcmdparsing(struct adapter *padapter, u8 cut_vers, break; case PWR_CMD_END: /* When this command is parsed, end the process */ - RT_TRACE(_module_hal_init_c_, _drv_info_, - ("%s: PWR_CMD_END\n", __func__)); return true; default: - RT_TRACE(_module_hal_init_c_, _drv_err_, - ("%s: Unknown CMD!!\n", __func__)); break; } } diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c index 3a0e3d41a404..f2969e160ac3 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c @@ -55,11 +55,8 @@ static s32 FillH2CCmd_88E(struct adapter *adapt, u8 ElementID, u32 CmdLen, u8 *p u32 h2c_cmd_ex = 0; s32 ret = _FAIL; - if (!adapt->bFWReady) { - DBG_88E("%s(): return H2C cmd because fw is not ready\n", - __func__); + if (!adapt->bFWReady) return ret; - } if (!pCmdBuffer) goto exit; @@ -71,10 +68,8 @@ static s32 FillH2CCmd_88E(struct adapter *adapt, u8 ElementID, u32 CmdLen, u8 *p /* pay attention to if race condition happened in H2C cmd setting. */ h2c_box_num = adapt->HalData->LastHMEBoxNum; - if (!_is_fw_read_cmd_down(adapt, h2c_box_num)) { - DBG_88E(" fw read cmd failed...\n"); + if (!_is_fw_read_cmd_down(adapt, h2c_box_num)) goto exit; - } *(u8 *)(&h2c_cmd) = ElementID; @@ -134,9 +129,6 @@ void rtw_hal_add_ra_tid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_le bitmap &= 0x0fffffff; - DBG_88E("%s=> mac_id:%d, raid:%d, ra_bitmap=0x%x, shortGIrate=0x%02x\n", - __func__, macid, raid, bitmap, shortGIrate); - ODM_RA_UpdateRateInfo_8188E(odmpriv, macid, raid, bitmap, shortGIrate); } @@ -146,9 +138,6 @@ void rtl8188e_set_FwPwrMode_cmd(struct adapter *adapt, u8 Mode) struct pwrctrl_priv *pwrpriv = &adapt->pwrctrlpriv; u8 RLBM = 0; /* 0:Min, 1:Max, 2:User define */ - DBG_88E("%s: Mode=%d SmartPS=%d UAPSD=%d\n", __func__, - Mode, pwrpriv->smart_ps, adapt->registrypriv.uapsd_enable); - switch (Mode) { case PS_MODE_ACTIVE: H2CSetPwrMode.Mode = 0; @@ -188,13 +177,8 @@ void rtl8188e_set_FwPwrMode_cmd(struct adapter *adapt, u8 Mode) void rtl8188e_set_FwMediaStatus_cmd(struct adapter *adapt, __le16 mstatus_rpt) { - u8 opmode, macid; u16 mst_rpt = le16_to_cpu(mstatus_rpt); - opmode = (u8)mst_rpt; - macid = (u8)(mst_rpt >> 8); - - DBG_88E("### %s: MStatus=%x MACID=%d\n", __func__, opmode, macid); FillH2CCmd_88E(adapt, H2C_COM_MEDIA_STATUS_RPT, sizeof(mst_rpt), (u8 *)&mst_rpt); } @@ -218,7 +202,7 @@ static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength) ether_addr_copy(pwlanhdr->addr3, cur_network->MacAddress); SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); - SetFrameSubType(pframe, WIFI_BEACON); + SetFrameSubType(pframe, IEEE80211_STYPE_BEACON); pframe += sizeof(struct ieee80211_hdr_3addr); pktlen = sizeof(struct ieee80211_hdr_3addr); @@ -275,10 +259,8 @@ static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength) _ConstructBeacon: - if ((pktlen + TXDESC_SIZE) > 512) { - DBG_88E("beacon frame too large\n"); + if ((pktlen + TXDESC_SIZE) > 512) return; - } *pLength = pktlen; } @@ -297,7 +279,7 @@ static void ConstructPSPoll(struct adapter *adapt, u8 *pframe, u32 *pLength) fctrl = &pwlanhdr->frame_control; *(fctrl) = 0; SetPwrMgt(fctrl); - SetFrameSubType(pframe, WIFI_PSPOLL); + SetFrameSubType(pframe, IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); /* AID. */ SetDuration(pframe, (pmlmeinfo->aid | 0xc000)); @@ -361,7 +343,7 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe, if (bQoS) { struct ieee80211_qos_hdr *pwlanqoshdr; - SetFrameSubType(pframe, WIFI_QOS_DATA_NULL); + SetFrameSubType(pframe, IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC); pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe; SetPriority(&pwlanqoshdr->qos_ctrl, AC); @@ -369,7 +351,7 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe, pktlen = sizeof(struct ieee80211_qos_hdr); } else { - SetFrameSubType(pframe, WIFI_DATA_NULL); + SetFrameSubType(pframe, IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC); pktlen = sizeof(struct ieee80211_hdr_3addr); } @@ -399,7 +381,7 @@ static void ConstructProbeRsp(struct adapter *adapt, u8 *pframe, u32 *pLength, u ether_addr_copy(pwlanhdr->addr3, bssid); SetSeqNum(pwlanhdr, 0); - SetFrameSubType(fctrl, WIFI_PROBERSP); + SetFrameSubType(fctrl, IEEE80211_STYPE_PROBE_RESP); pktlen = sizeof(struct ieee80211_hdr_3addr); pframe += pktlen; @@ -440,12 +422,9 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) struct rsvdpage_loc RsvdPageLoc; struct wlan_bssid_ex *pnetwork; - DBG_88E("%s\n", __func__); ReservedPagePacket = kzalloc(1000, GFP_KERNEL); - if (!ReservedPagePacket) { - DBG_88E("%s: alloc ReservedPagePacket fail!\n", __func__); + if (!ReservedPagePacket) return; - } pxmitpriv = &adapt->xmitpriv; pmlmeext = &adapt->mlmeextpriv; @@ -466,7 +445,6 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) if (PageNeed == 1) PageNeed += 1; PageNum += PageNeed; - adapt->HalData->FwRsvdPageStartOffset = PageNum; BufIndex += PageNeed * 128; @@ -524,7 +502,6 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) rtw_hal_mgnt_xmit(adapt, pmgntframe); - DBG_88E("%s: Set RSVD page location to Fw\n", __func__); FillH2CCmd_88E(adapt, H2C_COM_RSVD_PAGE, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc); exit: @@ -541,8 +518,6 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus) u8 DLBcnCount = 0; u32 poll = 0; - DBG_88E("%s mstatus(%x)\n", __func__, mstatus); - if (mstatus == 1) { /* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */ /* Suggested by filen. Added by tynli. */ @@ -559,10 +534,8 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus) usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL) & (~BIT(3))); usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL) | BIT(4)); - if (haldata->RegFwHwTxQCtrl & BIT(6)) { - DBG_88E("HalDownloadRSVDPage(): There is an Adapter is sending beacon.\n"); + if (haldata->RegFwHwTxQCtrl & BIT(6)) bSendBeacon = true; - } /* Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame. */ usb_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl & (~BIT(6)))); @@ -585,12 +558,6 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus) } while (!bcn_valid && (poll % 10) != 0 && !adapt->bSurpriseRemoved && !adapt->bDriverStopped); } while (!bcn_valid && DLBcnCount <= 100 && !adapt->bSurpriseRemoved && !adapt->bDriverStopped); - if (adapt->bSurpriseRemoved || adapt->bDriverStopped) - ; - else if (!bcn_valid) - DBG_88E("%s: 1 Download RSVD page failed! DLBcnCount:%u, poll:%u\n", __func__, DLBcnCount, poll); - else - DBG_88E("%s: 1 Download RSVD success! DLBcnCount:%u, poll:%u\n", __func__, DLBcnCount, poll); /* */ /* We just can send the reserved page twice during the time that Tx thread is stopped (e.g. pnpsetpower) */ /* because we need to free the Tx BCN Desc which is used by the first reserved page packet. */ @@ -613,10 +580,8 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus) } /* Update RSVD page location H2C to Fw. */ - if (bcn_valid) { + if (bcn_valid) rtw_hal_set_hwreg(adapt, HW_VAR_BCN_VALID, NULL); - DBG_88E("Set RSVD page location to Fw.\n"); - } /* Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli. */ /* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */ diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index 391c59490718..10e88f976163 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -165,11 +165,9 @@ skip_dm: void rtw_hal_dm_init(struct adapter *Adapter) { struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv; - struct odm_dm_struct *podmpriv = &Adapter->HalData->odmpriv; memset(pdmpriv, 0, sizeof(struct dm_priv)); Init_ODM_ComInfo_88E(Adapter); - ODM_InitDebugSetting(podmpriv); } /* Add new function to reset the state of antenna diversity before link. */ diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 95b27b4df705..d1086699f952 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -24,11 +24,8 @@ void iol_mode_enable(struct adapter *padapter, u8 enable) reg_0xf0 = usb_read8(padapter, REG_SYS_CFG); usb_write8(padapter, REG_SYS_CFG, reg_0xf0 | SW_OFFLOAD_EN); - if (!padapter->bFWReady) { - DBG_88E("bFWReady == false call reset 8051...\n"); + if (!padapter->bFWReady) _8051Reset88E(padapter); - } - } else { /* disable initial offload */ reg_0xf0 = usb_read8(padapter, REG_SYS_CFG); @@ -74,7 +71,6 @@ s32 rtl8188e_iol_efuse_patch(struct adapter *padapter) { s32 result = _SUCCESS; - DBG_88E("==> %s\n", __func__); if (rtw_iol_applied(padapter)) { iol_mode_enable(padapter, 1); result = iol_execute(padapter, CMD_READ_EFUSE_MAP); @@ -95,7 +91,6 @@ void _8051Reset88E(struct adapter *padapter) u1bTmp = usb_read8(padapter, REG_SYS_FUNC_EN + 1); usb_write8(padapter, REG_SYS_FUNC_EN + 1, u1bTmp & (~BIT(2))); usb_write8(padapter, REG_SYS_FUNC_EN + 1, u1bTmp | (BIT(2))); - DBG_88E("=====> %s(): 8051 reset success .\n", __func__); } void rtl8188e_InitializeFirmwareVars(struct adapter *padapter) @@ -139,11 +134,9 @@ void rtw_hal_set_odm_var(struct adapter *Adapter, enum hal_odm_variable eVariabl struct sta_info *psta = pValue1; if (bSet) { - DBG_88E("### Set STA_(%d) info\n", psta->mac_id); ODM_CmnInfoPtrArrayHook(podmpriv, ODM_CMNINFO_STA_STATUS, psta->mac_id, psta); ODM_RAInfo_Init(podmpriv, psta->mac_id); } else { - DBG_88E("### Clean STA_(%d) info\n", psta->mac_id); ODM_CmnInfoPtrArrayHook(podmpriv, ODM_CMNINFO_STA_STATUS, psta->mac_id, NULL); } } @@ -161,13 +154,10 @@ void rtw_hal_set_odm_var(struct adapter *Adapter, enum hal_odm_variable eVariabl void rtw_hal_notch_filter(struct adapter *adapter, bool enable) { - if (enable) { - DBG_88E("Enable notch filter\n"); + if (enable) usb_write8(adapter, rOFDM0_RxDSP + 1, usb_read8(adapter, rOFDM0_RxDSP + 1) | BIT(1)); - } else { - DBG_88E("Disable notch filter\n"); + else usb_write8(adapter, rOFDM0_RxDSP + 1, usb_read8(adapter, rOFDM0_RxDSP + 1) & ~BIT(1)); - } } /* */ @@ -191,7 +181,6 @@ static s32 _LLTWrite(struct adapter *padapter, u32 address, u32 data) break; if (count > POLLING_LLT_THRESHOLD) { - RT_TRACE(_module_hal_init_c_, _drv_err_, ("Failed to polling write LLT done at address %d!\n", address)); status = _FAIL; break; } @@ -241,19 +230,8 @@ s32 InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy) void Hal_InitPGData88E(struct adapter *padapter) { - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); - - if (!pEEPROM->bautoload_fail_flag) { /* autoload OK. */ - if (!is_boot_from_eeprom(padapter)) { - /* Read EFUSE real map to shadow. */ - EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI); - } - } else {/* autoload fail */ - RT_TRACE(_module_hci_hal_init_c_, _drv_notice_, ("AutoLoad Fail reported from CR9346!!\n")); - /* update to default value 0xFF */ - if (!is_boot_from_eeprom(padapter)) - EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI); - } + if (!is_boot_from_eeprom(padapter)) + EFUSE_ShadowMapUpdate(padapter); } void Hal_EfuseParseIDCode88E(struct adapter *padapter, u8 *hwinfo) @@ -263,14 +241,10 @@ void Hal_EfuseParseIDCode88E(struct adapter *padapter, u8 *hwinfo) /* Checl 0x8129 again for making sure autoload status!! */ EEPROMId = le16_to_cpu(*((__le16 *)hwinfo)); - if (EEPROMId != RTL_EEPROM_ID) { - DBG_88E("EEPROM ID(%#x) is invalid!!\n", EEPROMId); + if (EEPROMId != RTL_EEPROM_ID) pEEPROM->bautoload_fail_flag = true; - } else { + else pEEPROM->bautoload_fail_flag = false; - } - - DBG_88E("EEPROM ID = 0x%04x\n", EEPROMId); } static void Hal_ReadPowerValueFromPROM_8188E(struct txpowerinfo24g *pwrInfo24G, u8 *PROMContent, bool AutoLoadFail) @@ -404,11 +378,6 @@ void Hal_ReadPowerSavingMode88E(struct adapter *padapter, u8 *hwinfo, bool AutoL /* decide hw if support remote wakeup function */ /* if hw supported, 8051 (SIE) will generate WeakUP signal(D+/D- toggle) when autoresume */ padapter->pwrctrlpriv.bSupportRemoteWakeup = (hwinfo[EEPROM_USB_OPTIONAL_FUNCTION0] & BIT(1)) ? true : false; - - DBG_88E("%s...bHWPwrPindetect(%x)-bHWPowerdown(%x) , bSupportRemoteWakeup(%x)\n", __func__, - padapter->pwrctrlpriv.bHWPwrPindetect, padapter->pwrctrlpriv.bHWPowerdown, padapter->pwrctrlpriv.bSupportRemoteWakeup); - - DBG_88E("### PS params => power_mgnt(%x), usbss_enable(%x) ###\n", padapter->registrypriv.power_mgnt, padapter->registrypriv.usbss_enable); } } @@ -431,21 +400,12 @@ void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *PROMContent, bool Auto pHalData->Index24G_BW40_Base[0][ch] = pwrInfo24G.IndexBW40_Base[0][4]; else pHalData->Index24G_BW40_Base[0][ch] = pwrInfo24G.IndexBW40_Base[0][group]; - - DBG_88E("======= Path %d, Channel %d =======\n", 0, ch); - DBG_88E("Index24G_CCK_Base[%d][%d] = 0x%x\n", 0, ch, pHalData->Index24G_CCK_Base[0][ch]); - DBG_88E("Index24G_BW40_Base[%d][%d] = 0x%x\n", 0, ch, pHalData->Index24G_BW40_Base[0][ch]); } for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { pHalData->CCK_24G_Diff[0][TxCount] = pwrInfo24G.CCK_Diff[0][TxCount]; pHalData->OFDM_24G_Diff[0][TxCount] = pwrInfo24G.OFDM_Diff[0][TxCount]; pHalData->BW20_24G_Diff[0][TxCount] = pwrInfo24G.BW20_Diff[0][TxCount]; pHalData->BW40_24G_Diff[0][TxCount] = pwrInfo24G.BW40_Diff[0][TxCount]; - DBG_88E("======= TxCount %d =======\n", TxCount); - DBG_88E("CCK_24G_Diff[%d][%d] = %d\n", 0, TxCount, pHalData->CCK_24G_Diff[0][TxCount]); - DBG_88E("OFDM_24G_Diff[%d][%d] = %d\n", 0, TxCount, pHalData->OFDM_24G_Diff[0][TxCount]); - DBG_88E("BW20_24G_Diff[%d][%d] = %d\n", 0, TxCount, pHalData->BW20_24G_Diff[0][TxCount]); - DBG_88E("BW40_24G_Diff[%d][%d] = %d\n", 0, TxCount, pHalData->BW40_24G_Diff[0][TxCount]); } /* 2010/10/19 MH Add Regulator recognize for CU. */ @@ -456,7 +416,6 @@ void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *PROMContent, bool Auto } else { pHalData->EEPROMRegulatory = 0; } - DBG_88E("EEPROMRegulatory = 0x%x\n", pHalData->EEPROMRegulatory); } void Hal_EfuseParseXtal_8188E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoadFail) @@ -470,7 +429,6 @@ void Hal_EfuseParseXtal_8188E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoa } else { pHalData->CrystalCap = EEPROM_Default_CrystalCap_88E; } - DBG_88E("CrystalCap: 0x%2x\n", pHalData->CrystalCap); } void Hal_EfuseParseBoardType88E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoadFail) @@ -482,7 +440,6 @@ void Hal_EfuseParseBoardType88E(struct adapter *pAdapter, u8 *hwinfo, bool AutoL & 0xE0) >> 5; else pHalData->BoardType = 0; - DBG_88E("Board Type: 0x%2x\n", pHalData->BoardType); } void Hal_EfuseParseEEPROMVer88E(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail) @@ -496,9 +453,6 @@ void Hal_EfuseParseEEPROMVer88E(struct adapter *padapter, u8 *hwinfo, bool AutoL } else { pHalData->EEPROMVersion = 1; } - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - ("Hal_EfuseParseEEPROMVer(), EEVer = %d\n", - pHalData->EEPROMVersion)); } void rtl8188e_EfuseParseChnlPlan(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail) @@ -508,7 +462,6 @@ void rtl8188e_EfuseParseChnlPlan(struct adapter *padapter, u8 *hwinfo, bool Auto padapter->registrypriv.channel_plan, RT_CHANNEL_DOMAIN_WORLD_WIDE_13, AutoLoadFail); - DBG_88E("mlmepriv.ChannelPlan = 0x%02x\n", padapter->mlmepriv.ChannelPlan); } void Hal_EfuseParseCustomerID88E(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail) @@ -521,7 +474,6 @@ void Hal_EfuseParseCustomerID88E(struct adapter *padapter, u8 *hwinfo, bool Auto pHalData->EEPROMCustomerID = 0; pHalData->EEPROMSubCustomerID = 0; } - DBG_88E("EEPROM Customer ID: 0x%2x\n", pHalData->EEPROMCustomerID); } void Hal_ReadAntennaDiversity88E(struct adapter *pAdapter, u8 *PROMContent, bool AutoLoadFail) @@ -553,7 +505,6 @@ void Hal_ReadAntennaDiversity88E(struct adapter *pAdapter, u8 *PROMContent, bool } else { pHalData->AntDivCfg = 0; } - DBG_88E("EEPROM : AntDivCfg = %x, TRxAntDivType = %x\n", pHalData->AntDivCfg, pHalData->TRxAntDivType); } void Hal_ReadThermalMeter_88E(struct adapter *Adapter, u8 *PROMContent, bool AutoloadFail) @@ -567,8 +518,6 @@ void Hal_ReadThermalMeter_88E(struct adapter *Adapter, u8 *PROMContent, bool Aut pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_88E; if (pHalData->EEPROMThermalMeter == 0xff || AutoloadFail) { - pHalData->bAPKThermalMeterIgnore = true; pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_88E; } - DBG_88E("ThermalMeter = 0x%x\n", pHalData->EEPROMThermalMeter); } diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c index 8669bf097479..05dbd3f08328 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c @@ -156,7 +156,7 @@ void update_recvframe_phyinfo_88e(struct recv_frame *precvframe, myid(&padapter->eeprompriv), ETH_ALEN)); pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID && - (GetFrameSubType(wlanhdr) == WIFI_BEACON); + (GetFrameSubType(wlanhdr) == IEEE80211_STYPE_BEACON); if (pkt_info.bPacketBeacon) { if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE)) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c index 9b8a284544ac..efa8960a7eb5 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c @@ -23,35 +23,3 @@ void handle_txrpt_ccx_88e(struct adapter *adapter, u8 *buf) RTW_SCTX_DONE_CCX_PKT_FAIL); } } - -void _dbg_dump_tx_info(struct adapter *padapter, int frame_tag, - struct tx_desc *ptxdesc) -{ - u8 dmp_txpkt; - bool dump_txdesc = false; - - rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(dmp_txpkt)); - - if (dmp_txpkt == 1) {/* dump txdesc for data frame */ - DBG_88E("dump tx_desc for data frame\n"); - if ((frame_tag & 0x0f) == DATA_FRAMETAG) - dump_txdesc = true; - } else if (dmp_txpkt == 2) {/* dump txdesc for mgnt frame */ - DBG_88E("dump tx_desc for mgnt frame\n"); - if ((frame_tag & 0x0f) == MGNT_FRAMETAG) - dump_txdesc = true; - } - - if (dump_txdesc) { - DBG_88E("=====================================\n"); - DBG_88E("txdw0(0x%08x)\n", ptxdesc->txdw0); - DBG_88E("txdw1(0x%08x)\n", ptxdesc->txdw1); - DBG_88E("txdw2(0x%08x)\n", ptxdesc->txdw2); - DBG_88E("txdw3(0x%08x)\n", ptxdesc->txdw3); - DBG_88E("txdw4(0x%08x)\n", ptxdesc->txdw4); - DBG_88E("txdw5(0x%08x)\n", ptxdesc->txdw5); - DBG_88E("txdw6(0x%08x)\n", ptxdesc->txdw6); - DBG_88E("txdw7(0x%08x)\n", ptxdesc->txdw7); - DBG_88E("=====================================\n"); - } -} diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c index 35806b27fdee..25ce6db3beae 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c @@ -18,7 +18,7 @@ void sw_led_on(struct adapter *padapter, struct LED_871x *pLed) return; led_cfg = usb_read8(padapter, REG_LEDCFG2); usb_write8(padapter, REG_LEDCFG2, (led_cfg & 0xf0) | BIT(5) | BIT(6)); - pLed->bLedOn = true; + pLed->led_on = true; } void sw_led_off(struct adapter *padapter, struct LED_871x *pLed) @@ -37,7 +37,7 @@ void sw_led_off(struct adapter *padapter, struct LED_871x *pLed) led_cfg &= 0xFE; usb_write8(padapter, REG_MAC_PINMUX_CFG, led_cfg); exit: - pLed->bLedOn = false; + pLed->led_on = false; } void rtw_hal_sw_led_init(struct adapter *padapter) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c index 09bc915994db..aa69fc3880b3 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c @@ -31,8 +31,6 @@ int rtw_hal_init_recv_priv(struct adapter *padapter) kcalloc(NR_RECVBUFF, sizeof(struct recv_buf), GFP_KERNEL); if (!precvpriv->precv_buf) { res = _FAIL; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - ("alloc recv_buf fail!\n")); goto exit; } precvbuf = precvpriv->precv_buf; @@ -80,14 +78,6 @@ void rtw_hal_free_recv_priv(struct adapter *padapter) } kfree(precvpriv->precv_buf); - - if (skb_queue_len(&precvpriv->rx_skb_queue)) - DBG_88E(KERN_WARNING "rx_skb_queue not empty\n"); skb_queue_purge(&precvpriv->rx_skb_queue); - - if (skb_queue_len(&precvpriv->free_recv_skb_queue)) - DBG_88E(KERN_WARNING "free_recv_skb_queue not empty, %d\n", - skb_queue_len(&precvpriv->free_recv_skb_queue)); - skb_queue_purge(&precvpriv->free_recv_skb_queue); } diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c index 2866283c211d..1fa558e0de38 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c @@ -287,11 +287,7 @@ static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bag ptxdesc->txdw5 |= cpu_to_le32(0x00300000);/* retry limit = 12 */ ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate)); - } else if ((pxmitframe->frame_tag & 0x0f) == TXAGG_FRAMETAG) { - DBG_88E("pxmitframe->frame_tag == TXAGG_FRAMETAG\n"); } else { - DBG_88E("pxmitframe->frame_tag = %d\n", pxmitframe->frame_tag); - /* offset 4 */ ptxdesc->txdw1 |= cpu_to_le32((4) & 0x3f);/* CAM_ID(MAC_ID) */ @@ -322,7 +318,6 @@ static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bag rtl88eu_dm_set_tx_ant_by_tx_info(odmpriv, pmem, pattrib->mac_id); rtl8188eu_cal_txdesc_chksum(ptxdesc); - _dbg_dump_tx_info(adapt, pxmitframe->frame_tag, ptxdesc); return pull; } @@ -346,15 +341,11 @@ static s32 rtw_dump_xframe(struct adapter *adapt, struct xmit_frame *pxmitframe) rtw_issue_addbareq_cmd(adapt, pxmitframe); mem_addr = pxmitframe->buf_addr; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("%s()\n", __func__)); - for (t = 0; t < pattrib->nr_frags; t++) { if (inner_ret != _SUCCESS && ret == _SUCCESS) ret = _FAIL; if (t != (pattrib->nr_frags - 1)) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("pattrib->nr_frags=%d\n", pattrib->nr_frags)); - sz = pxmitpriv->frag_len; sz = sz - 4 - pattrib->icv_len; } else { @@ -377,8 +368,6 @@ static s32 rtw_dump_xframe(struct adapter *adapt, struct xmit_frame *pxmitframe) rtw_count_tx_stats(adapt, pxmitframe, sz); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_write_port, w_sz=%d\n", w_sz)); - mem_addr += w_sz; mem_addr = (u8 *)round_up((size_t)mem_addr, 4); @@ -413,7 +402,7 @@ static u32 xmitframe_need_length(struct xmit_frame *pxmitframe) bool rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitpriv) { - struct xmit_frame *pxmitframe = NULL; + struct xmit_frame *pxmitframe, *n; struct xmit_frame *pfirstframe = NULL; struct xmit_buf *pxmitbuf; @@ -422,7 +411,7 @@ bool rtl8188eu_xmitframe_complete(struct adapter *adapt, struct sta_info *psta = NULL; struct tx_servq *ptxservq = NULL; - struct list_head *xmitframe_plist = NULL, *xmitframe_phead = NULL; + struct list_head *xmitframe_phead = NULL; u32 pbuf; /* next pkt address */ u32 pbuf_tail; /* last pkt tail */ @@ -435,15 +424,11 @@ bool rtl8188eu_xmitframe_complete(struct adapter *adapt, /* dump frame variable */ u32 ff_hwaddr; - RT_TRACE(_module_rtl8192c_xmit_c_, _drv_info_, ("+xmitframe_complete\n")); - pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); if (!pxmitbuf) return false; /* 3 1. pick up first frame */ - rtw_free_xmitframe(pxmitpriv, pxmitframe); - pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry); if (!pxmitframe) { /* no more xmit frame, release xmit buffer */ @@ -507,12 +492,7 @@ bool rtl8188eu_xmitframe_complete(struct adapter *adapt, spin_lock_bh(&pxmitpriv->lock); xmitframe_phead = get_list_head(&ptxservq->sta_pending); - xmitframe_plist = xmitframe_phead->next; - - while (xmitframe_phead != xmitframe_plist) { - pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list); - xmitframe_plist = xmitframe_plist->next; - + list_for_each_entry_safe(pxmitframe, n, xmitframe_phead, list) { pxmitframe->agg_num = 0; /* not first frame of aggregation */ pxmitframe->pkt_offset = 0; /* not first frame of aggregation, no need to reserve offset */ @@ -627,7 +607,6 @@ bool rtw_hal_xmit(struct adapter *adapt, struct xmit_frame *pxmitframe) if (res == _SUCCESS) { rtw_dump_xframe(adapt, pxmitframe); } else { - DBG_88E("==> %s xmitframe_coalesce failed\n", __func__); rtw_free_xmitbuf(pxmitpriv, pxmitbuf); rtw_free_xmitframe(pxmitpriv, pxmitframe); } @@ -639,7 +618,6 @@ enqueue: spin_unlock_bh(&pxmitpriv->lock); if (res != _SUCCESS) { - RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("pre_xmitframe: enqueue xmitframe fail\n")); rtw_free_xmitframe(pxmitpriv, pxmitframe); /* Trick, make the statistics correct */ diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 80cdcf6f7879..05c67e7d23ad 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -35,7 +35,6 @@ static void _ConfigNormalChipOutEP_8188E(struct adapter *adapt, u8 NumOutPipe) default: break; } - DBG_88E("%s OutEpQueueSel(0x%02x), OutEpNumber(%d)\n", __func__, haldata->OutEpQueueSel, haldata->OutEpNumber); } static bool HalUsbSetQueuePipeMapping8188EUsb(struct adapter *adapt, u8 NumInPipe, u8 NumOutPipe) @@ -90,10 +89,8 @@ u32 rtw_hal_power_on(struct adapter *adapt) return _SUCCESS; if (!rtl88eu_pwrseqcmdparsing(adapt, PWR_CUT_ALL_MSK, - Rtl8188E_NIC_PWR_ON_FLOW)) { - DBG_88E(KERN_ERR "%s: run power on flow fail\n", __func__); + Rtl8188E_NIC_PWR_ON_FLOW)) return _FAIL; - } /* Enable MAC DMA/WMAC/SCHEDULE/SEC block */ /* Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy. Added by tynli. 2011.08.31. */ @@ -594,7 +591,6 @@ static void _InitAntenna_Selection(struct adapter *Adapter) if (haldata->AntDivCfg == 0) return; - DBG_88E("==> %s ....\n", __func__); usb_write32(Adapter, REG_LEDCFG0, usb_read32(Adapter, REG_LEDCFG0) | BIT(23)); phy_set_bb_reg(Adapter, rFPGA0_XAB_RFParameter, BIT(13), 0x01); @@ -603,25 +599,8 @@ static void _InitAntenna_Selection(struct adapter *Adapter) haldata->CurAntenna = Antenna_A; else haldata->CurAntenna = Antenna_B; - DBG_88E("%s,Cur_ant:(%x)%s\n", __func__, haldata->CurAntenna, (haldata->CurAntenna == Antenna_A) ? "Antenna_A" : "Antenna_B"); } -/*----------------------------------------------------------------------------- - * Function: HwSuspendModeEnable92Cu() - * - * Overview: HW suspend mode switch. - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 08/23/2010 MHC HW suspend mode switch test.. - *--------------------------------------------------------------------------- - */ enum rt_rf_power_state RfOnOffDetect(struct adapter *adapt) { u8 val8; @@ -629,12 +608,10 @@ enum rt_rf_power_state RfOnOffDetect(struct adapter *adapt) if (adapt->pwrctrlpriv.bHWPowerdown) { val8 = usb_read8(adapt, REG_HSISR); - DBG_88E("pwrdown, 0x5c(BIT(7))=%02x\n", val8); rfpowerstate = (val8 & BIT(7)) ? rf_off : rf_on; } else { /* rf on/off */ usb_write8(adapt, REG_MAC_PINMUX_CFG, usb_read8(adapt, REG_MAC_PINMUX_CFG) & ~(BIT(3))); val8 = usb_read8(adapt, REG_GPIO_IO_SEL); - DBG_88E("GPIO_IN=%02x\n", val8); rfpowerstate = (val8 & BIT(3)) ? rf_on : rf_off; } return rfpowerstate; @@ -649,11 +626,6 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) struct hal_data_8188e *haldata = Adapter->HalData; struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv; struct registry_priv *pregistrypriv = &Adapter->registrypriv; - unsigned long init_start_time = jiffies; - - #define HAL_INIT_PROFILE_TAG(stage) do {} while (0) - - HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_BEGIN); if (Adapter->pwrctrlpriv.bkeepfwalive) { if (haldata->odmpriv.RFCalibrateInfo.bIQKInitialized) { @@ -669,10 +641,8 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) goto exit; } - HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_PW_ON); status = rtw_hal_power_on(Adapter); if (status == _FAIL) { - RT_TRACE(_module_hci_hal_init_c_, _drv_err_, ("Failed to init power on!\n")); goto exit; } @@ -693,7 +663,6 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) txpktbuf_bndy = WMM_NORMAL_TX_PAGE_BOUNDARY_88E; } - HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC01); _InitQueueReservedPage(Adapter); _InitQueuePriority(Adapter); _InitPageBoundary(Adapter); @@ -701,7 +670,6 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) _InitTxBufferBoundary(Adapter, 0); - HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_DOWNLOAD_FW); if (Adapter->registrypriv.mp_mode == 1) { _InitRxSetting(Adapter); Adapter->bFWReady = false; @@ -709,11 +677,9 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) status = rtl88eu_download_fw(Adapter); if (status) { - DBG_88E("%s: Download Firmware failed!!\n", __func__); Adapter->bFWReady = false; return status; } - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("Initializeadapt8192CSdio(): Download Firmware Success!!\n")); Adapter->bFWReady = true; } rtl8188e_InitializeFirmwareVars(Adapter); @@ -724,23 +690,17 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) rtl88eu_phy_rf_config(Adapter); - HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_EFUSE_PATCH); status = rtl8188e_iol_efuse_patch(Adapter); - if (status == _FAIL) { - DBG_88E("%s rtl8188e_iol_efuse_patch failed\n", __func__); + if (status == _FAIL) goto exit; - } _InitTxBufferBoundary(Adapter, txpktbuf_bndy); - HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_LLTT); status = InitLLTTable(Adapter, txpktbuf_bndy); if (status == _FAIL) { - RT_TRACE(_module_hci_hal_init_c_, _drv_err_, ("Failed to init LLT table\n")); goto exit; } - HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC02); /* Get Rx PHY status in order to report RSSI and others. */ _InitDriverInfoSize(Adapter, DRVINFO_SZ); @@ -782,13 +742,10 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) haldata->RfRegChnlVal[0] = rtw_hal_read_rfreg(Adapter, (enum rf_radio_path)0, RF_CHNLBW, bRFRegOffsetMask); haldata->RfRegChnlVal[1] = rtw_hal_read_rfreg(Adapter, (enum rf_radio_path)1, RF_CHNLBW, bRFRegOffsetMask); - HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_TURN_ON_BLOCK); _BBTurnOnBlock(Adapter); - HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_SECURITY); invalidate_cam_all(Adapter); - HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC11); /* 2010/12/17 MH We need to set TX power according to EFUSE content at first. */ phy_set_tx_power_level(Adapter, haldata->CurrentChannel); @@ -813,7 +770,6 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) /* Nav limit , suggest by scott */ usb_write8(Adapter, 0x652, 0x0); - HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_HAL_DM); rtl8188e_InitHalDm(Adapter); /* 2010/08/11 MH Merge from 8192SE for Minicard init. We need to confirm current radio status */ @@ -837,7 +793,6 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) /* enable tx DMA to drop the redundate data of packet */ usb_write16(Adapter, REG_TXDMA_OFFSET_CHK, (usb_read16(Adapter, REG_TXDMA_OFFSET_CHK) | DROP_DATA_EN)); - HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_IQK); /* 2010/08/26 MH Merge from 8192CE. */ if (pwrctrlpriv->rf_pwrstate == rf_on) { if (haldata->odmpriv.RFCalibrateInfo.bIQKInitialized) { @@ -847,15 +802,11 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) haldata->odmpriv.RFCalibrateInfo.bIQKInitialized = true; } - HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_PW_TRACK); - ODM_TXPowerTrackingCheck(&haldata->odmpriv); - HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_LCK); rtl88eu_phy_lc_calibrate(Adapter); } -/* HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_PABIAS); */ /* _InitPABias(Adapter); */ usb_write8(Adapter, REG_USB_HRPWM, 0); @@ -863,10 +814,6 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) usb_write32(Adapter, REG_FWHW_TXQ_CTRL, usb_read32(Adapter, REG_FWHW_TXQ_CTRL) | BIT(12)); exit: - HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_END); - - DBG_88E("%s in %dms\n", __func__, - jiffies_to_msecs(jiffies - init_start_time)); return status; } @@ -875,8 +822,6 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) { u8 val8; - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("%s\n", __func__)); - /* Stop Tx Report Timer. 0x4EC[Bit1]=b'0 */ val8 = usb_read8(Adapter, REG_TX_RPT_CTRL); usb_write8(Adapter, REG_TX_RPT_CTRL, val8 & (~BIT(1))); @@ -942,12 +887,9 @@ static void rtl8192cu_hw_power_down(struct adapter *adapt) u32 rtl8188eu_hal_deinit(struct adapter *Adapter) { - DBG_88E("==> %s\n", __func__); - usb_write32(Adapter, REG_HIMR_88E, IMR_DISABLED_88E); usb_write32(Adapter, REG_HIMRE_88E, IMR_DISABLED_88E); - DBG_88E("bkeepfwalive(%x)\n", Adapter->pwrctrlpriv.bkeepfwalive); if (Adapter->pwrctrlpriv.bkeepfwalive) { if ((Adapter->pwrctrlpriv.bHWPwrPindetect) && (Adapter->pwrctrlpriv.bHWPowerdown)) rtl8192cu_hw_power_down(Adapter); @@ -971,14 +913,10 @@ u32 rtw_hal_inirp_init(struct adapter *Adapter) status = _SUCCESS; - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, - ("===> usb_inirp_init\n")); - /* issue Rx irp to receive data */ precvbuf = precvpriv->precv_buf; for (i = 0; i < NR_RECVBUFF; i++) { if (!usb_read_port(Adapter, RECV_BULK_IN_ADDR, precvbuf)) { - RT_TRACE(_module_hci_hal_init_c_, _drv_err_, ("usb_rx_init: usb_read_port error\n")); status = _FAIL; goto exit; } @@ -987,9 +925,6 @@ u32 rtw_hal_inirp_init(struct adapter *Adapter) } exit: - - RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("<=== usb_inirp_init\n")); - return status; } @@ -1018,9 +953,6 @@ static void Hal_EfuseParsePIDVID_8188EU(struct adapter *adapt, u8 *hwinfo, bool haldata->EEPROMCustomerID = EEPROM_Default_CustomerID; haldata->EEPROMSubCustomerID = EEPROM_Default_SubCustomerID; } - - DBG_88E("VID = 0x%04X, PID = 0x%04X\n", haldata->EEPROMVID, haldata->EEPROMPID); - DBG_88E("Customer ID: 0x%02X, SubCustomer ID: 0x%02X\n", haldata->EEPROMCustomerID, haldata->EEPROMSubCustomerID); } static void Hal_EfuseParseMACAddr_8188EU(struct adapter *adapt, u8 *hwinfo, bool AutoLoadFail) @@ -1036,8 +968,6 @@ static void Hal_EfuseParseMACAddr_8188EU(struct adapter *adapt, u8 *hwinfo, bool /* Read Permanent MAC address */ memcpy(eeprom->mac_addr, &hwinfo[EEPROM_MAC_ADDR_88EU], ETH_ALEN); } - RT_TRACE(_module_hci_hal_init_c_, _drv_notice_, - ("%s: Permanent Address = %pM\n", __func__, eeprom->mac_addr)); } static void readAdapterInfo_8188EU(struct adapter *adapt) @@ -1070,23 +1000,13 @@ static void _ReadPROMContent(struct adapter *Adapter) eeprom->EepromOrEfuse = (eeValue & BOOT_FROM_EEPROM) ? true : false; eeprom->bautoload_fail_flag = (eeValue & EEPROM_EN) ? false : true; - DBG_88E("Boot from %s, Autoload %s !\n", (eeprom->EepromOrEfuse ? "EEPROM" : "EFUSE"), - (eeprom->bautoload_fail_flag ? "Fail" : "OK")); - Hal_InitPGData88E(Adapter); readAdapterInfo_8188EU(Adapter); } void rtw_hal_read_chip_info(struct adapter *Adapter) { - unsigned long start = jiffies; - - MSG_88E("====> %s\n", __func__); - _ReadPROMContent(Adapter); - - MSG_88E("<==== %s in %d ms\n", __func__, - jiffies_to_msecs(jiffies - start)); } #define GPIO_DEBUG_PORT_NUM 0 @@ -1137,8 +1057,6 @@ static void hw_var_set_opmode(struct adapter *Adapter, u8 variable, u8 *val) val8 |= mode; usb_write8(Adapter, MSR, val8); - DBG_88E("%s()-%d mode = %d\n", __func__, __LINE__, mode); - if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) { StopTxBeacon(Adapter); @@ -1259,7 +1177,6 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) /* For 8190, we select only 24M, 12M, 6M, 11M, 5.5M, 2M, and 1M from the Basic rate. */ /* We do not use other rates. */ hal_set_brate_cfg(val, &BrateCfg); - DBG_88E("HW_VAR_BASIC_RATE: BrateCfg(%#x)\n", BrateCfg); /* 2011.03.30 add by Luke Lee */ /* CCK 2M ACK should be disabled for some BCM and Atheros AP IOT */ @@ -1541,7 +1458,6 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) else AcmCtrl &= (~AcmHw_BeqEn); - DBG_88E("[HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl); usb_write8(Adapter, REG_ACMHWCTRL, AcmCtrl); } break; @@ -1684,9 +1600,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) do { if (!(usb_read32(Adapter, REG_RXPKT_NUM) & RXDMA_IDLE)) break; - } while (trycnt--); - if (trycnt == 0) - DBG_88E("Stop RX DMA failed......\n"); + } while (--trycnt); /* RQPN Load 0 */ usb_write16(Adapter, REG_RQPN_NPQ, 0x0); @@ -1699,13 +1613,11 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) break; case HW_VAR_APFM_ON_MAC: haldata->bMacPwrCtrlOn = *val; - DBG_88E("%s: bMacPwrCtrlOn=%d\n", __func__, haldata->bMacPwrCtrlOn); break; case HW_VAR_TX_RPT_MAX_MACID: { u8 maxMacid = *val; - DBG_88E("### MacID(%d),Set Max Tx RPT MID(%d)\n", maxMacid, maxMacid + 1); usb_write8(Adapter, REG_TX_RPT_CTRL + 1, maxMacid + 1); } break; @@ -1835,27 +1747,6 @@ u8 rtw_hal_get_def_var(struct adapter *Adapter, enum hal_def_variable eVariable, *((u32 *)pValue) = MAX_AMPDU_FACTOR_64K; break; case HW_DEF_RA_INFO_DUMP: - { - u8 entry_id = *((u8 *)pValue); - - if (check_fwstate(&Adapter->mlmepriv, _FW_LINKED)) { - DBG_88E("============ RA status check ===================\n"); - DBG_88E("Mac_id:%d , RateID = %d, RAUseRate = 0x%08x, RateSGI = %d, DecisionRate = 0x%02x ,PTStage = %d\n", - entry_id, - haldata->odmpriv.RAInfo[entry_id].RateID, - haldata->odmpriv.RAInfo[entry_id].RAUseRate, - haldata->odmpriv.RAInfo[entry_id].RateSGI, - haldata->odmpriv.RAInfo[entry_id].DecisionRate, - haldata->odmpriv.RAInfo[entry_id].PTStage); - } - } - break; - case HW_DEF_ODM_DBG_FLAG: - { - struct odm_dm_struct *dm_ocm = &haldata->odmpriv; - - pr_info("dm_ocm->DebugComponents = 0x%llx\n", dm_ocm->DebugComponents); - } break; case HAL_DEF_DBG_DUMP_RXPKT: *((u8 *)pValue) = haldata->bDumpRxPkt; @@ -1919,8 +1810,6 @@ void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level) } rate_bitmap = ODM_Get_Rate_Bitmap(odmpriv, mac_id, mask, rssi_level); - DBG_88E("%s => mac_id:%d, networkType:0x%02x, mask:0x%08x\n\t ==> rssi_level:%d, rate_bitmap:0x%08x\n", - __func__, mac_id, networkType, mask, rssi_level, rate_bitmap); mask &= rate_bitmap; diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 4116051a9a65..3609a44ed078 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -34,7 +34,6 @@ struct qos_priv { }; #include <rtw_mlme.h> -#include <rtw_debug.h> #include <rtw_rf.h> #include <rtw_event.h> #include <rtw_led.h> diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 39df30599a5d..2e3e933781eb 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -117,7 +117,6 @@ enum hal_def_variable { HW_DEF_RA_INFO_DUMP, HAL_DEF_DBG_DUMP_TXPKT, HW_DEF_FA_CNT_DUMP, - HW_DEF_ODM_DBG_FLAG, }; enum hal_odm_variable { diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index cb6940d2aeab..da6245a77d5d 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -546,13 +546,6 @@ enum _PUBLIC_ACTION { ACT_PUBLIC_MAX }; -/* BACK action code */ -enum rtw_ieee80211_back_actioncode { - RTW_WLAN_ACTION_ADDBA_REQ = 0, - RTW_WLAN_ACTION_ADDBA_RESP = 1, - RTW_WLAN_ACTION_DELBA = 2, -}; - /* HT features action code */ enum rtw_ieee80211_ht_actioncode { RTW_WLAN_ACTION_NOTIFY_CH_WIDTH = 0, @@ -566,13 +559,6 @@ enum rtw_ieee80211_ht_actioncode { RTW_WLAN_ACTION_HI_INFO_EXCHG = 8, }; -/* BACK (block-ack) parties */ -enum rtw_ieee80211_back_parties { - RTW_WLAN_BACK_RECIPIENT = 0, - RTW_WLAN_BACK_INITIATOR = 1, - RTW_WLAN_BACK_TIMER = 2, -}; - #define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs) * 00:50:F2 */ diff --git a/drivers/staging/rtl8188eu/include/odm.h b/drivers/staging/rtl8188eu/include/odm.h index d814ce492424..98402cfb1168 100644 --- a/drivers/staging/rtl8188eu/include/odm.h +++ b/drivers/staging/rtl8188eu/include/odm.h @@ -691,8 +691,6 @@ struct odm_dm_struct { bool odm_ready; struct rtl8192cd_priv *fake_priv; - u64 DebugComponents; - u32 DebugLevel; /* ODM HANDLE, DRIVER NEEDS NOT TO HOOK------ */ bool bCckHighPower; diff --git a/drivers/staging/rtl8188eu/include/odm_debug.h b/drivers/staging/rtl8188eu/include/odm_debug.h deleted file mode 100644 index 857c64b8d2f4..000000000000 --- a/drivers/staging/rtl8188eu/include/odm_debug.h +++ /dev/null @@ -1,96 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ - -#ifndef __ODM_DBG_H__ -#define __ODM_DBG_H__ - -/* */ -/* Define the debug levels */ -/* */ -/* 1. DBG_TRACE and DBG_LOUD are used for normal cases. */ -/* They can help SW engineer to develop or trace states changed */ -/* and also help HW enginner to trace every operation to and from HW, */ -/* e.g IO, Tx, Rx. */ -/* */ -/* 2. DBG_WARNNING and DBG_SERIOUS are used for unusual or error cases, */ -/* which help us to debug SW or HW. */ - -/* Never used in a call to ODM_RT_TRACE()! */ -#define ODM_DBG_OFF 1 - -/* Fatal bug. */ -/* For example, Tx/Rx/IO locked up, OS hangs, memory access violation, */ -/* resource allocation failed, unexpected HW behavior, HW BUG and so on. */ -#define ODM_DBG_SERIOUS 2 - -/* Abnormal, rare, or unexpected cases. */ -/* For example, IRP/Packet/OID canceled, device suprisely unremoved and so on. */ -#define ODM_DBG_WARNING 3 - -/* Normal case with useful information about current SW or HW state. */ -/* For example, Tx/Rx descriptor to fill, Tx/Rx descr. completed status, */ -/* SW protocol state change, dynamic mechanism state change and so on. */ -/* */ -#define ODM_DBG_LOUD 4 - -/* Normal case with detail execution flow or information. */ -#define ODM_DBG_TRACE 5 - -/* Define the tracing components */ -/* BB Functions */ -#define ODM_COMP_DIG BIT(0) -#define ODM_COMP_RA_MASK BIT(1) -#define ODM_COMP_DYNAMIC_TXPWR BIT(2) -#define ODM_COMP_FA_CNT BIT(3) -#define ODM_COMP_RSSI_MONITOR BIT(4) -#define ODM_COMP_CCK_PD BIT(5) -#define ODM_COMP_ANT_DIV BIT(6) -#define ODM_COMP_PWR_SAVE BIT(7) -#define ODM_COMP_PWR_TRA BIT(8) -#define ODM_COMP_RATE_ADAPTIVE BIT(9) -#define ODM_COMP_PATH_DIV BIT(10) -#define ODM_COMP_PSD BIT(11) -#define ODM_COMP_DYNAMIC_PRICCA BIT(12) -#define ODM_COMP_RXHP BIT(13) -/* MAC Functions */ -#define ODM_COMP_EDCA_TURBO BIT(16) -#define ODM_COMP_EARLY_MODE BIT(17) -/* RF Functions */ -#define ODM_COMP_TX_PWR_TRACK BIT(24) -#define ODM_COMP_RX_GAIN_TRACK BIT(25) -#define ODM_COMP_CALIBRATION BIT(26) -/* Common Functions */ -#define ODM_COMP_COMMON BIT(30) -#define ODM_COMP_INIT BIT(31) - -/*------------------------Export Marco Definition---------------------------*/ -#define RT_PRINTK(fmt, args...) \ - pr_info("%s(): " fmt, __func__, ## args); - -#ifndef ASSERT - #define ASSERT(expr) -#endif - -#define ODM_RT_TRACE(pDM_Odm, comp, level, fmt) \ - if (((comp) & pDM_Odm->DebugComponents) && \ - (level <= pDM_Odm->DebugLevel)) { \ - pr_info("[ODM-8188E] "); \ - RT_PRINTK fmt; \ - } - -#define ODM_RT_ASSERT(pDM_Odm, expr, fmt) \ - if (!(expr)) { \ - pr_info("Assertion failed! %s at ......\n", #expr); \ - pr_info(" ......%s,%s,line=%d\n", __FILE__, \ - __func__, __LINE__); \ - RT_PRINTK fmt; \ - ASSERT(false); \ - } - -void ODM_InitDebugSetting(struct odm_dm_struct *pDM_Odm); - -#endif /* __ODM_DBG_H__ */ diff --git a/drivers/staging/rtl8188eu/include/odm_precomp.h b/drivers/staging/rtl8188eu/include/odm_precomp.h index 5254d875f96b..eb2b8b613aad 100644 --- a/drivers/staging/rtl8188eu/include/odm_precomp.h +++ b/drivers/staging/rtl8188eu/include/odm_precomp.h @@ -23,7 +23,6 @@ #include "odm.h" #include "odm_hwconfig.h" -#include "odm_debug.h" #include "phydm_regdefine11n.h" #include "hal8188e_rate_adaptive.h" /* for RA,Power training */ @@ -33,8 +32,6 @@ #include "odm_rtl8188e.h" -void odm_CmnInfoHook_Debug(struct odm_dm_struct *pDM_Odm); -void odm_CmnInfoInit_Debug(struct odm_dm_struct *pDM_Odm); void odm_DIGInit(struct odm_dm_struct *pDM_Odm); void odm_RateAdaptiveMaskInit(struct odm_dm_struct *pDM_Odm); void odm_DynamicBBPowerSavingInit(struct odm_dm_struct *pDM_Odm); @@ -42,7 +39,6 @@ void odm_DynamicTxPowerInit(struct odm_dm_struct *pDM_Odm); void odm_TXPowerTrackingInit(struct odm_dm_struct *pDM_Odm); void ODM_EdcaTurboInit(struct odm_dm_struct *pDM_Odm); void odm_SwAntDivInit_NIC(struct odm_dm_struct *pDM_Odm); -void odm_CmnInfoUpdate_Debug(struct odm_dm_struct *pDM_Odm); void odm_CommonInfoSelfUpdate(struct odm_dm_struct *pDM_Odm); void odm_FalseAlarmCounterStatistics(struct odm_dm_struct *pDM_Odm); void odm_DIG(struct odm_dm_struct *pDM_Odm); diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h index 0c4c23be1dd5..2c16d3f33e1c 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h @@ -20,19 +20,6 @@ #include "rtw_sreset.h" #include "odm_precomp.h" -/* Fw Array */ -#define Rtl8188E_FwImageArray Rtl8188EFwImgArray -#define Rtl8188E_FWImgArrayLength Rtl8188EFWImgArrayLength - -#define RTL8188E_FW_UMC_IMG "rtl8188E\\rtl8188efw.bin" -#define RTL8188E_PHY_REG "rtl8188E\\PHY_REG_1T.txt" -#define RTL8188E_PHY_RADIO_A "rtl8188E\\radio_a_1T.txt" -#define RTL8188E_PHY_RADIO_B "rtl8188E\\radio_b_1T.txt" -#define RTL8188E_AGC_TAB "rtl8188E\\AGC_TAB_1T.txt" -#define RTL8188E_PHY_MACREG "rtl8188E\\MAC_REG.txt" -#define RTL8188E_PHY_REG_PG "rtl8188E\\PHY_REG_PG.txt" -#define RTL8188E_PHY_REG_MP "rtl8188E\\PHY_REG_MP.txt" - /* RTL8188E Power Configuration CMDs for USB/SDIO interfaces */ #define Rtl8188E_NIC_PWR_ON_FLOW rtl8188E_power_on_flow #define Rtl8188E_NIC_RF_OFF_FLOW rtl8188E_radio_off_flow @@ -208,7 +195,6 @@ struct hal_data_8188e { u8 bTXPowerDataReadFromEEPORM; u8 EEPROMThermalMeter; - u8 bAPKThermalMeterIgnore; bool EepromOrEfuse; @@ -233,21 +219,10 @@ struct hal_data_8188e { u8 PwrGroupHT20[RF_PATH_MAX][CHANNEL_MAX_NUMBER]; u8 PwrGroupHT40[RF_PATH_MAX][CHANNEL_MAX_NUMBER]; - u8 LegacyHTTxPowerDiff;/* Legacy to HT rate power diff */ - /* The current Tx Power Level */ - u8 CurrentCckTxPwrIdx; - u8 CurrentOfdm24GTxPwrIdx; - u8 CurrentBW2024GTxPwrIdx; - u8 CurrentBW4024GTxPwrIdx; - /* Read/write are allow for following hardware information variables */ u8 framesync; - u32 framesyncC34; - u8 framesyncMonitor; - u8 DefaultInitialGain[4]; u8 pwrGroupCnt; u32 MCSTxPowerLevelOriginalOffset[MAX_PG_GROUP][16]; - u32 CCKTxPowerLevelOriginalOffset; u8 CrystalCap; @@ -280,12 +255,6 @@ struct hal_data_8188e { u8 bDumpRxPkt;/* for debug */ u8 bDumpTxPkt;/* for debug */ - u8 FwRsvdPageStartOffset; /* Reserve page start offset except - * beacon in TxQ. - */ - - /* 2010/08/09 MH Add CU power down mode. */ - bool pwrdown; /* Add for dual MAC 0--Mac0 1--Mac1 */ u32 interfaceIndex; @@ -309,7 +278,6 @@ struct hal_data_8188e { u8 UsbTxAggMode; u8 UsbTxAggDescNum; u16 HwRxPageSize; /* Hardware setting */ - u32 MaxUsbRxAggBlock; enum usb_rx_agg_mode UsbRxAggMode; u8 UsbRxAggBlockCount; /* USB Block count. Block size is diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_spec.h b/drivers/staging/rtl8188eu/include/rtl8188e_spec.h index 55cce1f6bd77..fe0871bbb95f 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_spec.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_spec.h @@ -7,15 +7,8 @@ #ifndef __RTL8188E_SPEC_H__ #define __RTL8188E_SPEC_H__ -/* 8192C Register offset definition */ - -#define HAL_PS_TIMER_INT_DELAY 50 /* 50 microseconds */ -#define HAL_92C_NAV_UPPER_UNIT 128 /* micro-second */ - -#define MAC_ADDR_LEN 6 /* 8188E PKT_BUFF_ACCESS_CTRL value */ #define TXPKT_BUF_SELECT 0x69 -#define RXPKT_BUF_SELECT 0xA5 #define DISABLE_TRXPKT_BUF_ACCESS 0x0 /* 0x0000h ~ 0x00FFh System Configuration */ @@ -52,19 +45,7 @@ #define REG_FSISR 0x0054 #define REG_HSIMR 0x0058 #define REG_HSISR 0x005c -#define REG_GPIO_PIN_CTRL_2 0x0060 /* RTL8723 WIFI/BT/GPS - * Multi-Function GPIO Pin Control. - */ -#define REG_GPIO_IO_SEL_2 0x0062 /* RTL8723 WIFI/BT/GPS - * Multi-Function GPIO Select. - */ #define REG_BB_PAD_CTRL 0x0064 -#define REG_MULTI_FUNC_CTRL 0x0068 /* RTL8723 WIFI/BT/GPS - * Multi-Function control source. - */ -#define REG_GPIO_OUTPUT 0x006c -#define REG_AFE_XTAL_CTRL_EXT 0x0078 /* RTL8188E */ -#define REG_XCK_OUT_CTRL 0x007c /* RTL8188E */ #define REG_MCUFWDL 0x0080 #define REG_WOL_EVENT 0x0081 /* RTL8188E */ #define REG_MCUTSTCFG 0x0084 @@ -172,9 +153,6 @@ #define REG_PCIE_HCPWM 0x0363 /* PCIe CPWM */ #define REG_WATCH_DOG 0x0368 -/* RTL8723 series ------------------------------ */ -#define REG_PCIE_HISR 0x03A0 - /* spec version 11 */ /* 0x0400h ~ 0x047Fh Protocol Configuration */ #define REG_VOQ_INFORMATION 0x0400 @@ -459,34 +437,6 @@ #define GPIO_IO_SEL (REG_GPIO_PIN_CTRL + 2) #define GPIO_MOD (REG_GPIO_PIN_CTRL + 3) -/* 8723/8188E Host System Interrupt Mask Register (offset 0x58, 32 byte) */ -#define HSIMR_GPIO12_0_INT_EN BIT(0) -#define HSIMR_SPS_OCP_INT_EN BIT(5) -#define HSIMR_RON_INT_EN BIT(6) -#define HSIMR_PDN_INT_EN BIT(7) -#define HSIMR_GPIO9_INT_EN BIT(25) - -/* 8723/8188E Host System Interrupt Status Register (offset 0x5C, 32 byte) */ -#define HSISR_GPIO12_0_INT BIT(0) -#define HSISR_SPS_OCP_INT BIT(5) -#define HSISR_RON_INT_EN BIT(6) -#define HSISR_PDNINT BIT(7) -#define HSISR_GPIO9_INT BIT(25) - -/* 8192C (MSR) Media Status Register (Offset 0x4C, 8 bits) */ -/* - * Network Type - * 00: No link - * 01: Link in ad hoc network - * 10: Link in infrastructure network - * 11: AP mode - * Default: 00b. - */ -#define MSR_NOLINK 0x00 -#define MSR_ADHOC 0x01 -#define MSR_INFRA 0x02 -#define MSR_AP 0x03 - /* 88EU (MSR) Media Status Register (Offset 0x4C, 8 bits) */ #define USB_INTR_CONTENT_C2H_OFFSET 0 #define USB_INTR_CONTENT_CPWM1_OFFSET 16 @@ -505,34 +455,6 @@ #define CMD_EFUSE_PATCH_ERR BIT(6) #define CMD_IOCONFIG_ERR BIT(7) -/* 6. Adaptive Control Registers (Offset: 0x0160 - 0x01CF) */ -/* 8192C Response Rate Set Register (offset 0x181, 24bits) */ -#define RRSR_1M BIT(0) -#define RRSR_2M BIT(1) -#define RRSR_5_5M BIT(2) -#define RRSR_11M BIT(3) -#define RRSR_6M BIT(4) -#define RRSR_9M BIT(5) -#define RRSR_12M BIT(6) -#define RRSR_18M BIT(7) -#define RRSR_24M BIT(8) -#define RRSR_36M BIT(9) -#define RRSR_48M BIT(10) -#define RRSR_54M BIT(11) -#define RRSR_MCS0 BIT(12) -#define RRSR_MCS1 BIT(13) -#define RRSR_MCS2 BIT(14) -#define RRSR_MCS3 BIT(15) -#define RRSR_MCS4 BIT(16) -#define RRSR_MCS5 BIT(17) -#define RRSR_MCS6 BIT(18) -#define RRSR_MCS7 BIT(19) - -/* 8192C Response Rate Set Register (offset 0x1BF, 8bits) */ -/* WOL bit information */ -#define HAL92C_WOL_PTK_UPDATE_EVENT BIT(0) -#define HAL92C_WOL_GTK_UPDATE_EVENT BIT(1) - /* 8192C BW_OPMODE bits (Offset 0x203, 8bit) */ #define BW_OPMODE_20MHZ BIT(2) #define BW_OPMODE_5G BIT(1) @@ -565,12 +487,6 @@ #define SCR_TxSecEnable 0x02 #define SCR_RxSecEnable 0x04 -/* 10. Power Save Control Registers (Offset: 0x0260 - 0x02DF) */ -#define WOW_PMEN BIT(0) /* Power management Enable. */ -#define WOW_WOMEN BIT(1) /* WoW function on or off. */ -#define WOW_MAGIC BIT(2) /* Magic packet */ -#define WOW_UWF BIT(3) /* Unicast Wakeup frame. */ - /* 12. Host Interrupt Status Registers (Offset: 0x0300 - 0x030F) */ /* 8188 IMR/ISR bits */ #define IMR_DISABLED_88E 0x0 @@ -648,21 +564,6 @@ So the following defines for 92C is not entire!!!!!! * 0x0600h ~ 0x07FFh WMAC Configuration (512 Bytes) * 0x2000h ~ 0x3FFFh 8051 FW Download Region (8196 Bytes) */ -/* 8192C (TXPAUSE) transmission pause (Offset 0x522, 8 bits) */ -/* Note: - * The bits of stopping AC(VO/VI/BE/BK) queue in datasheet - * RTL8192S/RTL8192C are wrong, - * the correct arragement is VO - Bit0, VI - Bit1, BE - Bit2, - * and BK - Bit3. - * 8723 and 88E may be not correct either in the earlier version. - */ -#define StopBecon BIT(6) -#define StopHigh BIT(5) -#define StopMgt BIT(4) -#define StopBK BIT(3) -#define StopBE BIT(2) -#define StopVI BIT(1) -#define StopVO BIT(0) /* 8192C (RCR) Receive Configuration Register(Offset 0x608, 32 bits) */ #define RCR_APPFCS BIT(31) /* WMAC append FCS after payload */ @@ -695,14 +596,8 @@ So the following defines for 92C is not entire!!!!!! #define RCR_FIFO_OFFSET 13 /* 0xFE00h ~ 0xFE55h USB Configuration */ -#define REG_USB_INFO 0xFE17 -#define REG_USB_SPECIAL_OPTION 0xFE55 -#define REG_USB_DMA_AGG_TO 0xFE5B -#define REG_USB_AGG_TO 0xFE5C -#define REG_USB_AGG_TH 0xFE5D - #define REG_USB_HRPWM 0xFE58 -#define REG_USB_HCPWM 0xFE57 + /* 8192C Register Bit and Content definition */ /* 0x0000h ~ 0x00FFh System Configuration */ @@ -1089,142 +984,6 @@ So the following defines for 92C is not entire!!!!!! #define SCR_TXBCUSEDK BIT(6) /* Force Tx Bcast pkt Use Default Key */ #define SCR_RXBCUSEDK BIT(7) /* Force Rx Bcast pkt Use Default Key */ -/* RTL8188E SDIO Configuration */ - -/* I/O bus domain address mapping */ -#define SDIO_LOCAL_BASE 0x10250000 -#define WLAN_IOREG_BASE 0x10260000 -#define FIRMWARE_FIFO_BASE 0x10270000 -#define TX_HIQ_BASE 0x10310000 -#define TX_MIQ_BASE 0x10320000 -#define TX_LOQ_BASE 0x10330000 -#define RX_RX0FF_BASE 0x10340000 - -/* SDIO host local register space mapping. */ -#define SDIO_LOCAL_MSK 0x0FFF -#define WLAN_IOREG_MSK 0x7FFF -#define WLAN_FIFO_MSK 0x1FFF /* Aggregation Length[12:0] */ -#define WLAN_RX0FF_MSK 0x0003 - -/* Without ref to the SDIO Device ID */ -#define SDIO_WITHOUT_REF_DEVICE_ID 0 -#define SDIO_LOCAL_DEVICE_ID 0 /* 0b[16], 000b[15:13] */ -#define WLAN_TX_HIQ_DEVICE_ID 4 /* 0b[16], 100b[15:13] */ -#define WLAN_TX_MIQ_DEVICE_ID 5 /* 0b[16], 101b[15:13] */ -#define WLAN_TX_LOQ_DEVICE_ID 6 /* 0b[16], 110b[15:13] */ -#define WLAN_RX0FF_DEVICE_ID 7 /* 0b[16], 111b[15:13] */ -#define WLAN_IOREG_DEVICE_ID 8 /* 1b[16] */ - -/* SDIO Tx Free Page Index */ -#define HI_QUEUE_IDX 0 -#define MID_QUEUE_IDX 1 -#define LOW_QUEUE_IDX 2 -#define PUBLIC_QUEUE_IDX 3 - -#define SDIO_MAX_TX_QUEUE 3 /* HIQ, MIQ and LOQ */ -#define SDIO_MAX_RX_QUEUE 1 - -/* SDIO Tx Control */ -#define SDIO_REG_TX_CTRL 0x0000 -/* SDIO Host Interrupt Mask */ -#define SDIO_REG_HIMR 0x0014 -/* SDIO Host Interrupt Service Routine */ -#define SDIO_REG_HISR 0x0018 -/* HCI Current Power Mode */ -#define SDIO_REG_HCPWM 0x0019 -/* RXDMA Request Length */ -#define SDIO_REG_RX0_REQ_LEN 0x001C -/* Free Tx Buffer Page */ -#define SDIO_REG_FREE_TXPG 0x0020 -/* HCI Current Power Mode 1 */ -#define SDIO_REG_HCPWM1 0x0024 -/* HCI Current Power Mode 2 */ -#define SDIO_REG_HCPWM2 0x0026 -/* HTSF Informaion */ -#define SDIO_REG_HTSFR_INFO 0x0030 -/* HCI Request Power Mode 1 */ -#define SDIO_REG_HRPWM1 0x0080 -/* HCI Request Power Mode 2 */ -#define SDIO_REG_HRPWM2 0x0082 -/* HCI Power Save Clock */ -#define SDIO_REG_HPS_CLKR 0x0084 -/* SDIO HCI Suspend Control */ -#define SDIO_REG_HSUS_CTRL 0x0086 -/* SDIO Host Extension Interrupt Mask Always */ -#define SDIO_REG_HIMR_ON 0x0090 -/* SDIO Host Extension Interrupt Status Always */ -#define SDIO_REG_HISR_ON 0x0091 - -#define SDIO_HIMR_DISABLED 0 - -/* RTL8188E SDIO Host Interrupt Mask Register */ -#define SDIO_HIMR_RX_REQUEST_MSK BIT(0) -#define SDIO_HIMR_AVAL_MSK BIT(1) -#define SDIO_HIMR_TXERR_MSK BIT(2) -#define SDIO_HIMR_RXERR_MSK BIT(3) -#define SDIO_HIMR_TXFOVW_MSK BIT(4) -#define SDIO_HIMR_RXFOVW_MSK BIT(5) -#define SDIO_HIMR_TXBCNOK_MSK BIT(6) -#define SDIO_HIMR_TXBCNERR_MSK BIT(7) -#define SDIO_HIMR_BCNERLY_INT_MSK BIT(16) -#define SDIO_HIMR_C2HCMD_MSK BIT(17) -#define SDIO_HIMR_CPWM1_MSK BIT(18) -#define SDIO_HIMR_CPWM2_MSK BIT(19) -#define SDIO_HIMR_HSISR_IND_MSK BIT(20) -#define SDIO_HIMR_GTINT3_IND_MSK BIT(21) -#define SDIO_HIMR_GTINT4_IND_MSK BIT(22) -#define SDIO_HIMR_PSTIMEOUT_MSK BIT(23) -#define SDIO_HIMR_OCPINT_MSK BIT(24) -#define SDIO_HIMR_ATIMEND_MSK BIT(25) -#define SDIO_HIMR_ATIMEND_E_MSK BIT(26) -#define SDIO_HIMR_CTWEND_MSK BIT(27) - -/* RTL8188E SDIO Specific */ -#define SDIO_HIMR_MCU_ERR_MSK BIT(28) -#define SDIO_HIMR_TSF_BIT32_TOGGLE_MSK BIT(29) - -/* SDIO Host Interrupt Service Routine */ -#define SDIO_HISR_RX_REQUEST BIT(0) -#define SDIO_HISR_AVAL BIT(1) -#define SDIO_HISR_TXERR BIT(2) -#define SDIO_HISR_RXERR BIT(3) -#define SDIO_HISR_TXFOVW BIT(4) -#define SDIO_HISR_RXFOVW BIT(5) -#define SDIO_HISR_TXBCNOK BIT(6) -#define SDIO_HISR_TXBCNERR BIT(7) -#define SDIO_HISR_BCNERLY_INT BIT(16) -#define SDIO_HISR_C2HCMD BIT(17) -#define SDIO_HISR_CPWM1 BIT(18) -#define SDIO_HISR_CPWM2 BIT(19) -#define SDIO_HISR_HSISR_IND BIT(20) -#define SDIO_HISR_GTINT3_IND BIT(21) -#define SDIO_HISR_GTINT4_IND BIT(22) -#define SDIO_HISR_PSTIME BIT(23) -#define SDIO_HISR_OCPINT BIT(24) -#define SDIO_HISR_ATIMEND BIT(25) -#define SDIO_HISR_ATIMEND_E BIT(26) -#define SDIO_HISR_CTWEND BIT(27) - -/* RTL8188E SDIO Specific */ -#define SDIO_HISR_MCU_ERR BIT(28) -#define SDIO_HISR_TSF_BIT32_TOGGLE BIT(29) - -#define MASK_SDIO_HISR_CLEAR \ - (SDIO_HISR_TXERR | SDIO_HISR_RXERR | SDIO_HISR_TXFOVW |\ - SDIO_HISR_RXFOVW | SDIO_HISR_TXBCNOK | SDIO_HISR_TXBCNERR |\ - SDIO_HISR_C2HCMD | SDIO_HISR_CPWM1 | SDIO_HISR_CPWM2 |\ - SDIO_HISR_HSISR_IND | SDIO_HISR_GTINT3_IND | SDIO_HISR_GTINT4_IND |\ - SDIO_HISR_PSTIMEOUT | SDIO_HISR_OCPINT) - -/* SDIO HCI Suspend Control Register */ -#define HCI_RESUME_PWR_RDY BIT(1) -#define HCI_SUS_CTRL BIT(0) - -/* SDIO Tx FIFO related */ -/* The number of Tx FIFO free page */ -#define SDIO_TX_FREE_PG_QUEUE 4 -#define SDIO_TX_FIFO_PAGE_SZ 128 - /* 0xFE00h ~ 0xFE55h USB Configuration */ /* 2 USB Information (0xFE17) */ @@ -1276,14 +1035,6 @@ So the following defines for 92C is not entire!!!!!! /* GPS function enable */ #define GPS_FUNC_EN BIT(22) -/* 3 REG_LIFECTRL_CTRL */ -#define HAL92C_EN_PKT_LIFE_TIME_BK BIT(3) -#define HAL92C_EN_PKT_LIFE_TIME_BE BIT(2) -#define HAL92C_EN_PKT_LIFE_TIME_VI BIT(1) -#define HAL92C_EN_PKT_LIFE_TIME_VO BIT(0) - -#define HAL92C_MSDU_LIFE_TIME_UNIT 128 /* in us */ - /* General definitions */ #define LAST_ENTRY_OF_TX_PKT_BUFFER 176 /* 22k 22528 bytes */ @@ -1309,48 +1060,15 @@ So the following defines for 92C is not entire!!!!!! #define EEPROM_CUSTOMERID_88E 0xC5 #define EEPROM_RF_ANTENNA_OPT_88E 0xC9 -/* RTL88EE */ -#define EEPROM_MAC_ADDR_88EE 0xD0 -#define EEPROM_VID_88EE 0xD6 -#define EEPROM_DID_88EE 0xD8 -#define EEPROM_SVID_88EE 0xDA -#define EEPROM_SMID_88EE 0xDC - /* RTL88EU */ #define EEPROM_MAC_ADDR_88EU 0xD7 #define EEPROM_VID_88EU 0xD0 #define EEPROM_PID_88EU 0xD2 #define EEPROM_USB_OPTIONAL_FUNCTION0 0xD4 -/* RTL88ES */ -#define EEPROM_MAC_ADDR_88ES 0x11A - /* EEPROM/Efuse Value Type */ #define EETYPE_TX_PWR 0x0 -/* Default Value for EEPROM or EFUSE!!! */ -#define EEPROM_Default_TSSI 0x0 -#define EEPROM_Default_TxPowerDiff 0x0 -#define EEPROM_Default_CrystalCap 0x5 -/* Default: 2X2, RTL8192CE(QFPN68) */ -#define EEPROM_Default_BoardType 0x02 -#define EEPROM_Default_TxPower 0x1010 -#define EEPROM_Default_HT2T_TxPwr 0x10 - -#define EEPROM_Default_LegacyHTTxPowerDiff 0x3 -#define EEPROM_Default_ThermalMeter 0x12 - -#define EEPROM_Default_AntTxPowerDiff 0x0 -#define EEPROM_Default_TxPwDiff_CrystalCap 0x5 -#define EEPROM_Default_TxPowerLevel 0x2A - -#define EEPROM_Default_HT40_2SDiff 0x0 -/* HT20<->40 default Tx Power Index Difference */ -#define EEPROM_Default_HT20_Diff 2 -#define EEPROM_Default_LegacyHTTxPowerDiff 0x3 -#define EEPROM_Default_HT40_PwrMaxOffset 0 -#define EEPROM_Default_HT20_PwrMaxOffset 0 - #define EEPROM_Default_CrystalCap_88E 0x20 #define EEPROM_Default_ThermalMeter_88E 0x18 diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h b/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h index 617c2273b41b..72a2bb812c9a 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h @@ -154,7 +154,4 @@ bool rtl8188eu_xmitframe_complete(struct adapter *padapter, void handle_txrpt_ccx_88e(struct adapter *adapter, u8 *buf); -void _dbg_dump_tx_info(struct adapter *padapter, int frame_tag, - struct tx_desc *ptxdesc); - #endif /* __RTL8188E_XMIT_H__ */ diff --git a/drivers/staging/rtl8188eu/include/rtw_android.h b/drivers/staging/rtl8188eu/include/rtw_android.h index d7ca7c2fb118..2c26993b8205 100644 --- a/drivers/staging/rtl8188eu/include/rtw_android.h +++ b/drivers/staging/rtl8188eu/include/rtw_android.h @@ -45,7 +45,6 @@ enum ANDROID_WIFI_CMD { ANDROID_WIFI_CMD_MAX }; -int rtw_android_cmdstr_to_num(char *cmdstr); int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd); #endif /* __RTW_ANDROID_H__ */ diff --git a/drivers/staging/rtl8188eu/include/rtw_cmd.h b/drivers/staging/rtl8188eu/include/rtw_cmd.h index 68b8ad1a412f..4e9cb93e4b8f 100644 --- a/drivers/staging/rtl8188eu/include/rtw_cmd.h +++ b/drivers/staging/rtl8188eu/include/rtw_cmd.h @@ -32,10 +32,7 @@ struct cmd_obj { struct cmd_priv { struct completion cmd_queue_comp; - struct completion terminate_cmdthread_comp; struct __queue cmd_queue; - u8 cmdthd_running; - struct adapter *padapter; }; #define init_h2fwcmd_w_parm_no_rsp(pcmd, pparm, code) \ @@ -54,7 +51,7 @@ void rtw_free_cmd_obj(struct cmd_obj *pcmd); int rtw_cmd_thread(void *context); -int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv); +void rtw_init_cmd_priv(struct cmd_priv *pcmdpriv); enum rtw_drvextra_cmd_id { NONE_WK_CID, diff --git a/drivers/staging/rtl8188eu/include/rtw_debug.h b/drivers/staging/rtl8188eu/include/rtw_debug.h deleted file mode 100644 index 1fdf16124a0d..000000000000 --- a/drivers/staging/rtl8188eu/include/rtw_debug.h +++ /dev/null @@ -1,131 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTW_DEBUG_H__ -#define __RTW_DEBUG_H__ - -#include <osdep_service.h> -#include <drv_types.h> - -#define DRIVERVERSION "v4.1.4_6773.20130222" -#define _drv_always_ 1 -#define _drv_emerg_ 2 -#define _drv_alert_ 3 -#define _drv_crit_ 4 -#define _drv_err_ 5 -#define _drv_warning_ 6 -#define _drv_notice_ 7 -#define _drv_info_ 8 -#define _drv_debug_ 9 - -#define _module_rtl871x_xmit_c_ BIT(0) -#define _module_xmit_osdep_c_ BIT(1) -#define _module_rtl871x_recv_c_ BIT(2) -#define _module_recv_osdep_c_ BIT(3) -#define _module_rtl871x_mlme_c_ BIT(4) -#define _module_mlme_osdep_c_ BIT(5) -#define _module_rtl871x_sta_mgt_c_ BIT(6) -#define _module_rtl871x_cmd_c_ BIT(7) -#define _module_cmd_osdep_c_ BIT(8) -#define _module_rtl871x_io_c_ BIT(9) -#define _module_io_osdep_c_ BIT(10) -#define _module_os_intfs_c_ BIT(11) -#define _module_rtl871x_security_c_ BIT(12) -#define _module_rtl871x_eeprom_c_ BIT(13) -#define _module_hal_init_c_ BIT(14) -#define _module_hci_hal_init_c_ BIT(15) -#define _module_rtl871x_ioctl_c_ BIT(16) -#define _module_rtl871x_ioctl_set_c_ BIT(17) -#define _module_rtl871x_ioctl_query_c_ BIT(18) -#define _module_rtl871x_pwrctrl_c_ BIT(19) -#define _module_hci_intfs_c_ BIT(20) -#define _module_hci_ops_c_ BIT(21) -#define _module_osdep_service_c_ BIT(22) -#define _module_mp_ BIT(23) -#define _module_hci_ops_os_c_ BIT(24) -#define _module_rtl871x_ioctl_os_c BIT(25) -#define _module_rtl8712_cmd_c_ BIT(26) -#define _module_rtl8192c_xmit_c_ BIT(27) -#define _module_hal_xmit_c_ BIT(28) -#define _module_efuse_ BIT(29) -#define _module_rtl8712_recv_c_ BIT(30) -#define _module_rtl8712_led_c_ BIT(31) - -#define DRIVER_PREFIX "R8188EU: " - -extern u32 GlobalDebugLevel; - -#define DBG_88E_LEVEL(_level, fmt, arg...) \ - do { \ - if (_level <= GlobalDebugLevel) \ - pr_info(DRIVER_PREFIX fmt, ##arg); \ - } while (0) - -#define DBG_88E(...) \ - do { \ - if (_drv_err_ <= GlobalDebugLevel) \ - pr_info(DRIVER_PREFIX __VA_ARGS__); \ - } while (0) - -#define MSG_88E(...) \ - do { \ - if (_drv_err_ <= GlobalDebugLevel) \ - pr_info(DRIVER_PREFIX __VA_ARGS__); \ - } while (0) - -#define RT_TRACE(_comp, _level, fmt) \ - do { \ - if (_level <= GlobalDebugLevel) { \ - pr_info("%s [0x%08x,%d]", DRIVER_PREFIX, \ - (unsigned int)_comp, _level); \ - pr_info fmt; \ - } \ - } while (0) - -#define RT_PRINT_DATA(_comp, _level, _titlestring, _hexdata, _hexdatalen)\ - do { \ - if (_level <= GlobalDebugLevel) { \ - int __i; \ - u8 *ptr = (u8 *)_hexdata; \ - pr_info("%s", DRIVER_PREFIX); \ - pr_info(_titlestring); \ - for (__i = 0; __i < (int)_hexdatalen; __i++) { \ - pr_info("%02X%s", ptr[__i], \ - (((__i + 1) % 4) == 0) ? \ - " " : " "); \ - if (((__i + 1) % 16) == 0) \ - pr_cont("\n"); \ - } \ - pr_cont("\n"); \ - } \ - } while (0) - -int proc_get_drv_version(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_write_reg(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_set_write_reg(struct file *file, const char __user *buffer, - unsigned long count, void *data); -int proc_get_read_reg(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_set_read_reg(struct file *file, const char __user *buffer, - unsigned long count, void *data); - -int proc_get_adapter_state(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -int proc_get_best_channel(char *page, char **start, - off_t offset, int count, - int *eof, void *data); - -#endif /* __RTW_DEBUG_H__ */ diff --git a/drivers/staging/rtl8188eu/include/rtw_efuse.h b/drivers/staging/rtl8188eu/include/rtw_efuse.h index 74182c32c4ec..bb5e2b5d4bf1 100644 --- a/drivers/staging/rtl8188eu/include/rtw_efuse.h +++ b/drivers/staging/rtl8188eu/include/rtw_efuse.h @@ -23,9 +23,6 @@ #define PGPKT_DATA_SIZE 8 -#define EFUSE_WIFI 0 -#define EFUSE_BT 1 - /* E-Fuse */ #define EFUSE_MAP_SIZE 512 #define EFUSE_MAX_SIZE 256 @@ -60,13 +57,11 @@ u8 Efuse_CalculateWordCnts(u8 word_en); u8 efuse_OneByteRead(struct adapter *adapter, u16 addr, u8 *data); u8 efuse_OneByteWrite(struct adapter *adapter, u16 addr, u8 data); -void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, - u16 _size_byte, u8 *pbuf); int Efuse_PgPacketRead(struct adapter *adapt, u8 offset, u8 *data); bool Efuse_PgPacketWrite(struct adapter *adapter, u8 offset, u8 word, u8 *data); void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata); u8 Efuse_WordEnableDataWrite(struct adapter *adapter, u16 efuse_addr, u8 word_en, u8 *data); -void EFUSE_ShadowMapUpdate(struct adapter *adapter, u8 efusetype); +void EFUSE_ShadowMapUpdate(struct adapter *adapter); #endif diff --git a/drivers/staging/rtl8188eu/include/rtw_led.h b/drivers/staging/rtl8188eu/include/rtw_led.h index ee62ed76a465..5f65c3e1e46f 100644 --- a/drivers/staging/rtl8188eu/include/rtw_led.h +++ b/drivers/staging/rtl8188eu/include/rtw_led.h @@ -52,7 +52,7 @@ struct LED_871x { * either RTW_LED_ON or RTW_LED_OFF are. */ - u8 bLedOn; /* true if LED is ON, false if LED is OFF. */ + u8 led_on; /* true if LED is ON, false if LED is OFF. */ u8 bLedBlinkInProgress; /* true if it is blinking, false o.w.. */ diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme.h b/drivers/staging/rtl8188eu/include/rtw_mlme.h index 1b74b32b8a81..2f02316906d0 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme.h @@ -111,8 +111,6 @@ struct mlme_priv { u8 to_join; /* flag */ u8 to_roaming; /* roaming trying times */ - u8 *nic_hdl; - struct list_head *pscanned; struct __queue free_bss_pool; struct __queue scanned_queue; @@ -222,8 +220,6 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf); void rtw_joinbss_event_callback(struct adapter *adapter, u8 *pbuf); void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf); void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf); -void rtw_atimdone_event_callback(struct adapter *adapter, u8 *pbuf); -void rtw_cpwm_event_callback(struct adapter *adapter, u8 *pbuf); void indicate_wx_scan_complete_event(struct adapter *padapter); void rtw_indicate_wx_assoc_event(struct adapter *padapter); void rtw_indicate_wx_disassoc_event(struct adapter *padapter); diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h index 03d55eb7dc16..c4fcfa986726 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h @@ -383,7 +383,6 @@ struct p2p_oper_class_map { }; struct mlme_ext_priv { - struct adapter *padapter; u8 mlmeext_init; atomic_t event_seq; u16 mgnt_seq; @@ -662,7 +661,7 @@ static struct fwevent wlanevents[] = { {0, &rtw_joinbss_event_callback}, /*10*/ {sizeof(struct stassoc_event), &rtw_stassoc_event_callback}, {sizeof(struct stadel_event), &rtw_stadel_event_callback}, - {0, &rtw_atimdone_event_callback}, + {0, NULL}, {0, rtw_dummy_event_callback}, {0, NULL}, /*15*/ {0, NULL}, @@ -672,7 +671,7 @@ static struct fwevent wlanevents[] = { {0, NULL}, /*20*/ {0, NULL}, {0, NULL}, - {0, &rtw_cpwm_event_callback}, + {0, NULL}, {0, NULL}, }; diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h index e20bab41708a..8c906b666b62 100644 --- a/drivers/staging/rtl8188eu/include/rtw_recv.h +++ b/drivers/staging/rtl8188eu/include/rtw_recv.h @@ -231,8 +231,7 @@ struct recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue); struct recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue); void rtw_init_recvframe(struct recv_frame *precvframe, struct recv_priv *precvpriv); -int rtw_free_recvframe(struct recv_frame *precvframe, - struct __queue *pfree_recv_queue); +void rtw_free_recvframe(struct recv_frame *precvframe, struct __queue *pfree_recv_queue); #define rtw_dequeue_recvframe(queue) rtw_alloc_recvframe(queue) int _rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue); diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h index 84e17330628e..716fec036e54 100644 --- a/drivers/staging/rtl8188eu/include/wifi.h +++ b/drivers/staging/rtl8188eu/include/wifi.h @@ -25,42 +25,6 @@ enum WIFI_FRAME_TYPE { WIFI_QOS_DATA_TYPE = (BIT(7) | BIT(3)), /* QoS Data */ }; -enum WIFI_FRAME_SUBTYPE { - /* below is for mgt frame */ - WIFI_ASSOCREQ = (0 | WIFI_MGT_TYPE), - WIFI_ASSOCRSP = (BIT(4) | WIFI_MGT_TYPE), - WIFI_REASSOCREQ = (BIT(5) | WIFI_MGT_TYPE), - WIFI_REASSOCRSP = (BIT(5) | BIT(4) | WIFI_MGT_TYPE), - WIFI_PROBEREQ = (BIT(6) | WIFI_MGT_TYPE), - WIFI_PROBERSP = (BIT(6) | BIT(4) | WIFI_MGT_TYPE), - WIFI_BEACON = (BIT(7) | WIFI_MGT_TYPE), - WIFI_ATIM = (BIT(7) | BIT(4) | WIFI_MGT_TYPE), - WIFI_DISASSOC = (BIT(7) | BIT(5) | WIFI_MGT_TYPE), - WIFI_AUTH = (BIT(7) | BIT(5) | BIT(4) | WIFI_MGT_TYPE), - WIFI_DEAUTH = (BIT(7) | BIT(6) | WIFI_MGT_TYPE), - WIFI_ACTION = (BIT(7) | BIT(6) | BIT(4) | WIFI_MGT_TYPE), - - /* below is for control frame */ - WIFI_PSPOLL = (BIT(7) | BIT(5) | WIFI_CTRL_TYPE), - WIFI_RTS = (BIT(7) | BIT(5) | BIT(4) | WIFI_CTRL_TYPE), - WIFI_CTS = (BIT(7) | BIT(6) | WIFI_CTRL_TYPE), - WIFI_ACK = (BIT(7) | BIT(6) | BIT(4) | WIFI_CTRL_TYPE), - WIFI_CFEND = (BIT(7) | BIT(6) | BIT(5) | WIFI_CTRL_TYPE), - WIFI_CFEND_CFACK = (BIT(7) | BIT(6) | BIT(5) | BIT(4) | - WIFI_CTRL_TYPE), - - /* below is for data frame */ - WIFI_DATA = (0 | WIFI_DATA_TYPE), - WIFI_DATA_CFACK = (BIT(4) | WIFI_DATA_TYPE), - WIFI_DATA_CFPOLL = (BIT(5) | WIFI_DATA_TYPE), - WIFI_DATA_CFACKPOLL = (BIT(5) | BIT(4) | WIFI_DATA_TYPE), - WIFI_DATA_NULL = (BIT(6) | WIFI_DATA_TYPE), - WIFI_CF_ACK = (BIT(6) | BIT(4) | WIFI_DATA_TYPE), - WIFI_CF_POLL = (BIT(6) | BIT(5) | WIFI_DATA_TYPE), - WIFI_CF_ACKPOLL = (BIT(6) | BIT(5) | BIT(4) | WIFI_DATA_TYPE), - WIFI_QOS_DATA_NULL = (BIT(6) | WIFI_QOS_DATA_TYPE), -}; - #define SetToDs(pbuf) \ *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_TODS) diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index c95ae4d6a3b6..b958a8d882b0 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -11,7 +11,6 @@ #include <osdep_service.h> #include <drv_types.h> #include <wlan_bssdef.h> -#include <rtw_debug.h> #include <wifi.h> #include <rtw_mlme.h> #include <rtw_mlme_ext.h> @@ -71,7 +70,6 @@ void rtw_indicate_wx_assoc_event(struct adapter *padapter) memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN); - DBG_88E_LEVEL(_drv_always_, "assoc success\n"); wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL); } @@ -84,7 +82,6 @@ void rtw_indicate_wx_disassoc_event(struct adapter *padapter) wrqu.ap_addr.sa_family = ARPHRD_ETHER; eth_zero_addr(wrqu.ap_addr.sa_data); - DBG_88E_LEVEL(_drv_always_, "indicate disassoc\n"); wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL); } @@ -224,7 +221,7 @@ static char *translate_scan(struct adapter *padapter, /* parsing WPA/WPA2 IE */ { u8 *buf; - u8 wpa_ie[255], rsn_ie[255]; + u8 *wpa_ie, *rsn_ie; u16 wpa_len = 0, rsn_len = 0; u8 *p; @@ -232,9 +229,15 @@ static char *translate_scan(struct adapter *padapter, if (!buf) return start; + wpa_ie = kzalloc(255, GFP_ATOMIC); + if (!wpa_ie) + return start; + + rsn_ie = kzalloc(255, GFP_ATOMIC); + if (!rsn_ie) + return start; + rtw_get_sec_ie(pnetwork->network.ies, pnetwork->network.ie_length, rsn_ie, &rsn_len, wpa_ie, &wpa_len); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: ssid =%s\n", pnetwork->network.ssid.ssid)); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: wpa_len =%d rsn_len =%d\n", wpa_len, rsn_len)); if (wpa_len > 0) { p = buf; @@ -268,6 +271,8 @@ static char *translate_scan(struct adapter *padapter, start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie); } kfree(buf); + kfree(wpa_ie); + kfree(rsn_ie); } {/* parsing WPS IE */ @@ -315,26 +320,20 @@ static int wpa_set_auth_algs(struct net_device *dev, u32 value) int ret = 0; if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) { - DBG_88E("%s, AUTH_ALG_SHARED_KEY and AUTH_ALG_OPEN_SYSTEM [value:0x%x]\n", __func__, value); padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch; padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto; } else if (value & AUTH_ALG_SHARED_KEY) { - DBG_88E("%s, AUTH_ALG_SHARED_KEY [value:0x%x]\n", __func__, value); padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared; padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared; } else if (value & AUTH_ALG_OPEN_SYSTEM) { - DBG_88E("%s, AUTH_ALG_OPEN_SYSTEM\n", __func__); if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) { padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen; padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; } - } else if (value & AUTH_ALG_LEAP) { - DBG_88E("%s, AUTH_ALG_LEAP\n", __func__); } else { - DBG_88E("%s, error!\n", __func__); ret = -EINVAL; } return ret; @@ -368,9 +367,6 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, } if (strcmp(param->u.crypt.alg, "WEP") == 0) { - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("%s, crypt.alg = WEP\n", __func__)); - DBG_88E("%s, crypt.alg = WEP\n", __func__); - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_; padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_; @@ -378,22 +374,15 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, wep_key_idx = param->u.crypt.idx; wep_key_len = param->u.crypt.key_len; - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(1)wep_key_idx =%d\n", wep_key_idx)); - DBG_88E("(1)wep_key_idx =%d\n", wep_key_idx); - if (wep_key_idx > WEP_KEYS) return -EINVAL; - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(2)wep_key_idx =%d\n", wep_key_idx)); - if (wep_key_len > 0) { wep_key_len = wep_key_len <= 5 ? 5 : 13; wep_total_len = wep_key_len + offsetof(struct ndis_802_11_wep, KeyMaterial); pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len); - if (!pwep) { - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("%s: pwep allocate fail !!!\n", __func__)); + if (!pwep) goto exit; - } memset(pwep, 0, wep_total_len); pwep->KeyLength = wep_key_len; pwep->Length = wep_total_len; @@ -409,11 +398,9 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, pwep->KeyIndex |= 0x80000000; memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength); if (param->u.crypt.set_tx) { - DBG_88E("wep, set_tx = 1\n"); if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL) ret = -EOPNOTSUPP; } else { - DBG_88E("wep, set_tx = 0\n"); if (wep_key_idx >= WEP_KEYS) { ret = -EOPNOTSUPP; goto exit; @@ -450,15 +437,12 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, padapter->securitypriv.busetkipkey = false; } - DBG_88E(" ~~~~set sta key:unicastkey\n"); - rtw_setstakey_cmd(padapter, (unsigned char *)psta, true); } else { /* group key */ memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16)); memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, ¶m->u.crypt.key[16], 8); memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, ¶m->u.crypt.key[24], 8); padapter->securitypriv.binstallGrpkey = true; - DBG_88E(" ~~~~set sta key:groupkey\n"); padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx; @@ -507,17 +491,7 @@ static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ie goto exit; } - /* dump */ - { - int i; - - DBG_88E("\n wpa_ie(length:%d):\n", ielen); - for (i = 0; i < ielen; i += 8) - DBG_88E("0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", buf[i], buf[i + 1], buf[i + 2], buf[i + 3], buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7]); - } - if (ielen < RSN_HEADER_LEN) { - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("Ie len too short %d\n", ielen)); ret = -1; goto exit; } @@ -588,8 +562,6 @@ static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ie while (cnt < ielen) { eid = buf[cnt]; if ((eid == WLAN_EID_VENDOR_SPECIFIC) && (!memcmp(&buf[cnt + 2], wps_oui, 4))) { - DBG_88E("SET WPS_IE\n"); - padapter->securitypriv.wps_ie_len = min(buf[cnt + 1] + 2, MAX_WPA_IE_LEN << 2); memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len); @@ -602,10 +574,6 @@ static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ie } } } - - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, - ("%s: pairwise_cipher = 0x%08x padapter->securitypriv.ndisencryptstatus =%d padapter->securitypriv.ndisauthtype =%d\n", - __func__, pairwise_cipher, padapter->securitypriv.ndisencryptstatus, padapter->securitypriv.ndisauthtype)); exit: kfree(buf); return ret; @@ -625,8 +593,6 @@ static int rtw_wx_get_name(struct net_device *dev, struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; NDIS_802_11_RATES_EX *prates = NULL; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("cmd_code =%x\n", info->cmd)); - if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) { /* parsing HT_CAP_IE */ p = rtw_get_ie(&pcur_bss->ies[12], WLAN_EID_HT_CAPABILITY, &ht_ielen, pcur_bss->ie_length - 12); @@ -657,14 +623,6 @@ static int rtw_wx_get_name(struct net_device *dev, return 0; } -static int rtw_wx_set_freq(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+%s\n", __func__)); - return 0; -} - static int rtw_wx_get_freq(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -707,23 +665,18 @@ static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a, switch (wrqu->mode) { case IW_MODE_AUTO: networkType = Ndis802_11AutoUnknown; - DBG_88E("set_mode = IW_MODE_AUTO\n"); break; case IW_MODE_ADHOC: networkType = Ndis802_11IBSS; - DBG_88E("set_mode = IW_MODE_ADHOC\n"); break; case IW_MODE_MASTER: networkType = Ndis802_11APMode; - DBG_88E("set_mode = IW_MODE_MASTER\n"); break; case IW_MODE_INFRA: networkType = Ndis802_11Infrastructure; - DBG_88E("set_mode = IW_MODE_INFRA\n"); break; default: ret = -EINVAL; - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("\n Mode: %s is not supported\n", iw_operation_mode[wrqu->mode])); goto exit; } if (!rtw_set_802_11_infrastructure_mode(padapter, networkType)) { @@ -741,8 +694,6 @@ static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a, struct adapter *padapter = netdev_priv(dev); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s\n", __func__)); - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) wrqu->mode = IW_MODE_INFRA; else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) || @@ -770,7 +721,6 @@ static int rtw_wx_set_pmkid(struct net_device *dev, memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN); if (pPMK->cmd == IW_PMKSA_ADD) { - DBG_88E("[%s] IW_PMKSA_ADD!\n", __func__); if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN)) return ret; ret = true; @@ -780,7 +730,6 @@ static int rtw_wx_set_pmkid(struct net_device *dev, for (j = 0; j < NUM_PMKID_CACHE; j++) { if (!memcmp(psecuritypriv->PMKIDList[j].bssid, strIssueBssid, ETH_ALEN)) { /* BSSID is matched, the same AP => rewrite with new PMKID. */ - DBG_88E("[%s] BSSID exists in the PMKList.\n", __func__); memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN); psecuritypriv->PMKIDList[j].used = true; psecuritypriv->PMKIDIndex = j + 1; @@ -791,9 +740,6 @@ static int rtw_wx_set_pmkid(struct net_device *dev, if (!blInserted) { /* Find a new entry */ - DBG_88E("[%s] Use the new entry index = %d for this PMKID.\n", - __func__, psecuritypriv->PMKIDIndex); - memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bssid, strIssueBssid, ETH_ALEN); memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN); @@ -803,7 +749,6 @@ static int rtw_wx_set_pmkid(struct net_device *dev, psecuritypriv->PMKIDIndex = 0; } } else if (pPMK->cmd == IW_PMKSA_REMOVE) { - DBG_88E("[%s] IW_PMKSA_REMOVE!\n", __func__); ret = true; for (j = 0; j < NUM_PMKID_CACHE; j++) { if (!memcmp(psecuritypriv->PMKIDList[j].bssid, strIssueBssid, ETH_ALEN)) { @@ -814,7 +759,6 @@ static int rtw_wx_set_pmkid(struct net_device *dev, } } } else if (pPMK->cmd == IW_PMKSA_FLUSH) { - DBG_88E("[%s] IW_PMKSA_FLUSH!\n", __func__); memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE); psecuritypriv->PMKIDIndex = 0; ret = true; @@ -843,8 +787,6 @@ static int rtw_wx_get_range(struct net_device *dev, u16 val; int i; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s. cmd_code =%x\n", __func__, info->cmd)); - wrqu->data.length = sizeof(*range); memset(range, 0, sizeof(*range)); @@ -952,12 +894,9 @@ static int rtw_wx_set_wap(struct net_device *dev, authmode = padapter->securitypriv.ndisauthtype; spin_lock_bh(&queue->lock); phead = get_list_head(queue); - pmlmepriv->pscanned = phead->next; - - while (phead != pmlmepriv->pscanned) { - pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list); - - pmlmepriv->pscanned = pmlmepriv->pscanned->next; + list_for_each(pmlmepriv->pscanned, phead) { + pnetwork = list_entry(pmlmepriv->pscanned, + struct wlan_network, list); dst_bssid = pnetwork->network.MacAddress; @@ -998,8 +937,6 @@ static int rtw_wx_get_wap(struct net_device *dev, eth_zero_addr(wrqu->ap_addr.sa_data); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s\n", __func__)); - if (check_fwstate(pmlmepriv, _FW_LINKED) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || check_fwstate(pmlmepriv, WIFI_AP_STATE)) @@ -1014,19 +951,12 @@ static int rtw_wx_set_mlme(struct net_device *dev, union iwreq_data *wrqu, char *extra) { int ret = 0; - u16 reason; struct adapter *padapter = netdev_priv(dev); struct iw_mlme *mlme = (struct iw_mlme *)extra; if (!mlme) return -1; - DBG_88E("%s\n", __func__); - - reason = mlme->reason_code; - - DBG_88E("%s, cmd =%d, reason =%d\n", __func__, mlme->cmd, reason); - switch (mlme->cmd) { case IW_MLME_DEAUTH: if (!rtw_set_802_11_disassociate(padapter)) @@ -1051,15 +981,12 @@ static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a, struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT]; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s\n", __func__)); - if (!rtw_pwr_wakeup(padapter)) { ret = -1; goto exit; } if (padapter->bDriverStopped) { - DBG_88E("bDriverStopped =%d\n", padapter->bDriverStopped); ret = -1; goto exit; } @@ -1103,15 +1030,11 @@ static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a, memcpy(ssid[0].ssid, req->essid, len); ssid[0].ssid_length = len; - DBG_88E("IW_SCAN_THIS_ESSID, ssid =%s, len =%d\n", req->essid, req->essid_len); - spin_lock_bh(&pmlmepriv->lock); _status = rtw_sitesurvey_cmd(padapter, ssid, 1, NULL, 0); spin_unlock_bh(&pmlmepriv->lock); - } else if (req->scan_type == IW_SCAN_TYPE_PASSIVE) { - DBG_88E("%s, req->scan_type == IW_SCAN_TYPE_PASSIVE\n", __func__); } } else { if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE && @@ -1189,9 +1112,6 @@ static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a, u32 wait_for_surveydone; int wait_status; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s\n", __func__)); - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, (" Start of Query SIOCGIWSCAN .\n")); - if (padapter->pwrctrlpriv.brfoffbyhw && padapter->bDriverStopped) { ret = -EINVAL; goto exit; @@ -1211,21 +1131,17 @@ static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a, spin_lock_bh(&pmlmepriv->scanned_queue.lock); phead = get_list_head(queue); - plist = phead->next; - - while (phead != plist) { + list_for_each(plist, phead) { if ((stop - ev) < SCAN_ITEM_SIZE) { ret = -E2BIG; break; } - pnetwork = container_of(plist, struct wlan_network, list); + pnetwork = list_entry(plist, struct wlan_network, list); /* report network only if the current channel set contains the channel to which this network belongs */ if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0) ev = translate_scan(padapter, a, pnetwork, ev, stop); - - plist = plist->next; } spin_unlock_bh(&pmlmepriv->scanned_queue.lock); @@ -1257,8 +1173,6 @@ static int rtw_wx_set_essid(struct net_device *dev, uint ret = 0, len; - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, - ("+%s: fw_state = 0x%08x\n", __func__, get_fwstate(pmlmepriv))); if (!rtw_pwr_wakeup(padapter)) { ret = -1; goto exit; @@ -1280,38 +1194,24 @@ static int rtw_wx_set_essid(struct net_device *dev, } authmode = padapter->securitypriv.ndisauthtype; - DBG_88E("=>%s\n", __func__); if (wrqu->essid.flags && wrqu->essid.length) { len = min_t(uint, wrqu->essid.length, IW_ESSID_MAX_SIZE); - if (wrqu->essid.length != 33) - DBG_88E("ssid =%s, len =%d\n", extra, wrqu->essid.length); - memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid)); ndis_ssid.ssid_length = len; memcpy(ndis_ssid.ssid, extra, len); src_ssid = ndis_ssid.ssid; - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("%s: ssid =[%s]\n", __func__, src_ssid)); spin_lock_bh(&queue->lock); phead = get_list_head(queue); - pmlmepriv->pscanned = phead->next; - - while (phead != pmlmepriv->pscanned) { - pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list); - - pmlmepriv->pscanned = pmlmepriv->pscanned->next; + list_for_each(pmlmepriv->pscanned, phead) { + pnetwork = list_entry(pmlmepriv->pscanned, + struct wlan_network, list); dst_ssid = pnetwork->network.ssid.ssid; - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, - ("%s: dst_ssid =%s\n", __func__, - pnetwork->network.ssid.ssid)); - if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.ssid_length)) && (pnetwork->network.ssid.ssid_length == ndis_ssid.ssid_length)) { - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, - ("%s: find match, set infra mode\n", __func__)); if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode) @@ -1328,8 +1228,6 @@ static int rtw_wx_set_essid(struct net_device *dev, } } spin_unlock_bh(&queue->lock); - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, - ("set ssid: set_802_11_auth. mode =%d\n", authmode)); rtw_set_802_11_authentication_mode(padapter, authmode); if (!rtw_set_802_11_ssid(padapter, &ndis_ssid)) { ret = -1; @@ -1338,8 +1236,6 @@ static int rtw_wx_set_essid(struct net_device *dev, } exit: - DBG_88E("<=%s, ret %d\n", __func__, ret); - return ret; } @@ -1352,8 +1248,6 @@ static int rtw_wx_get_essid(struct net_device *dev, struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s\n", __func__)); - if ((check_fwstate(pmlmepriv, _FW_LINKED)) || (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) { len = pcur_bss->ssid.ssid_length; @@ -1379,9 +1273,6 @@ static int rtw_wx_set_rate(struct net_device *dev, u32 ratevalue = 0; u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff}; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s\n", __func__)); - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("target_rate = %d, fixed = %d\n", target_rate, fixed)); - if (target_rate == -1) { ratevalue = 11; goto set_rate; @@ -1440,8 +1331,6 @@ set_rate: } else { datarates[i] = 0xff; } - - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("datarate_inx =%d\n", datarates[i])); } return 0; @@ -1480,8 +1369,6 @@ static int rtw_wx_set_rts(struct net_device *dev, padapter->registrypriv.rts_thresh = wrqu->rts.value; } - DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh); - return 0; } @@ -1491,8 +1378,6 @@ static int rtw_wx_get_rts(struct net_device *dev, { struct adapter *padapter = netdev_priv(dev); - DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh); - wrqu->rts.value = padapter->registrypriv.rts_thresh; wrqu->rts.fixed = 0; /* no auto select */ /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */ @@ -1516,8 +1401,6 @@ static int rtw_wx_set_frag(struct net_device *dev, padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1; } - DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len); - return 0; } @@ -1527,8 +1410,6 @@ static int rtw_wx_get_frag(struct net_device *dev, { struct adapter *padapter = netdev_priv(dev); - DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len); - wrqu->frag.value = padapter->xmitpriv.frag_len; wrqu->frag.fixed = 0; /* no auto select */ @@ -1559,14 +1440,11 @@ static int rtw_wx_set_enc(struct net_device *dev, struct adapter *padapter = netdev_priv(dev); struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - DBG_88E("+%s, flags = 0x%x\n", __func__, erq->flags); - memset(&wep, 0, sizeof(struct ndis_802_11_wep)); key = erq->flags & IW_ENCODE_INDEX; if (erq->flags & IW_ENCODE_DISABLED) { - DBG_88E("EncryptionDisabled\n"); padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_; @@ -1585,12 +1463,10 @@ static int rtw_wx_set_enc(struct net_device *dev, } else { keyindex_provided = 0; key = padapter->securitypriv.dot11PrivacyKeyIndex; - DBG_88E("%s, key =%d\n", __func__, key); } /* set authentication mode */ if (erq->flags & IW_ENCODE_OPEN) { - DBG_88E("%s():IW_ENCODE_OPEN\n", __func__); padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; @@ -1598,7 +1474,6 @@ static int rtw_wx_set_enc(struct net_device *dev, authmode = Ndis802_11AuthModeOpen; padapter->securitypriv.ndisauthtype = authmode; } else if (erq->flags & IW_ENCODE_RESTRICTED) { - DBG_88E("%s():IW_ENCODE_RESTRICTED\n", __func__); padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared; padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_; @@ -1606,8 +1481,6 @@ static int rtw_wx_set_enc(struct net_device *dev, authmode = Ndis802_11AuthModeShared; padapter->securitypriv.ndisauthtype = authmode; } else { - DBG_88E("%s():erq->flags = 0x%x\n", __func__, erq->flags); - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open; padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_; @@ -1628,8 +1501,6 @@ static int rtw_wx_set_enc(struct net_device *dev, /* set key_id only, no given KeyMaterial(erq->length == 0). */ padapter->securitypriv.dot11PrivacyKeyIndex = key; - DBG_88E("(keyindex_provided == 1), keyid =%d, key_len =%d\n", key, padapter->securitypriv.dot11DefKeylen[key]); - switch (padapter->securitypriv.dot11DefKeylen[key]) { case 5: padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_; @@ -1807,7 +1678,6 @@ static int rtw_wx_set_auth(struct net_device *dev, if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { LeaveAllPowerSaveMode(padapter); rtw_disassoc_cmd(padapter, 500, false); - DBG_88E("%s...call rtw_indicate_disconnect\n ", __func__); rtw_indicate_disconnect(padapter); rtw_free_assoc_resources(padapter); } @@ -1910,12 +1780,6 @@ static int rtw_wx_get_nick(struct net_device *dev, return 0; } -static int dummy(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - return -1; -} - static int wpa_set_param(struct net_device *dev, u8 name, u32 value) { uint ret = 0; @@ -1934,8 +1798,6 @@ static int wpa_set_param(struct net_device *dev, u8 name, u32 value) padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled; break; } - RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, - ("%s:padapter->securitypriv.ndisauthtype =%d\n", __func__, padapter->securitypriv.ndisauthtype)); break; case IEEE_PARAM_TKIP_COUNTERMEASURES: break; @@ -2024,7 +1886,6 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p) break; default: - DBG_88E("Unknown WPA supplicant request: %d\n", param->cmd); ret = -EOPNOTSUPP; break; } @@ -2080,8 +1941,6 @@ static int set_group_key(struct adapter *padapter, u8 *key, u8 alg, int keyid) struct cmd_priv *pcmdpriv = &padapter->cmdpriv; int res = _SUCCESS; - DBG_88E("%s\n", __func__); - pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); if (!pcmd) { res = _FAIL; @@ -2160,7 +2019,6 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, struct security_priv *psecuritypriv = &padapter->securitypriv; struct sta_priv *pstapriv = &padapter->stapriv; - DBG_88E("%s\n", __func__); param->u.crypt.err = 0; param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0'; if (param_len != sizeof(struct ieee_param) + param->u.crypt.key_len) { @@ -2174,23 +2032,17 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, } } else { psta = rtw_get_stainfo(pstapriv, param->sta_addr); - if (!psta) { - DBG_88E("%s(), sta has already been removed or never been added\n", __func__); + if (!psta) goto exit; - } } - if (strcmp(param->u.crypt.alg, "none") == 0 && (!psta)) { + if (strcmp(param->u.crypt.alg, "none") == 0 && (!psta)) /* todo:clear default encryption keys */ - - DBG_88E("clear default encryption keys, keyid =%d\n", param->u.crypt.idx); goto exit; - } + if (strcmp(param->u.crypt.alg, "WEP") == 0 && (!psta)) { - DBG_88E("r871x_set_encryption, crypt.alg = WEP\n"); wep_key_idx = param->u.crypt.idx; wep_key_len = param->u.crypt.key_len; - DBG_88E("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len); if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) { ret = -EINVAL; goto exit; @@ -2200,10 +2052,8 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, wep_key_len = wep_key_len <= 5 ? 5 : 13; wep_total_len = wep_key_len + offsetof(struct ndis_802_11_wep, KeyMaterial); pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len); - if (!pwep) { - DBG_88E(" r871x_set_encryption: pwep allocate fail !!!\n"); + if (!pwep) goto exit; - } memset(pwep, 0, wep_total_len); @@ -2216,8 +2066,6 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength); if (param->u.crypt.set_tx) { - DBG_88E("wep, set_tx = 1\n"); - psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled; psecuritypriv->dot11PrivacyAlgrthm = _WEP40_; psecuritypriv->dot118021XGrpPrivacy = _WEP40_; @@ -2235,8 +2083,6 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx); } else { - DBG_88E("wep, set_tx = 0\n"); - /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */ /* psecuritypriv->dot11PrivacyKeyIndex = keyid", but can rtw_set_key to cam */ @@ -2253,8 +2099,6 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /* group key */ if (param->u.crypt.set_tx == 1) { if (strcmp(param->u.crypt.alg, "WEP") == 0) { - DBG_88E("%s, set group_key, WEP\n", __func__); - memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16)); @@ -2262,7 +2106,6 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, if (param->u.crypt.key_len == 13) psecuritypriv->dot118021XGrpPrivacy = _WEP104_; } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) { - DBG_88E("%s, set group_key, TKIP\n", __func__); psecuritypriv->dot118021XGrpPrivacy = _TKIP_; memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16)); @@ -2272,12 +2115,10 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, psecuritypriv->busetkipkey = true; } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) { - DBG_88E("%s, set group_key, CCMP\n", __func__); psecuritypriv->dot118021XGrpPrivacy = _AES_; memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16)); } else { - DBG_88E("%s, set group_key, none\n", __func__); psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_; } psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx; @@ -2299,14 +2140,10 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16)); if (strcmp(param->u.crypt.alg, "WEP") == 0) { - DBG_88E("%s, set pairwise key, WEP\n", __func__); - psta->dot118021XPrivacy = _WEP40_; if (param->u.crypt.key_len == 13) psta->dot118021XPrivacy = _WEP104_; } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) { - DBG_88E("%s, set pairwise key, TKIP\n", __func__); - psta->dot118021XPrivacy = _TKIP_; /* set mic key */ @@ -2315,12 +2152,8 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, psecuritypriv->busetkipkey = true; } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) { - DBG_88E("%s, set pairwise key, CCMP\n", __func__); - psta->dot118021XPrivacy = _AES_; } else { - DBG_88E("%s, set pairwise key, none\n", __func__); - psta->dot118021XPrivacy = _NO_PRIVACY_; } @@ -2386,8 +2219,6 @@ static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int struct sta_priv *pstapriv = &padapter->stapriv; unsigned char *pbuf = param->u.bcn_ie.buf; - DBG_88E("%s, len =%d\n", __func__, len); - if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) return -EINVAL; @@ -2408,8 +2239,6 @@ static int rtw_hostapd_sta_flush(struct net_device *dev) { struct adapter *padapter = netdev_priv(dev); - DBG_88E("%s\n", __func__); - flush_all_cam_entry(padapter); /* clear CAM */ return rtw_sta_flush(padapter); @@ -2423,8 +2252,6 @@ static int rtw_add_sta(struct net_device *dev, struct ieee_param *param) struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct sta_priv *pstapriv = &padapter->stapriv; - DBG_88E("%s(aid =%d) =%pM\n", __func__, param->u.add_sta.aid, (param->sta_addr)); - if (!check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE))) return -EINVAL; @@ -2477,8 +2304,6 @@ static int rtw_del_sta(struct net_device *dev, struct ieee_param *param) struct sta_priv *pstapriv = &padapter->stapriv; int updated = 0; - DBG_88E("%s =%pM\n", __func__, (param->sta_addr)); - if (!check_fwstate(pmlmepriv, _FW_LINKED | WIFI_AP_STATE)) return -EINVAL; @@ -2496,8 +2321,6 @@ static int rtw_del_sta(struct net_device *dev, struct ieee_param *param) spin_unlock_bh(&pstapriv->asoc_list_lock); associated_clients_update(padapter, updated); psta = NULL; - } else { - DBG_88E("%s(), sta has already been removed or never been added\n", __func__); } return 0; @@ -2513,8 +2336,6 @@ static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *par struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param; struct sta_data *psta_data = (struct sta_data *)param_ex->data; - DBG_88E("rtw_ioctl_get_sta_info, sta_addr: %pM\n", (param_ex->sta_addr)); - if (!check_fwstate(pmlmepriv, _FW_LINKED | WIFI_AP_STATE)) return -EINVAL; @@ -2567,8 +2388,6 @@ static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param) struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct sta_priv *pstapriv = &padapter->stapriv; - DBG_88E("%s, sta_addr: %pM\n", __func__, (param->sta_addr)); - if (!check_fwstate(pmlmepriv, _FW_LINKED | WIFI_AP_STATE)) return -EINVAL; @@ -2586,8 +2405,6 @@ static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param) copy_len = min_t(int, wpa_ie_len + 2, sizeof(psta->wpa_ie)); param->u.wpa_ie.len = copy_len; memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len); - } else { - DBG_88E("sta's wpa_ie is NONE\n"); } } else { ret = -1; @@ -2604,8 +2421,6 @@ static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; int ie_len; - DBG_88E("%s, len =%d\n", __func__, len); - if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) return -EINVAL; @@ -2617,10 +2432,8 @@ static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, if (ie_len > 0) { pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len); pmlmepriv->wps_beacon_ie_len = ie_len; - if (!pmlmepriv->wps_beacon_ie) { - DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__); + if (!pmlmepriv->wps_beacon_ie) return -EINVAL; - } memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len); @@ -2638,8 +2451,6 @@ static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *par struct mlme_priv *pmlmepriv = &padapter->mlmepriv; int ie_len; - DBG_88E("%s, len =%d\n", __func__, len); - if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) return -EINVAL; @@ -2651,10 +2462,8 @@ static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *par if (ie_len > 0) { pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len); pmlmepriv->wps_probe_resp_ie_len = ie_len; - if (!pmlmepriv->wps_probe_resp_ie) { - DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__); + if (!pmlmepriv->wps_probe_resp_ie) return -EINVAL; - } memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len); } @@ -2667,8 +2476,6 @@ static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *par struct mlme_priv *pmlmepriv = &padapter->mlmepriv; int ie_len; - DBG_88E("%s, len =%d\n", __func__, len); - if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) return -EINVAL; @@ -2680,10 +2487,8 @@ static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *par if (ie_len > 0) { pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len); pmlmepriv->wps_assoc_resp_ie_len = ie_len; - if (!pmlmepriv->wps_assoc_resp_ie) { - DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__); + if (!pmlmepriv->wps_assoc_resp_ie) return -EINVAL; - } memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len); } @@ -2703,14 +2508,11 @@ static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) return -EINVAL; - if (param->u.wpa_param.name != 0) /* dummy test... */ - DBG_88E("%s name(%u) != 0\n", __func__, param->u.wpa_param.name); value = param->u.wpa_param.value; /* use the same definition of hostapd's ignore_broadcast_ssid */ if (value != 1 && value != 2) value = 0; - DBG_88E("%s value(%u)\n", __func__, value); pmlmeinfo->hidden_ssid_mode = value; return 0; } @@ -2821,7 +2623,6 @@ static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p) ret = rtw_ioctl_acl_remove_sta(dev, param, p->length); break; default: - DBG_88E("Unknown hostapd request: %d\n", param->cmd); ret = -EOPNOTSUPP; break; } @@ -2899,87 +2700,53 @@ FREE_EXT: } static iw_handler rtw_handlers[] = { - NULL, /* SIOCSIWCOMMIT */ - rtw_wx_get_name, /* SIOCGIWNAME */ - dummy, /* SIOCSIWNWID */ - dummy, /* SIOCGIWNWID */ - rtw_wx_set_freq, /* SIOCSIWFREQ */ - rtw_wx_get_freq, /* SIOCGIWFREQ */ - rtw_wx_set_mode, /* SIOCSIWMODE */ - rtw_wx_get_mode, /* SIOCGIWMODE */ - dummy, /* SIOCSIWSENS */ - rtw_wx_get_sens, /* SIOCGIWSENS */ - NULL, /* SIOCSIWRANGE */ - rtw_wx_get_range, /* SIOCGIWRANGE */ - rtw_wx_set_priv, /* SIOCSIWPRIV */ - NULL, /* SIOCGIWPRIV */ - NULL, /* SIOCSIWSTATS */ - NULL, /* SIOCGIWSTATS */ - dummy, /* SIOCSIWSPY */ - dummy, /* SIOCGIWSPY */ - NULL, /* SIOCGIWTHRSPY */ - NULL, /* SIOCWIWTHRSPY */ - rtw_wx_set_wap, /* SIOCSIWAP */ - rtw_wx_get_wap, /* SIOCGIWAP */ - rtw_wx_set_mlme, /* request MLME operation; uses struct iw_mlme */ - dummy, /* SIOCGIWAPLIST -- depricated */ - rtw_wx_set_scan, /* SIOCSIWSCAN */ - rtw_wx_get_scan, /* SIOCGIWSCAN */ - rtw_wx_set_essid, /* SIOCSIWESSID */ - rtw_wx_get_essid, /* SIOCGIWESSID */ - dummy, /* SIOCSIWNICKN */ - rtw_wx_get_nick, /* SIOCGIWNICKN */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ - rtw_wx_set_rate, /* SIOCSIWRATE */ - rtw_wx_get_rate, /* SIOCGIWRATE */ - rtw_wx_set_rts, /* SIOCSIWRTS */ - rtw_wx_get_rts, /* SIOCGIWRTS */ - rtw_wx_set_frag, /* SIOCSIWFRAG */ - rtw_wx_get_frag, /* SIOCGIWFRAG */ - dummy, /* SIOCSIWTXPOW */ - dummy, /* SIOCGIWTXPOW */ - dummy, /* SIOCSIWRETRY */ - rtw_wx_get_retry, /* SIOCGIWRETRY */ - rtw_wx_set_enc, /* SIOCSIWENCODE */ - rtw_wx_get_enc, /* SIOCGIWENCODE */ - dummy, /* SIOCSIWPOWER */ - rtw_wx_get_power, /* SIOCGIWPOWER */ - NULL, /*---hole---*/ - NULL, /*---hole---*/ - rtw_wx_set_gen_ie, /* SIOCSIWGENIE */ - NULL, /* SIOCGWGENIE */ - rtw_wx_set_auth, /* SIOCSIWAUTH */ - NULL, /* SIOCGIWAUTH */ - rtw_wx_set_enc_ext, /* SIOCSIWENCODEEXT */ - NULL, /* SIOCGIWENCODEEXT */ - rtw_wx_set_pmkid, /* SIOCSIWPMKSA */ - NULL, /*---hole---*/ + IW_HANDLER(SIOCGIWNAME, rtw_wx_get_name), + IW_HANDLER(SIOCGIWFREQ, rtw_wx_get_freq), + IW_HANDLER(SIOCSIWMODE, rtw_wx_set_mode), + IW_HANDLER(SIOCGIWMODE, rtw_wx_get_mode), + IW_HANDLER(SIOCGIWSENS, rtw_wx_get_sens), + IW_HANDLER(SIOCGIWRANGE, rtw_wx_get_range), + IW_HANDLER(SIOCSIWPRIV, rtw_wx_set_priv), + IW_HANDLER(SIOCSIWAP, rtw_wx_set_wap), + IW_HANDLER(SIOCGIWAP, rtw_wx_get_wap), + IW_HANDLER(SIOCSIWMLME, rtw_wx_set_mlme), + IW_HANDLER(SIOCSIWSCAN, rtw_wx_set_scan), + IW_HANDLER(SIOCGIWSCAN, rtw_wx_get_scan), + IW_HANDLER(SIOCSIWESSID, rtw_wx_set_essid), + IW_HANDLER(SIOCGIWESSID, rtw_wx_get_essid), + IW_HANDLER(SIOCGIWNICKN, rtw_wx_get_nick), + IW_HANDLER(SIOCSIWRATE, rtw_wx_set_rate), + IW_HANDLER(SIOCGIWRATE, rtw_wx_get_rate), + IW_HANDLER(SIOCSIWRTS, rtw_wx_set_rts), + IW_HANDLER(SIOCGIWRTS, rtw_wx_get_rts), + IW_HANDLER(SIOCSIWFRAG, rtw_wx_set_frag), + IW_HANDLER(SIOCGIWFRAG, rtw_wx_get_frag), + IW_HANDLER(SIOCGIWRETRY, rtw_wx_get_retry), + IW_HANDLER(SIOCSIWENCODE, rtw_wx_set_enc), + IW_HANDLER(SIOCGIWENCODE, rtw_wx_get_enc), + IW_HANDLER(SIOCGIWPOWER, rtw_wx_get_power), + IW_HANDLER(SIOCSIWGENIE, rtw_wx_set_gen_ie), + IW_HANDLER(SIOCSIWAUTH, rtw_wx_set_auth), + IW_HANDLER(SIOCSIWENCODEEXT, rtw_wx_set_enc_ext), + IW_HANDLER(SIOCSIWPMKSA, rtw_wx_set_pmkid), }; static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev) { struct adapter *padapter = netdev_priv(dev); struct iw_statistics *piwstats = &padapter->iwstats; - int tmp_level = 0; - int tmp_qual = 0; - int tmp_noise = 0; if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { piwstats->qual.qual = 0; piwstats->qual.level = 0; piwstats->qual.noise = 0; } else { - tmp_level = padapter->recvpriv.signal_strength; - tmp_qual = padapter->recvpriv.signal_qual; - tmp_noise = padapter->recvpriv.noise; - - piwstats->qual.level = tmp_level; - piwstats->qual.qual = tmp_qual; - piwstats->qual.noise = tmp_noise; + piwstats->qual.level = padapter->recvpriv.signal_strength; + piwstats->qual.qual = padapter->recvpriv.signal_qual; + piwstats->qual.noise = padapter->recvpriv.noise; } piwstats->qual.updated = IW_QUAL_ALL_UPDATED;/* IW_QUAL_DBM; */ - return &padapter->iwstats; + return piwstats; } struct iw_handler_def rtw_handlers_def = { diff --git a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c index df53b7d52618..f12d8a707376 100644 --- a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c @@ -87,12 +87,8 @@ void rtw_report_sec_ie(struct adapter *adapter, u8 authmode, u8 *sec_ie) u8 *buff, *p, i; union iwreq_data wrqu; - RT_TRACE(_module_mlme_osdep_c_, _drv_info_, - ("+%s, authmode=%d\n", __func__, authmode)); buff = NULL; if (authmode == WLAN_EID_VENDOR_SPECIFIC) { - RT_TRACE(_module_mlme_osdep_c_, _drv_info_, - ("%s, authmode=%d\n", __func__, authmode)); buff = rtw_malloc(IW_CUSTOM_MAX); if (!buff) return; @@ -144,8 +140,6 @@ void rtw_indicate_sta_assoc_event(struct adapter *padapter, struct sta_info *pst memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN); - DBG_88E("+%s\n", __func__); - wireless_send_event(padapter->pnetdev, IWEVREGISTERED, &wrqu, NULL); } @@ -167,8 +161,6 @@ void rtw_indicate_sta_disassoc_event(struct adapter *padapter, struct sta_info * memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN); - DBG_88E("+%s\n", __func__); - wireless_send_event(padapter->pnetdev, IWEVEXPIRED, &wrqu, NULL); } diff --git a/drivers/staging/rtl8188eu/os_dep/mon.c b/drivers/staging/rtl8188eu/os_dep/mon.c index 73b9599fe0dc..6370a3d8881b 100644 --- a/drivers/staging/rtl8188eu/os_dep/mon.c +++ b/drivers/staging/rtl8188eu/os_dep/mon.c @@ -14,7 +14,7 @@ #include <rtw_xmit.h> #include <mon.h> -/** +/* * unprotect_frame() - unset Protected flag and strip off IV and ICV/MIC */ static void unprotect_frame(struct sk_buff *skb, int iv_len, int icv_len) @@ -65,7 +65,7 @@ static void mon_recv_encrypted(struct net_device *dev, const u8 *data, netdev_info(dev, "Encrypted packets are not supported"); } -/** +/* * rtl88eu_mon_recv_hook() - forward received frame to the monitor interface * * Assumes that the frame contains an IV and an ICV/MIC, and that @@ -96,7 +96,7 @@ void rtl88eu_mon_recv_hook(struct net_device *dev, struct recv_frame *frame) mon_recv_encrypted(dev, data, data_len); } -/** +/* * rtl88eu_mon_xmit_hook() - forward trasmitted frame to the monitor interface * * Assumes that: @@ -163,18 +163,15 @@ struct net_device *rtl88eu_mon_init(void) dev = alloc_netdev(0, "mon%d", NET_NAME_UNKNOWN, mon_setup); if (!dev) - goto fail; + return NULL; err = register_netdev(dev); - if (err < 0) - goto fail_free_dev; + if (err < 0) { + free_netdev(dev); + return NULL; + } return dev; - -fail_free_dev: - free_netdev(dev); -fail: - return NULL; } void rtl88eu_mon_deinit(struct net_device *dev) diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index a826228cbbe9..423c382e3d20 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -18,7 +18,7 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Realtek Wireless Lan Driver"); MODULE_AUTHOR("Realtek Semiconductor Corp."); -MODULE_VERSION(DRIVERVERSION); +MODULE_VERSION("v4.1.4_6773.20130222"); MODULE_FIRMWARE("rtlwifi/rtl8188eufw.bin"); #define RTW_NOTCH_FILTER 0 /* 0:Disable, 1:Enable, */ @@ -136,12 +136,10 @@ MODULE_PARM_DESC(monitor_enable, "Enable monitor interface (default: false)"); static int netdev_close(struct net_device *pnetdev); -static void loadparam(struct adapter *padapter, struct net_device *pnetdev) +static void loadparam(struct adapter *padapter) { struct registry_priv *registry_par = &padapter->registrypriv; - GlobalDebugLevel = rtw_debug; - memcpy(registry_par->ssid.ssid, "ANY", 3); registry_par->ssid.ssid_length = 3; @@ -301,8 +299,6 @@ struct net_device *rtw_init_netdev(void) struct adapter *padapter; struct net_device *pnetdev; - RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+init_net_dev\n")); - pnetdev = alloc_etherdev_mq(sizeof(struct adapter), 4); if (!pnetdev) return NULL; @@ -310,12 +306,12 @@ struct net_device *rtw_init_netdev(void) pnetdev->dev.type = &wlan_type; padapter = netdev_priv(pnetdev); padapter->pnetdev = pnetdev; - DBG_88E("register rtw_netdev_ops to netdev_ops\n"); pnetdev->netdev_ops = &rtw_netdev_ops; pnetdev->watchdog_timeo = HZ * 3; /* 3 second timeout */ pnetdev->wireless_handlers = (struct iw_handler_def *)&rtw_handlers_def; - loadparam(padapter, pnetdev); + loadparam(padapter); + padapter->cmdThread = NULL; return pnetdev; } @@ -324,27 +320,22 @@ static int rtw_start_drv_threads(struct adapter *padapter) { int err = 0; - RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+%s\n", __func__)); - - padapter->cmdThread = kthread_run(rtw_cmd_thread, padapter, - "RTW_CMD_THREAD"); - if (IS_ERR(padapter->cmdThread)) + padapter->cmdThread = kthread_run(rtw_cmd_thread, padapter, "RTW_CMD_THREAD"); + if (IS_ERR(padapter->cmdThread)) { err = PTR_ERR(padapter->cmdThread); - else - /* wait for cmd_thread to run */ - wait_for_completion_interruptible(&padapter->cmdpriv.terminate_cmdthread_comp); + padapter->cmdThread = NULL; + } return err; } void rtw_stop_drv_threads(struct adapter *padapter) { - RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+%s\n", __func__)); + if (!padapter->cmdThread) + return; - /* Below is to terminate rtw_cmd_thread & event_thread... */ complete(&padapter->cmdpriv.cmd_queue_comp); - if (padapter->cmdThread) - wait_for_completion_interruptible(&padapter->cmdpriv.terminate_cmdthread_comp); + kthread_stop(padapter->cmdThread); } static u8 rtw_init_default_value(struct adapter *padapter) @@ -422,42 +413,29 @@ u8 rtw_init_drv_sw(struct adapter *padapter) { u8 ret8 = _SUCCESS; - RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+%s\n", __func__)); - - if ((rtw_init_cmd_priv(&padapter->cmdpriv)) == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, ("\n Can't init cmd_priv\n")); - ret8 = _FAIL; - goto exit; - } - - padapter->cmdpriv.padapter = padapter; + rtw_init_cmd_priv(&padapter->cmdpriv); if (rtw_init_mlme_priv(padapter) == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, ("\n Can't init mlme_priv\n")); ret8 = _FAIL; goto exit; } if (init_mlme_ext_priv(padapter) == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, ("\n Can't init mlme_ext_priv\n")); ret8 = _FAIL; goto exit; } if (_rtw_init_xmit_priv(&padapter->xmitpriv, padapter) == _FAIL) { - DBG_88E("Can't _rtw_init_xmit_priv\n"); ret8 = _FAIL; goto exit; } if (_rtw_init_recv_priv(&padapter->recvpriv, padapter) == _FAIL) { - DBG_88E("Can't _rtw_init_recv_priv\n"); ret8 = _FAIL; goto exit; } if (_rtw_init_sta_priv(&padapter->stapriv) == _FAIL) { - DBG_88E("Can't _rtw_init_sta_priv\n"); ret8 = _FAIL; goto exit; } @@ -476,27 +454,19 @@ u8 rtw_init_drv_sw(struct adapter *padapter) rtw_hal_sreset_init(padapter); exit: - RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-%s\n", __func__)); - return ret8; } void rtw_cancel_all_timer(struct adapter *padapter) { - RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+%s\n", __func__)); - del_timer_sync(&padapter->mlmepriv.assoc_timer); - RT_TRACE(_module_os_intfs_c_, _drv_info_, ("%s:cancel association timer complete!\n", __func__)); del_timer_sync(&padapter->mlmepriv.scan_to_timer); - RT_TRACE(_module_os_intfs_c_, _drv_info_, ("%s:cancel scan_to_timer!\n", __func__)); del_timer_sync(&padapter->mlmepriv.dynamic_chk_timer); - RT_TRACE(_module_os_intfs_c_, _drv_info_, ("%s:cancel dynamic_chk_timer!\n", __func__)); /* cancel sw led timer */ rtw_hal_sw_led_deinit(padapter); - RT_TRACE(_module_os_intfs_c_, _drv_info_, ("%s:cancel DeInitSwLeds!\n", __func__)); del_timer_sync(&padapter->pwrctrlpriv.pwr_state_check_timer); @@ -505,8 +475,6 @@ void rtw_cancel_all_timer(struct adapter *padapter) u8 rtw_free_drv_sw(struct adapter *padapter) { - RT_TRACE(_module_os_intfs_c_, _drv_info_, ("==>%s", __func__)); - free_mlme_ext_priv(&padapter->mlmeextpriv); rtw_free_mlme_priv(&padapter->mlmepriv); @@ -519,12 +487,8 @@ u8 rtw_free_drv_sw(struct adapter *padapter) rtw_hal_free_data(padapter); - RT_TRACE(_module_os_intfs_c_, _drv_info_, ("<== %s\n", __func__)); - mutex_destroy(&padapter->hw_init_mutex); - RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-%s\n", __func__)); - return _SUCCESS; } @@ -535,9 +499,6 @@ static int _netdev_open(struct net_device *pnetdev) struct adapter *padapter = netdev_priv(pnetdev); struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; - RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+88eu_drv - dev_open\n")); - DBG_88E("+88eu_drv - drv_open, bup =%d\n", padapter->bup); - if (pwrctrlpriv->ps_flag) { padapter->net_closed = false; goto netdev_open_normal_process; @@ -548,10 +509,8 @@ static int _netdev_open(struct net_device *pnetdev) padapter->bSurpriseRemoved = false; status = rtw_hal_init(padapter); - if (status == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, ("rtl88eu_hal_init(): Can't init h/w!\n")); + if (status == _FAIL) goto netdev_open_error; - } pr_info("MAC Address = %pM\n", pnetdev->dev_addr); @@ -585,16 +544,12 @@ static int _netdev_open(struct net_device *pnetdev) netif_tx_wake_all_queues(pnetdev); netdev_open_normal_process: - RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-88eu_drv - dev_open\n")); - DBG_88E("-88eu_drv - drv_open, bup =%d\n", padapter->bup); return 0; netdev_open_error: padapter->bup = false; netif_carrier_off(pnetdev); netif_tx_stop_all_queues(pnetdev); - RT_TRACE(_module_os_intfs_c_, _drv_err_, ("-88eu_drv - dev_open, fail!\n")); - DBG_88E("-88eu_drv - drv_open fail, bup =%d\n", padapter->bup); return -1; } @@ -615,16 +570,13 @@ int ips_netdrv_open(struct adapter *padapter) int status = _SUCCESS; padapter->net_closed = false; - DBG_88E("===> %s.........\n", __func__); padapter->bDriverStopped = false; padapter->bSurpriseRemoved = false; status = rtw_hal_init(padapter); - if (status == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, ("%s(): Can't init h/w!\n", __func__)); + if (status == _FAIL) goto netdev_open_error; - } rtw_hal_inirp_init(padapter); @@ -635,47 +587,33 @@ int ips_netdrv_open(struct adapter *padapter) return _SUCCESS; netdev_open_error: - DBG_88E("-%s - drv_open failure, bup =%d\n", __func__, padapter->bup); - return _FAIL; } int rtw_ips_pwr_up(struct adapter *padapter) { int result; - unsigned long start_time = jiffies; - DBG_88E("===> %s..............\n", __func__); rtw_reset_drv_sw(padapter); result = ips_netdrv_open(padapter); led_control_8188eu(padapter, LED_CTL_NO_LINK); - DBG_88E("<=== %s.............. in %dms\n", __func__, - jiffies_to_msecs(jiffies - start_time)); return result; } void rtw_ips_pwr_down(struct adapter *padapter) { - unsigned long start_time = jiffies; - - DBG_88E("===> %s...................\n", __func__); - padapter->net_closed = true; led_control_8188eu(padapter, LED_CTL_POWER_OFF); rtw_ips_dev_unload(padapter); - DBG_88E("<=== %s..................... in %dms\n", __func__, - jiffies_to_msecs(jiffies - start_time)); } void rtw_ips_dev_unload(struct adapter *padapter) { - DBG_88E("====> %s...\n", __func__); - rtw_hal_set_hwreg(padapter, HW_VAR_FIFO_CLEARN_UP, NULL); usb_intf_stop(padapter); @@ -689,8 +627,6 @@ static int netdev_close(struct net_device *pnetdev) { struct adapter *padapter = netdev_priv(pnetdev); - RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+88eu_drv - drv_close\n")); - if (padapter->pwrctrlpriv.bInternalAutoSuspend) { if (padapter->pwrctrlpriv.rf_pwrstate == rf_off) padapter->pwrctrlpriv.ps_flag = true; @@ -698,9 +634,6 @@ static int netdev_close(struct net_device *pnetdev) padapter->net_closed = true; if (padapter->pwrctrlpriv.rf_pwrstate == rf_on) { - DBG_88E("(2)88eu_drv - drv_close, bup =%d, hw_init_completed =%d\n", - padapter->bup, padapter->hw_init_completed); - /* s1. */ if (pnetdev) { if (!rtw_netif_queue_stopped(pnetdev)) @@ -720,7 +653,5 @@ static int netdev_close(struct net_device *pnetdev) led_control_8188eu(padapter, LED_CTL_POWER_OFF); } - RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-88eu_drv - drv_close\n")); - DBG_88E("-88eu_drv - drv_close, bup =%d\n", padapter->bup); return 0; } diff --git a/drivers/staging/rtl8188eu/os_dep/recv_linux.c b/drivers/staging/rtl8188eu/os_dep/recv_linux.c index a647cdc330e4..3460619ae08f 100644 --- a/drivers/staging/rtl8188eu/os_dep/recv_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/recv_linux.c @@ -72,11 +72,8 @@ int rtw_recv_indicatepkt(struct adapter *padapter, pfree_recv_queue = &precvpriv->free_recv_queue; skb = precv_frame->pkt; - if (!skb) { - RT_TRACE(_module_recv_osdep_c_, _drv_err_, - ("%s():skb == NULL something wrong!!!!\n", __func__)); + if (!skb) goto _recv_indicatepkt_drop; - } if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { struct sk_buff *pskb2 = NULL; @@ -124,9 +121,6 @@ _recv_indicatepkt_end: rtw_free_recvframe(precv_frame, pfree_recv_queue); - RT_TRACE(_module_recv_osdep_c_, _drv_info_, - ("\n %s :after netif_rx!!!!\n", __func__)); - return _SUCCESS; _recv_indicatepkt_drop: diff --git a/drivers/staging/rtl8188eu/os_dep/rtw_android.c b/drivers/staging/rtl8188eu/os_dep/rtw_android.c index f1470ac56874..3c5446999686 100644 --- a/drivers/staging/rtl8188eu/os_dep/rtw_android.c +++ b/drivers/staging/rtl8188eu/os_dep/rtw_android.c @@ -10,7 +10,6 @@ #include <rtw_android.h> #include <osdep_service.h> -#include <rtw_debug.h> #include <rtw_ioctl_set.h> static const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = { @@ -52,7 +51,7 @@ struct android_wifi_priv_cmd { int total_len; }; -int rtw_android_cmdstr_to_num(char *cmdstr) +static int rtw_android_cmdstr_to_num(char *cmdstr) { int cmd_num; @@ -135,8 +134,6 @@ int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) if (IS_ERR(command)) return PTR_ERR(command); command[priv_cmd.total_len - 1] = 0; - DBG_88E("%s: Android private cmd \"%s\" on %s\n", - __func__, command, ifr->ifr_name); cmd_num = rtw_android_cmdstr_to_num(command); switch (cmd_num) { case ANDROID_WIFI_CMD_START: @@ -202,7 +199,6 @@ int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) case ANDROID_WIFI_CMD_P2P_SET_PS: break; default: - DBG_88E("Unknown PRIVATE command %s - ignored\n", command); snprintf(command, 3, "OK"); bytes_written = strlen("OK"); } @@ -211,20 +207,14 @@ response: if (bytes_written >= 0) { if ((bytes_written == 0) && (priv_cmd.total_len > 0)) command[0] = '\0'; - if (bytes_written >= priv_cmd.total_len) { - DBG_88E("%s: bytes_written = %d\n", __func__, - bytes_written); + if (bytes_written >= priv_cmd.total_len) bytes_written = priv_cmd.total_len; - } else { + else bytes_written++; - } priv_cmd.used_len = bytes_written; if (copy_to_user((char __user *)priv_cmd.buf, command, - bytes_written)) { - DBG_88E("%s: failed to copy data to user buffer\n", - __func__); + bytes_written)) ret = -EFAULT; - } } else { ret = bytes_written; } diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 3a970d67aa8c..b7e2692c35f3 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -143,16 +143,6 @@ static void usb_dvobj_deinit(struct usb_interface *usb_intf) void usb_intf_stop(struct adapter *padapter) { - RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+%s\n", __func__)); - - /* disable_hw_interrupt */ - if (!padapter->bSurpriseRemoved) { - /* device still exists, so driver can do i/o operation */ - /* TODO: */ - RT_TRACE(_module_hci_intfs_c_, _drv_err_, - ("SurpriseRemoved == false\n")); - } - /* cancel in irp */ rtw_hal_inirp_deinit(padapter); @@ -160,14 +150,10 @@ void usb_intf_stop(struct adapter *padapter) usb_write_port_cancel(padapter); /* todo:cancel other irps */ - - RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-%s\n", __func__)); } static void rtw_dev_unload(struct adapter *padapter) { - RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+%s\n", __func__)); - if (padapter->bup) { pr_debug("===> %s\n", __func__); padapter->bDriverStopped = true; @@ -186,14 +172,9 @@ static void rtw_dev_unload(struct adapter *padapter) } padapter->bup = false; - } else { - RT_TRACE(_module_hci_intfs_c_, _drv_err_, - ("r871x_dev_unload():padapter->bup == false\n")); } pr_debug("<=== %s\n", __func__); - - RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-%s\n", __func__)); } static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message) @@ -351,7 +332,6 @@ static int rtw_usb_if1_init(struct usb_interface *pusb_intf) padapter->HalData = kzalloc(sizeof(struct hal_data_8188e), GFP_KERNEL); if (!padapter->HalData) { - DBG_88E("Failed to allocate memory for HAL data\n"); err = -ENOMEM; goto free_adapter; } @@ -367,8 +347,6 @@ static int rtw_usb_if1_init(struct usb_interface *pusb_intf) /* step 5. */ if (rtw_init_drv_sw(padapter) == _FAIL) { - RT_TRACE(_module_hci_intfs_c_, _drv_err_, - ("Initialize driver software resource Failed!\n")); err = -ENOMEM; goto free_hal_data; } @@ -388,8 +366,9 @@ static int rtw_usb_if1_init(struct usb_interface *pusb_intf) pr_debug("can't get autopm:\n"); /* alloc dev name after read efuse. */ - if (dev_alloc_name(pnetdev, padapter->registrypriv.ifname) < 0) - RT_TRACE(_module_os_intfs_c_, _drv_err_, ("dev_alloc_name, fail!\n")); + err = dev_alloc_name(pnetdev, padapter->registrypriv.ifname); + if (err < 0) + goto free_hal_data; netif_carrier_off(pnetdev); @@ -401,7 +380,6 @@ static int rtw_usb_if1_init(struct usb_interface *pusb_intf) /* step 6. Tell the network stack we exist */ err = register_netdev(pnetdev); if (err) { - RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("register_netdev() failed\n")); goto free_hal_data; } @@ -478,7 +456,6 @@ static void rtw_dev_remove(struct usb_interface *pusb_intf) struct adapter *padapter = dvobj->if1; pr_debug("+%s\n", __func__); - RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+dev_remove()\n")); if (!pusb_intf->unregistering) padapter->bSurpriseRemoved = true; @@ -492,7 +469,6 @@ static void rtw_dev_remove(struct usb_interface *pusb_intf) usb_dvobj_deinit(pusb_intf); - RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-dev_remove()\n")); pr_debug("-r871xu_dev_remove, done\n"); } diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index e8222ffb6fea..0ceb05f3884f 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -28,10 +28,8 @@ static void interrupt_handler_8188eu(struct adapter *adapt, u16 pkt_len, u8 *pbu { struct hal_data_8188e *haldata = adapt->HalData; - if (pkt_len != INTERRUPT_MSG_FORMAT_LEN) { - DBG_88E("%s Invalid interrupt content length (%d)!\n", __func__, pkt_len); + if (pkt_len != INTERRUPT_MSG_FORMAT_LEN) return; - } /* HISR */ memcpy(&haldata->IntArray[0], &pbuf[USB_INTR_CONTENT_HISR_OFFSET], 4); @@ -66,20 +64,11 @@ static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb) pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff; do { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - ("%s: rxdesc=offsset 0:0x%08x, 4:0x%08x, 8:0x%08x, C:0x%08x\n", - __func__, prxstat->rxdw0, prxstat->rxdw1, - prxstat->rxdw2, prxstat->rxdw4)); - prxstat = (struct recv_stat *)pbuf; precvframe = rtw_alloc_recvframe(pfree_recv_queue); - if (!precvframe) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - ("%s: precvframe==NULL\n", __func__)); - DBG_88E("%s()-%d: rtw_alloc_recvframe() failed! RX Drop!\n", __func__, __LINE__); + if (!precvframe) goto _exit_recvbuf2recvframe; - } INIT_LIST_HEAD(&precvframe->list); @@ -88,8 +77,6 @@ static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb) pattrib = &precvframe->attrib; if ((pattrib->crc_err) || (pattrib->icv_err)) { - DBG_88E("%s: RX Warning! crc_err=%d icv_err=%d, skip!\n", __func__, pattrib->crc_err, pattrib->icv_err); - rtw_free_recvframe(precvframe, pfree_recv_queue); goto _exit_recvbuf2recvframe; } @@ -100,9 +87,6 @@ static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb) pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->shift_sz + pattrib->pkt_len; if ((pattrib->pkt_len <= 0) || (pkt_offset > transfer_len)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - ("%s: pkt_len<=0\n", __func__)); - DBG_88E("%s()-%d: RX Warning!,pkt_len<=0 or pkt_offset> transfer_len\n", __func__, __LINE__); rtw_free_recvframe(precvframe, pfree_recv_queue); goto _exit_recvbuf2recvframe; } @@ -138,8 +122,6 @@ static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb) skb_reserve(pkt_copy, shift_sz);/* force ip_hdr at 8-byte alignment address according to shift_sz. */ skb_put_data(pkt_copy, (pbuf + pattrib->drvinfo_sz + RXDESC_SIZE), skb_len); } else { - DBG_88E("%s: alloc_skb fail , drop frag frame\n", - __func__); rtw_free_recvframe(precvframe, pfree_recv_queue); goto _exit_recvbuf2recvframe; } @@ -159,11 +141,7 @@ static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb) if (pattrib->pkt_rpt_type == NORMAL_RX) { /* Normal rx packet */ if (pattrib->physt) update_recvframe_phyinfo_88e(precvframe, pphy_status); - if (rtw_recv_entry(precvframe) != _SUCCESS) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - ("%s: rtw_recv_entry(precvframe) != _SUCCESS\n", - __func__)); - } + rtw_recv_entry(precvframe); } else if (pattrib->pkt_rpt_type == TX_REPORT1) { /* CCX-TXRPT ack for xmit mgmt frames. */ handle_txrpt_ccx_88e(adapt, precvframe->pkt->data); @@ -223,15 +201,11 @@ usbctrl_vendorreq(struct adapter *adapt, u16 value, void *pdata, u16 len, u8 req int vendorreq_times = 0; if ((adapt->bSurpriseRemoved) || (adapt->pwrctrlpriv.pnp_bstop_trx)) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - ("%s:(adapt->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", - __func__)); status = -EPERM; goto exit; } if (len > MAX_VENDOR_REQ_CMD_SIZE) { - DBG_88E("[%s] Buffer len error ,vendor request failed\n", __func__); status = -EINVAL; goto exit; } @@ -272,10 +246,6 @@ usbctrl_vendorreq(struct adapter *adapt, u16 value, void *pdata, u16 len, u8 req if (reqtype == REALTEK_USB_VENQT_READ) memcpy(pdata, pIo_buf, len); } else { /* error cases */ - DBG_88E("reg 0x%x, usb %s %u fail, status:%d value=0x%x, vendorreq_times:%d\n", - value, (reqtype == REALTEK_USB_VENQT_READ) ? "read" : "write", - len, status, *(u32 *)pdata, vendorreq_times); - if (status < 0) { if (status == -ESHUTDOWN || status == -ENODEV) adapt->bSurpriseRemoved = true; @@ -340,29 +310,15 @@ static void usb_read_port_complete(struct urb *purb) struct adapter *adapt = (struct adapter *)precvbuf->adapter; struct recv_priv *precvpriv = &adapt->recvpriv; - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s!!!\n", __func__)); - if (adapt->bSurpriseRemoved || adapt->bDriverStopped || adapt->bReadPortCancel) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - ("%s:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n", - __func__, adapt->bDriverStopped, - adapt->bSurpriseRemoved)); - precvbuf->reuse = true; - DBG_88E("%s() RX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bReadPortCancel(%d)\n", - __func__, adapt->bDriverStopped, - adapt->bSurpriseRemoved, adapt->bReadPortCancel); return; } if (purb->status == 0) { /* SUCCESS */ if ((purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - ("%s: (purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)\n", - __func__)); precvbuf->reuse = true; usb_read_port(adapt, RECV_BULK_IN_ADDR, precvbuf); - DBG_88E("%s()-%d: RX Warning!\n", __func__, __LINE__); } else { skb_put(precvbuf->pskb, purb->actual_length); skb_queue_tail(&precvpriv->rx_skb_queue, precvbuf->pskb); @@ -375,11 +331,6 @@ static void usb_read_port_complete(struct urb *purb) usb_read_port(adapt, RECV_BULK_IN_ADDR, precvbuf); } } else { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - ("%s : purb->status(%d) != 0\n", - __func__, purb->status)); - - DBG_88E("###=> %s => urb status(%d)\n", __func__, purb->status); skb_put(precvbuf->pskb, purb->actual_length); precvbuf->pskb = NULL; @@ -392,8 +343,6 @@ static void usb_read_port_complete(struct urb *purb) fallthrough; case -ENOENT: adapt->bDriverStopped = true; - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - ("%s:bDriverStopped=true\n", __func__)); break; case -EPROTO: case -EOVERFLOW: @@ -402,7 +351,6 @@ static void usb_read_port_complete(struct urb *purb) usb_read_port(adapt, RECV_BULK_IN_ADDR, precvbuf); break; case -EINPROGRESS: - DBG_88E("ERROR: URB IS IN PROGRESS!\n"); break; default: break; @@ -418,21 +366,14 @@ u32 usb_read_port(struct adapter *adapter, u32 addr, struct recv_buf *precvbuf) struct usb_device *pusbd = pdvobj->pusbdev; int err; unsigned int pipe; - u32 ret = _SUCCESS; if (adapter->bDriverStopped || adapter->bSurpriseRemoved || adapter->pwrctrlpriv.pnp_bstop_trx) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - ("%s:(adapt->bDriverStopped ||adapt->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", - __func__)); return _FAIL; } - if (!precvbuf) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - ("%s:precvbuf==NULL\n", __func__)); + if (!precvbuf) return _FAIL; - } if (!precvbuf->reuse || !precvbuf->pskb) { precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue); @@ -443,11 +384,8 @@ u32 usb_read_port(struct adapter *adapter, u32 addr, struct recv_buf *precvbuf) /* re-assign for linux based on skb */ if (!precvbuf->reuse || !precvbuf->pskb) { precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ); - if (!precvbuf->pskb) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("init_recvbuf(): alloc_skb fail!\n")); - DBG_88E("#### %s() alloc_skb fail!#####\n", __func__); + if (!precvbuf->pskb) return _FAIL; - } } else { /* reuse skb */ precvbuf->reuse = false; } @@ -464,16 +402,10 @@ u32 usb_read_port(struct adapter *adapter, u32 addr, struct recv_buf *precvbuf) precvbuf);/* context is precvbuf */ err = usb_submit_urb(purb, GFP_ATOMIC); - if ((err) && (err != (-EPERM))) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - ("cannot submit rx in-token(err=0x%.8x), URB_STATUS =0x%.8x", - err, purb->status)); - DBG_88E("cannot submit rx in-token(err = 0x%08x),urb_status = %d\n", - err, purb->status); - ret = _FAIL; - } + if (err) + return _FAIL; - return ret; + return _SUCCESS; } void rtw_hal_inirp_deinit(struct adapter *padapter) @@ -483,8 +415,6 @@ void rtw_hal_inirp_deinit(struct adapter *padapter) precvbuf = padapter->recvpriv.precv_buf; - DBG_88E("%s\n", __func__); - padapter->bReadPortCancel = true; for (i = 0; i < NR_RECVBUFF; i++) { @@ -547,49 +477,23 @@ static void usb_write_port_complete(struct urb *purb) break; } - if (padapter->bSurpriseRemoved || padapter->bDriverStopped || - padapter->bWritePortCancel) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - ("%s:bDriverStopped(%d) OR bSurpriseRemoved(%d)", - __func__, padapter->bDriverStopped, - padapter->bSurpriseRemoved)); - DBG_88E("%s(): TX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bWritePortCancel(%d) pxmitbuf->ext_tag(%x)\n", - __func__, padapter->bDriverStopped, - padapter->bSurpriseRemoved, padapter->bReadPortCancel, - pxmitbuf->ext_tag); - + if (padapter->bSurpriseRemoved || padapter->bDriverStopped || padapter->bWritePortCancel) goto check_completion; - } if (purb->status) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - ("%s : purb->status(%d) != 0\n", - __func__, purb->status)); - DBG_88E("###=> %s status(%d)\n", __func__, purb->status); if ((purb->status == -EPIPE) || (purb->status == -EPROTO)) { sreset_set_wifi_error_status(padapter, USB_WRITE_PORT_FAIL); } else if (purb->status == -EINPROGRESS) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - ("%s: EINPROGRESS\n", __func__)); goto check_completion; } else if (purb->status == -ENOENT) { - DBG_88E("%s: -ENOENT\n", __func__); goto check_completion; } else if (purb->status == -ECONNRESET) { - DBG_88E("%s: -ECONNRESET\n", __func__); goto check_completion; } else if (purb->status == -ESHUTDOWN) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - ("%s: ESHUTDOWN\n", __func__)); padapter->bDriverStopped = true; - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - ("%s:bDriverStopped = true\n", __func__)); goto check_completion; } else { padapter->bSurpriseRemoved = true; - DBG_88E("bSurpriseRemoved = true\n"); - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - ("%s:bSurpriseRemoved = true\n", __func__)); goto check_completion; } } @@ -616,13 +520,8 @@ u32 usb_write_port(struct adapter *padapter, u32 addr, u32 cnt, struct xmit_buf struct xmit_frame *pxmitframe = (struct xmit_frame *)xmitbuf->priv_data; struct usb_device *pusbd = pdvobj->pusbdev; - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("+%s\n", __func__)); - if ((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) || (padapter->pwrctrlpriv.pnp_bstop_trx)) { - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - ("%s:( padapter->bDriverStopped ||padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", - __func__)); rtw_sctx_done_err(&xmitbuf->sctx, RTW_SCTX_DONE_TX_DENY); goto exit; } @@ -670,11 +569,6 @@ u32 usb_write_port(struct adapter *padapter, u32 addr, u32 cnt, struct xmit_buf status = usb_submit_urb(purb, GFP_ATOMIC); if (status) { rtw_sctx_done_err(&xmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR); - DBG_88E("%s, status =%d\n", __func__, status); - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, - ("%s(): usb_submit_urb, status =%x\n", - __func__, status)); - if (status == -ENODEV) padapter->bDriverStopped = true; @@ -683,8 +577,6 @@ u32 usb_write_port(struct adapter *padapter, u32 addr, u32 cnt, struct xmit_buf ret = _SUCCESS; - RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("-%s\n", __func__)); - exit: if (ret != _SUCCESS) rtw_free_xmitbuf(pxmitpriv, xmitbuf); @@ -696,8 +588,6 @@ void usb_write_port_cancel(struct adapter *padapter) int i, j; struct xmit_buf *pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmitbuf; - DBG_88E("%s\n", __func__); - padapter->bWritePortCancel = true; for (i = 0; i < NR_XMITBUFF; i++) { @@ -726,7 +616,6 @@ void rtl8188eu_recv_tasklet(struct tasklet_struct *t) while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) { if ((adapt->bDriverStopped) || (adapt->bSurpriseRemoved)) { - DBG_88E("recv_tasklet => bDriverStopped or bSurpriseRemoved\n"); dev_kfree_skb_any(pskb); break; } @@ -746,12 +635,8 @@ void rtl8188eu_xmit_tasklet(struct tasklet_struct *t) return; while (1) { - if ((adapt->bDriverStopped) || - (adapt->bSurpriseRemoved) || - (adapt->bWritePortCancel)) { - DBG_88E("xmit_tasklet => bDriverStopped or bSurpriseRemoved or bWritePortCancel\n"); + if ((adapt->bDriverStopped) || (adapt->bSurpriseRemoved) || (adapt->bWritePortCancel)) break; - } if (!rtl8188eu_xmitframe_complete(adapt, pxmitpriv)) break; diff --git a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c index a9c42fb80583..1b5776ae8eba 100644 --- a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c @@ -26,10 +26,8 @@ int rtw_os_xmit_resource_alloc(struct xmit_buf *pxmitbuf, u32 alloc_sz) for (i = 0; i < 8; i++) { pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL); - if (!pxmitbuf->pxmit_urb[i]) { - DBG_88E("pxmitbuf->pxmit_urb[i]==NULL"); + if (!pxmitbuf->pxmit_urb[i]) return _FAIL; - } } return _SUCCESS; } @@ -118,13 +116,9 @@ static int rtw_mlcst2unicst(struct adapter *padapter, struct sk_buff *skb) spin_lock_bh(&pstapriv->asoc_list_lock); phead = &pstapriv->asoc_list; - plist = phead->next; - /* free sta asoc_queue */ - while (phead != plist) { - psta = container_of(plist, struct sta_info, asoc_list); - - plist = plist->next; + list_for_each(plist, phead) { + psta = list_entry(plist, struct sta_info, asoc_list); /* avoid come from STA1 and send back STA1 */ if (!memcmp(psta->hwaddr, &skb->data[6], 6)) @@ -136,16 +130,12 @@ static int rtw_mlcst2unicst(struct adapter *padapter, struct sk_buff *skb) memcpy(newskb->data, psta->hwaddr, 6); res = rtw_xmit(padapter, &newskb); if (res < 0) { - DBG_88E("%s()-%d: rtw_xmit() return error!\n", - __func__, __LINE__); pxmitpriv->tx_drop++; dev_kfree_skb_any(newskb); } else { pxmitpriv->tx_pkts++; } } else { - DBG_88E("%s-%d: skb_copy() failed!\n", - __func__, __LINE__); pxmitpriv->tx_drop++; spin_unlock_bh(&pstapriv->asoc_list_lock); @@ -169,13 +159,8 @@ int rtw_xmit_entry(struct sk_buff *pkt, struct net_device *pnetdev) struct mlme_priv *pmlmepriv = &padapter->mlmepriv; s32 res = 0; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("+xmit_enry\n")); - - if (!rtw_if_up(padapter)) { - RT_TRACE(_module_xmit_osdep_c_, _drv_err_, - ("%s: rtw_if_up fail\n", __func__)); + if (!rtw_if_up(padapter)) goto drop_packet; - } rtw_check_xmit_resource(padapter, pkt); @@ -194,16 +179,11 @@ int rtw_xmit_entry(struct sk_buff *pkt, struct net_device *pnetdev) goto drop_packet; pxmitpriv->tx_pkts++; - RT_TRACE(_module_xmit_osdep_c_, _drv_info_, - ("%s: tx_pkts=%d\n", __func__, (u32)pxmitpriv->tx_pkts)); goto exit; drop_packet: pxmitpriv->tx_drop++; dev_kfree_skb_any(pkt); - RT_TRACE(_module_xmit_osdep_c_, _drv_notice_, - ("%s: drop, tx_drop=%d\n", __func__, (u32)pxmitpriv->tx_drop)); - exit: return NETDEV_TX_OK; } diff --git a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c index 7876b389913a..52eeb56c5c76 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c @@ -46,7 +46,6 @@ void rtl92e_set_bandwidth(struct net_device *dev, netdev_err(dev, "%s(): Unknown bandwidth: %#X\n", __func__, Bandwidth); break; - } } } @@ -73,7 +72,6 @@ bool rtl92e_config_rf(struct net_device *dev) pPhyReg = &priv->PHYRegDef[eRFPath]; - switch (eRFPath) { case RF90_PATH_A: case RF90_PATH_C: @@ -143,7 +141,6 @@ bool rtl92e_config_rf(struct net_device *dev) __func__, eRFPath); goto fail; } - } RT_TRACE(COMP_PHY, "PHY Initialization Success\n"); @@ -170,7 +167,6 @@ void rtl92e_set_cck_tx_power(struct net_device *dev, u8 powerlevel) rtl92e_set_bb_reg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC); } - void rtl92e_set_ofdm_tx_power(struct net_device *dev, u8 powerlevel) { struct r8192_priv *priv = rtllib_priv(dev); @@ -215,5 +211,4 @@ void rtl92e_set_ofdm_tx_power(struct net_device *dev, u8 powerlevel) (byte1 << 8) | byte0; rtl92e_set_bb_reg(dev, RegOffset[index], 0x7f7f7f7f, writeVal); } - } diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c index c8506517cc8d..f75a12543781 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c @@ -185,14 +185,12 @@ void rtl92e_cam_restore(struct net_device *dev) rtl92e_set_key(dev, 4, 0, priv->rtllib->pairwise_key_type, (u8 *)dev->dev_addr, 0, - (u32 *)(&priv->rtllib->swcamtable[4]. - key_buf[0])); + (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0])); } else { rtl92e_set_key(dev, 4, 0, priv->rtllib->pairwise_key_type, MacAddr, 0, - (u32 *)(&priv->rtllib->swcamtable[4]. - key_buf[0])); + (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0])); } } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP) { @@ -200,13 +198,11 @@ void rtl92e_cam_restore(struct net_device *dev) rtl92e_set_key(dev, 4, 0, priv->rtllib->pairwise_key_type, (u8 *)dev->dev_addr, 0, - (u32 *)(&priv->rtllib->swcamtable[4]. - key_buf[0])); + (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0])); } else { rtl92e_set_key(dev, 4, 0, priv->rtllib->pairwise_key_type, MacAddr, - 0, (u32 *)(&priv->rtllib->swcamtable[4]. - key_buf[0])); + 0, (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0])); } } diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h index 736f1a824cd2..698552a92100 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h @@ -569,8 +569,8 @@ void rtl92e_writel(struct net_device *dev, int x, u32 y); void force_pci_posting(struct net_device *dev); -void rtl92e_rx_enable(struct net_device *); -void rtl92e_tx_enable(struct net_device *); +void rtl92e_rx_enable(struct net_device *dev); +void rtl92e_tx_enable(struct net_device *dev); void rtl92e_hw_sleep_wq(void *data); void rtl92e_commit(struct net_device *dev); diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c index c53aa2d305ca..756d8db51937 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c @@ -1733,7 +1733,7 @@ static void _rtl92e_dm_check_edca_turbo(struct net_device *dev) priv->bcurrent_turbo_EDCA = true; } } else { - if (priv->bcurrent_turbo_EDCA) { + if (priv->bcurrent_turbo_EDCA) { u8 tmp = AC0_BE; priv->rtllib->SetHwRegHandler(dev, HW_VAR_AC_PARAM, diff --git a/drivers/staging/rtl8192e/rtl819x_HTProc.c b/drivers/staging/rtl8192e/rtl819x_HTProc.c index 48d28c7d870b..3b8efaf9b88c 100644 --- a/drivers/staging/rtl8192e/rtl819x_HTProc.c +++ b/drivers/staging/rtl8192e/rtl819x_HTProc.c @@ -276,7 +276,7 @@ void HTConstructCapabilityElement(struct rtllib_device *ieee, u8 *posHTCap, struct rt_hi_throughput *pHT = ieee->pHTInfo; struct ht_capab_ele *pCapELE = NULL; - if ((posHTCap == NULL) || (pHT == NULL)) { + if (!posHTCap || !pHT) { netdev_warn(ieee->dev, "%s(): posHTCap and pHTInfo are null\n", __func__); return; @@ -357,7 +357,7 @@ void HTConstructInfoElement(struct rtllib_device *ieee, u8 *posHTInfo, struct rt_hi_throughput *pHT = ieee->pHTInfo; struct ht_info_ele *pHTInfoEle = (struct ht_info_ele *)posHTInfo; - if ((posHTInfo == NULL) || (pHTInfoEle == NULL)) { + if (!posHTInfo || !pHTInfoEle) { netdev_warn(ieee->dev, "%s(): posHTInfo and pHTInfoEle are null\n", __func__); @@ -397,7 +397,7 @@ void HTConstructInfoElement(struct rtllib_device *ieee, u8 *posHTInfo, void HTConstructRT2RTAggElement(struct rtllib_device *ieee, u8 *posRT2RTAgg, u8 *len) { - if (posRT2RTAgg == NULL) { + if (!posRT2RTAgg) { netdev_warn(ieee->dev, "%s(): posRT2RTAgg is null\n", __func__); return; } @@ -420,7 +420,7 @@ static u8 HT_PickMCSRate(struct rtllib_device *ieee, u8 *pOperateMCS) { u8 i; - if (pOperateMCS == NULL) { + if (!pOperateMCS) { netdev_warn(ieee->dev, "%s(): pOperateMCS is null\n", __func__); return false; } @@ -453,7 +453,7 @@ u8 HTGetHighestMCSRate(struct rtllib_device *ieee, u8 *pMCSRateSet, u8 mcsRate = 0; u8 availableMcsRate[16]; - if (pMCSRateSet == NULL || pMCSFilter == NULL) { + if (!pMCSRateSet || !pMCSFilter) { netdev_warn(ieee->dev, "%s(): pMCSRateSet and pMCSFilter are null\n", __func__); diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h index 4cabaf21c1ca..c6f8b772335c 100644 --- a/drivers/staging/rtl8192e/rtllib.h +++ b/drivers/staging/rtl8192e/rtllib.h @@ -1979,8 +1979,6 @@ void rtllib_softmac_new_net(struct rtllib_device *ieee, void SendDisassociation(struct rtllib_device *ieee, bool deauth, u16 asRsn); void rtllib_softmac_xmit(struct rtllib_txb *txb, struct rtllib_device *ieee); -void rtllib_stop_send_beacons(struct rtllib_device *ieee); -void notify_wx_assoc_event(struct rtllib_device *ieee); void rtllib_start_ibss(struct rtllib_device *ieee); void rtllib_softmac_init(struct rtllib_device *ieee); void rtllib_softmac_free(struct rtllib_device *ieee); diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index 6e48b31a9afc..c2209c033838 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -2285,8 +2285,7 @@ int rtllib_parse_info_param(struct rtllib_device *ieee, length -= sizeof(*info_element) + info_element->len; info_element = - (struct rtllib_info_element *)&info_element-> - data[info_element->len]; + (struct rtllib_info_element *)&info_element->data[info_element->len]; } if (!network->atheros_cap_exist && !network->broadcom_cap_exist && diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index f9a51f3620d2..25b3d3950a3c 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -730,7 +730,6 @@ EXPORT_SYMBOL(rtllib_act_scanning); /* called with ieee->lock held */ static void rtllib_start_scan(struct rtllib_device *ieee) { - RT_TRACE(COMP_DBG, "===>%s()\n", __func__); if (ieee->rtllib_ips_leave_wq != NULL) ieee->rtllib_ips_leave_wq(ieee->dev); diff --git a/drivers/staging/rtl8192e/rtllib_tx.c b/drivers/staging/rtl8192e/rtllib_tx.c index 89ec72b1895a..37715afb0210 100644 --- a/drivers/staging/rtl8192e/rtllib_tx.c +++ b/drivers/staging/rtl8192e/rtllib_tx.c @@ -881,7 +881,7 @@ static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) success: if (txb) { - struct cb_desc *tcb_desc = (struct cb_desc *) + tcb_desc = (struct cb_desc *) (txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bTxEnableFwCalcDur = 1; tcb_desc->priority = skb->priority; diff --git a/drivers/staging/rtl8192e/rtllib_wx.c b/drivers/staging/rtl8192e/rtllib_wx.c index ab1b8217c4e0..0d67d5880377 100644 --- a/drivers/staging/rtl8192e/rtllib_wx.c +++ b/drivers/staging/rtl8192e/rtllib_wx.c @@ -293,8 +293,6 @@ int rtllib_wx_set_encode(struct rtllib_device *ieee, int i, key, key_provided, len; struct lib80211_crypt_data **crypt; - netdev_dbg(ieee->dev, "%s()\n", __func__); - key = erq->flags & IW_ENCODE_INDEX; if (key) { if (key > NUM_WEP_KEYS) @@ -463,8 +461,6 @@ int rtllib_wx_get_encode(struct rtllib_device *ieee, int len, key; struct lib80211_crypt_data *crypt; - netdev_dbg(ieee->dev, "%s()\n", __func__); - if (ieee->iw_mode == IW_MODE_MONITOR) return -1; diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h index 39f4ddd86796..7903c777a417 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -2249,10 +2249,8 @@ void ieee80211_wake_queue(struct ieee80211_device *ieee); void ieee80211_stop_queue(struct ieee80211_device *ieee); struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee); void ieee80211_start_send_beacons(struct ieee80211_device *ieee); -void ieee80211_stop_send_beacons(struct ieee80211_device *ieee); int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p); -void notify_wx_assoc_event(struct ieee80211_device *ieee); void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success); void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c index 25ea8e1b6b65..ab885353f668 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c @@ -33,9 +33,9 @@ short ieee80211_is_shortslot(const struct ieee80211_network *net) } EXPORT_SYMBOL(ieee80211_is_shortslot); -/* returns the total length needed for pleacing the RATE MFIE +/* returns the total length needed for placing the RATE MFIE * tag and the EXTENDED RATE MFIE tag if needed. - * It encludes two bytes per tag for the tag itself and its len + * It includes two bytes per tag for the tag itself and its len */ static unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee) { @@ -50,7 +50,7 @@ static unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee) return rate_len; } -/* pleace the MFIE rate, tag to the memory (double) poined. +/* place the MFIE rate, tag to the memory (double) pointer. * Then it updates the pointer so that * it points after the new MFIE tag added. */ @@ -436,7 +436,7 @@ void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee) * So we switch to IEEE80211_LINKED_SCANNING to remember * that we are still logically linked (not interested in * new network events, despite for updating the net list, - * but we are temporarly 'unlinked' as the driver shall + * but we are temporarily 'unlinked' as the driver shall * not filter RX frames and the channel is changing. * So the only situation in witch are interested is to check * if the state become LINKED because of the #1 situation @@ -1162,7 +1162,7 @@ void ieee80211_associate_abort(struct ieee80211_device *ieee) ieee->associate_seq++; - /* don't scan, and avoid to have the RX path possibily + /* don't scan, and avoid having the RX path possibly * try again to associate. Even do not react to AUTH or * ASSOC response. Just wait for the retry wq to be scheduled. * Here we will check if there are good nets to associate @@ -1373,7 +1373,7 @@ inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee /* if the user set the AP check if match. * if the network does not broadcast essid we check the user supplyed ANY essid * if the network does broadcast and the user does not set essid it is OK - * if the network does broadcast and the user did set essid chech if essid match + * if the network does broadcast and the user did set essid check if essid match */ if ((apset && apmatch && ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset))) || @@ -1911,8 +1911,11 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED && ieee->iw_mode == IW_MODE_INFRA) { - struct ieee80211_network network_resp; - struct ieee80211_network *network = &network_resp; + struct ieee80211_network *network; + + network = kzalloc(sizeof(*network), GFP_KERNEL); + if (!network) + return -ENOMEM; errcode = assoc_parse(ieee, skb, &aid); if (!errcode) { @@ -1923,7 +1926,6 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, /* Let the register setting defaultly with Legacy station */ if (ieee->qos_support) { assoc_resp = (struct ieee80211_assoc_response_frame *)skb->data; - memset(network, 0, sizeof(*network)); if (ieee80211_parse_info_param(ieee, assoc_resp->info_element,\ rx_stats->len - sizeof(*assoc_resp), \ network, rx_stats)) { @@ -1949,6 +1951,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, else ieee80211_associate_abort(ieee); } + kfree(network); } break; @@ -2240,9 +2243,9 @@ static void ieee80211_start_ibss_wq(struct work_struct *work) * time to scan all the chans..) or we have just run up the iface * after setting ad-hoc mode. So we have to give another try.. * Here, in ibss mode, should be safe to do this without extra care - * (in bss mode we had to make sure no-one tryed to associate when + * (in bss mode we had to make sure no-one tried to associate when * we had just checked the ieee->state and we was going to start the - * scan) beacause in ibss mode the ieee80211_new_net function, when + * scan) because in ibss mode the ieee80211_new_net function, when * finds a good net, just set the ieee->state to IEEE80211_LINKED, * so, at worst, we waste a bit of time to initiate an unneeded syncro * scan, that will stop at the first round because it sees the state diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c index 96e6aaf859ec..8602e3a6c837 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c @@ -795,7 +795,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) success: //WB add to fill data tcb_desc here. only first fragment is considered, need to change, and you may remove to other place. if (txb) { - struct cb_desc *tcb_desc = (struct cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); + tcb_desc = (struct cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bTxEnableFwCalcDur = 1; if (is_multicast_ether_addr(header.addr1)) tcb_desc->bMulticast = 1; diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index f48186a89fa1..db26edeccea6 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -902,7 +902,6 @@ static void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate) { struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); - int ret; unsigned long flags; struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); u8 queue_index = tcb_desc->queue_index; @@ -915,7 +914,7 @@ static void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, *(struct net_device **)(skb->cb) = dev; tcb_desc->bTxEnableFwCalcDur = 1; skb_push(skb, priv->ieee80211->tx_headroom); - ret = rtl8192_tx(dev, skb); + rtl8192_tx(dev, skb); spin_unlock_irqrestore(&priv->tx_lock, flags); } @@ -2304,8 +2303,6 @@ static int rtl8192_read_eeprom_info(struct net_device *dev) /* set channelplan from eeprom */ priv->ChannelPlan = priv->eeprom_ChannelPlan; if (bLoad_From_EEPOM) { - int i; - for (i = 0; i < 6; i += 2) { ret = eprom_read(dev, (u16)((EEPROM_NODE_ADDRESS_BYTE_0 + i) >> 1)); if (ret < 0) @@ -2369,8 +2366,6 @@ static int rtl8192_read_eeprom_info(struct net_device *dev) priv->EEPROM_Def_Ver = 1; RT_TRACE(COMP_EPROM, "EEPROM_DEF_VER:%d\n", priv->EEPROM_Def_Ver); if (priv->EEPROM_Def_Ver == 0) { /* old eeprom definition */ - int i; - if (bLoad_From_EEPOM) { ret = eprom_read(dev, (EEPROM_TX_PW_INDEX_CCK >> 1)); if (ret < 0) @@ -2972,12 +2967,10 @@ static RESET_TYPE RxCheckStuck(struct net_device *dev) return RESET_TYPE_NORESET; } -/** +/* * This function is called by Checkforhang to check whether we should * ask OS to reset driver * - * \param pAdapter The adapter context for this miniport - * * Note:NIC with USB interface sholud not call this function because we * cannot scan descriptor to judge whether there is tx stuck. * Note: This function may be required to be rewrite for Vista OS. @@ -3697,7 +3690,7 @@ static u8 HwRateToMRate90(bool bIsHT, u8 rate) return ret_rate; } -/** +/* * Function: UpdateRxPktTimeStamp * Overview: Record the TSF time stamp when receiving a packet * @@ -4297,7 +4290,7 @@ static void TranslateRxSignalStuff819xUsb(struct sk_buff *skb, rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats); } -/** +/* * Function: UpdateReceivedRateHistogramStatistics * Overview: Record the received data rate * diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c index bac402b40121..725bf5ca9e34 100644 --- a/drivers/staging/rtl8192u/r8192U_dm.c +++ b/drivers/staging/rtl8192u/r8192U_dm.c @@ -2876,7 +2876,8 @@ void dm_check_fsync(struct net_device *dev) * When Who Remark * 05/29/2008 amy Create Version 0 porting from windows code. * - *---------------------------------------------------------------------------*/ + *--------------------------------------------------------------------------- + */ void dm_shadow_init(struct net_device *dev) { u8 page; @@ -2915,7 +2916,8 @@ void dm_shadow_init(struct net_device *dev) * When Who Remark * 03/06/2008 Jacken Create Version 0. * - *---------------------------------------------------------------------------*/ + *--------------------------------------------------------------------------- + */ static void dm_init_dynamic_txpower(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); diff --git a/drivers/staging/rtl8192u/r8192U_hw.h b/drivers/staging/rtl8192u/r8192U_hw.h index 8d3a592f1c35..217e77766442 100644 --- a/drivers/staging/rtl8192u/r8192U_hw.h +++ b/drivers/staging/rtl8192u/r8192U_hw.h @@ -88,7 +88,7 @@ enum _RTL8192Usb_HW { #define RX_FIFO_THRESHOLD_MASK (BIT(13) | BIT(14) | BIT(15)) #define RX_FIFO_THRESHOLD_SHIFT 13 #define RX_FIFO_THRESHOLD_NONE 7 -#define MAX_RX_DMA_MASK (BIT(8) | BIT(9) | BIT(10)) +#define MAX_RX_DMA_MASK (BIT(8) | BIT(9) | BIT(10)) #define RCR_MXDMA_OFFSET 8 #define RCR_FIFO_OFFSET 13 #define RCR_ONLYERLPKT BIT(31) // Early Receiving based on Packet Size. @@ -159,7 +159,7 @@ enum _RTL8192Usb_HW { #define BW_OPMODE_20MHZ BIT(2) BW_OPMODE = 0x300, // Bandwidth operation mode MSR = 0x303, // Media Status register -#define MSR_LINK_MASK (BIT(0)|BIT(1)) +#define MSR_LINK_MASK (BIT(0) | BIT(1)) #define MSR_LINK_MANAGED 2 #define MSR_LINK_NONE 0 #define MSR_LINK_SHIFT 0 @@ -221,14 +221,13 @@ enum _RTL8192Usb_HW { #define RATR_MCS14 0x04000000 #define RATR_MCS15 0x08000000 // ALL CCK Rate -#define RATE_ALL_CCK RATR_1M|RATR_2M|RATR_55M|RATR_11M -#define RATE_ALL_OFDM_AG RATR_6M|RATR_9M|RATR_12M|RATR_18M|RATR_24M\ - |RATR_36M|RATR_48M|RATR_54M -#define RATE_ALL_OFDM_1SS RATR_MCS0|RATR_MCS1|RATR_MCS2|RATR_MCS3 | \ - RATR_MCS4|RATR_MCS5|RATR_MCS6|RATR_MCS7 -#define RATE_ALL_OFDM_2SS RATR_MCS8|RATR_MCS9 |RATR_MCS10|RATR_MCS11| \ - RATR_MCS12|RATR_MCS13|RATR_MCS14|RATR_MCS15 - +#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M) +#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M |\ + RATR_24M | RATR_36M | RATR_48M | RATR_54M) +#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | RATR_MCS3 |\ + RATR_MCS4 | RATR_MCS5 | RATR_MCS6 | RATR_MCS7) +#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | RATR_MCS11 |\ + RATR_MCS12 | RATR_MCS13 | RATR_MCS14 | RATR_MCS15) EPROM_CMD = 0xfe58, #define Cmd9346CR_9356SEL BIT(4) #define EPROM_CMD_OPERATING_MODE_SHIFT 6 diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.c b/drivers/staging/rtl8192u/r819xU_cmdpkt.c index 4cece40a92f6..30a320422358 100644 --- a/drivers/staging/rtl8192u/r819xU_cmdpkt.c +++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.c @@ -250,46 +250,6 @@ static void cmpk_handle_interrupt_status(struct net_device *dev, u8 *pmsg) } /*----------------------------------------------------------------------------- - * Function: cmpk_handle_query_config_rx() - * - * Overview: The function is responsible for extract the message from - * firmware. It will contain dedicated info in - * ws-06-0063-rtl8190-command-packet-specification. Please - * refer to chapter "Beacon State Element". - * - * Input: u8 *pmsg - Message Pointer of the command packet. - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 05/12/2008 amy Create Version 0 porting from windows code. - * - *--------------------------------------------------------------------------- - */ -static void cmpk_handle_query_config_rx(struct net_device *dev, u8 *pmsg) -{ - struct cmpk_query_cfg rx_query_cfg; - - /* 1. Extract TX feedback info from RFD to temp structure buffer. */ - /* It seems that FW use big endian(MIPS) and DRV use little endian in - * windows OS. So we have to read the content byte by byte or transfer - * endian type before copy the message copy. - */ - rx_query_cfg.cfg_action = (pmsg[4] & 0x80) >> 7; - rx_query_cfg.cfg_type = (pmsg[4] & 0x60) >> 5; - rx_query_cfg.cfg_size = (pmsg[4] & 0x18) >> 3; - rx_query_cfg.cfg_page = (pmsg[6] & 0x0F) >> 0; - rx_query_cfg.cfg_offset = pmsg[7]; - rx_query_cfg.value = (pmsg[8] << 24) | (pmsg[9] << 16) | - (pmsg[10] << 8) | (pmsg[11] << 0); - rx_query_cfg.mask = (pmsg[12] << 24) | (pmsg[13] << 16) | - (pmsg[14] << 8) | (pmsg[15] << 0); -} - -/*----------------------------------------------------------------------------- * Function: cmpk_count_tx_status() * * Overview: Count aggregated tx status from firmwar of one type rx command @@ -514,7 +474,6 @@ u32 cmpk_message_handle_rx(struct net_device *dev, break; case BOTH_QUERY_CONFIG: - cmpk_handle_query_config_rx(dev, pcmd_buff); cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE; break; diff --git a/drivers/staging/rtl8192u/r819xU_phy.c b/drivers/staging/rtl8192u/r819xU_phy.c index eef751d2b12e..37b82553412e 100644 --- a/drivers/staging/rtl8192u/r819xU_phy.c +++ b/drivers/staging/rtl8192u/r819xU_phy.c @@ -1185,14 +1185,32 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel, u8 *stage, u8 *step, u32 *delay) { struct r8192_priv *priv = ieee80211_priv(dev); - struct sw_chnl_cmd PreCommonCmd[MAX_PRECMD_CNT]; + struct sw_chnl_cmd *PreCommonCmd; u32 PreCommonCmdCnt; - struct sw_chnl_cmd PostCommonCmd[MAX_POSTCMD_CNT]; + struct sw_chnl_cmd *PostCommonCmd; u32 PostCommonCmdCnt; - struct sw_chnl_cmd RfDependCmd[MAX_RFDEPENDCMD_CNT]; + struct sw_chnl_cmd *RfDependCmd; u32 RfDependCmdCnt; struct sw_chnl_cmd *CurrentCmd = NULL; u8 e_rfpath; + bool ret; + + PreCommonCmd = kzalloc(sizeof(*PreCommonCmd) * MAX_PRECMD_CNT, GFP_KERNEL); + if (!PreCommonCmd) + return false; + + PostCommonCmd = kzalloc(sizeof(*PostCommonCmd) * MAX_POSTCMD_CNT, GFP_KERNEL); + if (!PostCommonCmd) { + kfree(PreCommonCmd); + return false; + } + + RfDependCmd = kzalloc(sizeof(*RfDependCmd) * MAX_RFDEPENDCMD_CNT, GFP_KERNEL); + if (!RfDependCmd) { + kfree(PreCommonCmd); + kfree(PostCommonCmd); + return false; + } RT_TRACE(COMP_CH, "%s() stage: %d, step: %d, channel: %d\n", __func__, *stage, *step, channel); @@ -1201,7 +1219,8 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel, /* return true to tell upper caller function this channel * setting is finished! Or it will in while loop. */ - return true; + ret = true; + goto out; } /* FIXME: need to check whether channel is legal or not here */ @@ -1227,7 +1246,8 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel, RT_TRACE(COMP_ERR, "illegal channel for Zebra 8225: %d\n", channel); - return true; + ret = true; + goto out; } rtl8192_phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT, @@ -1246,7 +1266,8 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel, RT_TRACE(COMP_ERR, "illegal channel for Zebra 8256: %d\n", channel); - return true; + ret = true; + goto out; } rtl8192_phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT, @@ -1262,7 +1283,8 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel, default: RT_TRACE(COMP_ERR, "Unknown RFChipID: %d\n", priv->rf_chip); - return true; + ret = true; + goto out; } do { @@ -1281,7 +1303,8 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel, if (CurrentCmd->cmd_id == CMD_ID_END) { if ((*stage) == 2) { (*delay) = CurrentCmd->ms_delay; - return true; + ret = true; + goto out; } (*stage)++; (*step) = 0; @@ -1324,7 +1347,14 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel, (*delay) = CurrentCmd->ms_delay; (*step)++; - return false; + ret = false; + +out: + kfree(PreCommonCmd); + kfree(PostCommonCmd); + kfree(RfDependCmd); + + return ret; } /****************************************************************************** diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c index 715f1fe8b472..22974277afa0 100644 --- a/drivers/staging/rtl8712/hal_init.c +++ b/drivers/staging/rtl8712/hal_init.c @@ -40,7 +40,10 @@ static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context) dev_err(&udev->dev, "r8712u: Firmware request failed\n"); usb_put_dev(udev); usb_set_intfdata(usb_intf, NULL); + r8712_free_drv_sw(adapter); + adapter->dvobj_deinit(adapter); complete(&adapter->rtl8712_fw_ready); + free_netdev(adapter->pnetdev); return; } adapter->fw = firmware; diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index 0c3ae8495afb..2214aca09730 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -328,8 +328,6 @@ int r8712_init_drv_sw(struct _adapter *padapter) void r8712_free_drv_sw(struct _adapter *padapter) { - struct net_device *pnetdev = padapter->pnetdev; - r8712_free_cmd_priv(&padapter->cmdpriv); r8712_free_evt_priv(&padapter->evtpriv); r8712_DeInitSwLeds(padapter); @@ -339,8 +337,6 @@ void r8712_free_drv_sw(struct _adapter *padapter) _r8712_free_sta_priv(&padapter->stapriv); _r8712_free_recv_priv(&padapter->recvpriv); mp871xdeinit(padapter); - if (pnetdev) - free_netdev(pnetdev); } static void enable_video_mode(struct _adapter *padapter, int cbw40_value) diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c index ff3cb09c57a6..e9294e1ed06e 100644 --- a/drivers/staging/rtl8712/rtl8712_cmd.c +++ b/drivers/staging/rtl8712/rtl8712_cmd.c @@ -55,7 +55,7 @@ static void check_hw_pbc(struct _adapter *padapter) /* Here we only set bPbcPressed to true * After trigger PBC, the variable will be set to false */ - DBG_8712("CheckPbcGPIO - PBC is pressed !!!!\n"); + netdev_dbg(padapter->pnetdev, "CheckPbcGPIO - PBC is pressed !!!!\n"); /* 0 is the default value and it means the application monitors * the HW PBC doesn't provide its pid to driver. */ diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index db5c7a487ab3..0ffb30f1af7e 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -1039,8 +1039,9 @@ static void recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) skb_reserve(pkt_copy, 4 - ((addr_t)(pkt_copy->data) % 4)); skb_reserve(pkt_copy, shift_sz); memcpy(pkt_copy->data, pbuf, tmp_len); - precvframe->u.hdr.rx_head = precvframe->u.hdr.rx_data = - precvframe->u.hdr.rx_tail = pkt_copy->data; + precvframe->u.hdr.rx_head = pkt_copy->data; + precvframe->u.hdr.rx_data = pkt_copy->data; + precvframe->u.hdr.rx_tail = pkt_copy->data; precvframe->u.hdr.rx_end = pkt_copy->data + alloc_sz; recvframe_put(precvframe, tmp_len); diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index 116cb812dcb9..84a22eba7ebf 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -482,9 +482,9 @@ static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz) ptxdesc->txdw1 |= cpu_to_le32((0x01 << 22) & 0x00c00000); /*KEY_ID when WEP is used;*/ - ptxdesc->txdw1 |= cpu_to_le32((psecuritypriv-> - PrivacyKeyIndex << 17) & - 0x00060000); + ptxdesc->txdw1 |= + cpu_to_le32((psecuritypriv->PrivacyKeyIndex << 17) & + 0x00060000); break; case _TKIP_: case _TKIP_WTMIC_: diff --git a/drivers/staging/rtl8712/rtl871x_debug.h b/drivers/staging/rtl8712/rtl871x_debug.h index 57f2a38cb71c..69c631af2a2a 100644 --- a/drivers/staging/rtl8712/rtl871x_debug.h +++ b/drivers/staging/rtl8712/rtl871x_debug.h @@ -127,27 +127,4 @@ #undef _MODULE_DEFINE_ #endif -#define _dbgdump printk - -#define MSG_8712(x, ...) {} - -#define DBG_8712(x, ...) {} - -#define WRN_8712(x, ...) {} - -#define ERR_8712(x, ...) {} - -#undef MSG_8712 -#define MSG_8712 _dbgdump - -#undef DBG_8712 -#define DBG_8712 _dbgdump - -#undef WRN_8712 -#define WRN_8712 _dbgdump - -#undef ERR_8712 -#define ERR_8712 _dbgdump - #endif /*__RTL871X_DEBUG_H__*/ - diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index ba4a71e91ae0..92b7c9c07df6 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -139,10 +139,8 @@ static struct wlan_network *r8712_find_network(struct __queue *scanned_queue, return NULL; spin_lock_irqsave(&scanned_queue->lock, irqL); phead = &scanned_queue->queue; - plist = phead->next; - while (plist != phead) { - pnetwork = container_of(plist, struct wlan_network, list); - plist = plist->next; + list_for_each(plist, phead) { + pnetwork = list_entry(plist, struct wlan_network, list); if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN)) break; } diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c index 31414a960c9e..26fa09b45c90 100644 --- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c +++ b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c @@ -149,26 +149,30 @@ static int mp_start_test(struct _adapter *padapter) struct mp_priv *pmppriv = &padapter->mppriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct wlan_network *tgt_network = &pmlmepriv->cur_network; - struct wlan_bssid_ex bssid; + struct wlan_bssid_ex *bssid; struct sta_info *psta; unsigned long length; unsigned long irqL; int res = 0; + bssid = kzalloc(sizeof(*bssid), GFP_KERNEL); + if (!bssid) + return -ENOMEM; + /* 3 1. initialize a new struct wlan_bssid_ex */ - memcpy(bssid.MacAddress, pmppriv->network_macaddr, ETH_ALEN); - bssid.Ssid.SsidLength = 16; - memcpy(bssid.Ssid.Ssid, (unsigned char *)"mp_pseudo_adhoc", - bssid.Ssid.SsidLength); - bssid.InfrastructureMode = Ndis802_11IBSS; - bssid.NetworkTypeInUse = Ndis802_11DS; - bssid.IELength = 0; - length = r8712_get_wlan_bssid_ex_sz(&bssid); + memcpy(bssid->MacAddress, pmppriv->network_macaddr, ETH_ALEN); + bssid->Ssid.SsidLength = 16; + memcpy(bssid->Ssid.Ssid, (unsigned char *)"mp_pseudo_adhoc", + bssid->Ssid.SsidLength); + bssid->InfrastructureMode = Ndis802_11IBSS; + bssid->NetworkTypeInUse = Ndis802_11DS; + bssid->IELength = 0; + length = r8712_get_wlan_bssid_ex_sz(bssid); if (length % 4) { /*round up to multiple of 4 bytes.*/ - bssid.Length = ((length >> 2) + 1) << 2; + bssid->Length = ((length >> 2) + 1) << 2; } else { - bssid.Length = length; + bssid->Length = length; } spin_lock_irqsave(&pmlmepriv->lock, irqL); if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) @@ -185,7 +189,7 @@ static int mp_start_test(struct _adapter *padapter) tgt_network->network.MacAddress); if (psta) r8712_free_stainfo(padapter, psta); - psta = r8712_alloc_stainfo(&padapter->stapriv, bssid.MacAddress); + psta = r8712_alloc_stainfo(&padapter->stapriv, bssid->MacAddress); if (!psta) { res = -ENOMEM; goto end_of_mp_start_test; @@ -193,13 +197,14 @@ static int mp_start_test(struct _adapter *padapter) /* 3 3. join pseudo AdHoc */ tgt_network->join_res = 1; tgt_network->aid = psta->aid = 1; - memcpy(&tgt_network->network, &bssid, length); + memcpy(&tgt_network->network, bssid, length); _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); r8712_os_indicate_connect(padapter); /* Set to LINKED STATE for MP TRX Testing */ set_fwstate(pmlmepriv, _FW_LINKED); end_of_mp_start_test: spin_unlock_irqrestore(&pmlmepriv->lock, irqL); + kfree(bssid); return res; } diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h b/drivers/staging/rtl8712/rtl871x_mp_ioctl.h index 59fa6664d868..98204493a04c 100644 --- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h +++ b/drivers/staging/rtl8712/rtl871x_mp_ioctl.h @@ -135,135 +135,8 @@ uint oid_rt_get_power_mode_hdl( struct oid_par_priv *poid_par_priv); #ifdef _RTL871X_MP_IOCTL_C_ /* CAUTION!!! */ /* This ifdef _MUST_ be left in!! */ -static const struct oid_obj_priv oid_rtl_seg_81_80_00[] = { - /* 0x00 OID_RT_PRO_RESET_DUT */ - {1, oid_null_function}, - /* 0x01 */ - {1, oid_rt_pro_set_data_rate_hdl}, - /* 0x02 */ - {1, oid_rt_pro_start_test_hdl}, - /* 0x03 */ - {1, oid_rt_pro_stop_test_hdl}, - /* 0x04 OID_RT_PRO_SET_PREAMBLE */ - {1, oid_null_function}, - /* 0x05 OID_RT_PRO_SET_SCRAMBLER */ - {1, oid_null_function}, - /* 0x06 OID_RT_PRO_SET_FILTER_BB */ - {1, oid_null_function}, - /* 0x07 OID_RT_PRO_SET_MANUAL_DIVERS_BB */ - {1, oid_null_function}, - /* 0x08 */ - {1, oid_rt_pro_set_channel_direct_call_hdl}, - /* 0x09 OID_RT_PRO_SET_SLEEP_MODE_DIRECT_CALL */ - {1, oid_null_function}, - /* 0x0A OID_RT_PRO_SET_WAKE_MODE_DIRECT_CALL */ - {1, oid_null_function}, - /* 0x0B OID_RT_PRO_SET_TX_CONTINUOUS_DIRECT_CALL */ - {1, oid_rt_pro_set_continuous_tx_hdl}, - /* 0x0C OID_RT_PRO_SET_SINGLE_CARRIER_TX_CONTINUOUS */ - {1, oid_rt_pro_set_single_carrier_tx_hdl}, - /* 0x0D OID_RT_PRO_SET_TX_ANTENNA_BB */ - {1, oid_null_function}, - /* 0x0E */ - {1, oid_rt_pro_set_antenna_bb_hdl}, - /* 0x0F OID_RT_PRO_SET_CR_SCRAMBLER */ - {1, oid_null_function}, - /* 0x10 OID_RT_PRO_SET_CR_NEW_FILTER */ - {1, oid_null_function}, - /* 0x11 OID_RT_PRO_SET_TX_POWER_CONTROL */ - {1, oid_rt_pro_set_tx_power_control_hdl}, - /* 0x12 OID_RT_PRO_SET_CR_TX_CONFIG */ - {1, oid_null_function}, - /* 0x13 OID_RT_PRO_GET_TX_POWER_CONTROL */ - {1, oid_null_function}, - /* 0x14 OID_RT_PRO_GET_CR_SIGNAL_QUALITY */ - {1, oid_null_function}, - /* 0x15 OID_RT_PRO_SET_CR_SETPOINT */ - {1, oid_null_function}, - /* 0x16 OID_RT_PRO_SET_INTEGRATOR */ - {1, oid_null_function}, - /* 0x17 OID_RT_PRO_SET_SIGNAL_QUALITY */ - {1, oid_null_function}, - /* 0x18 OID_RT_PRO_GET_INTEGRATOR */ - {1, oid_null_function}, - /* 0x19 OID_RT_PRO_GET_SIGNAL_QUALITY */ - {1, oid_null_function}, - /* 0x1A OID_RT_PRO_QUERY_EEPROM_TYPE */ - {1, oid_null_function}, - /* 0x1B OID_RT_PRO_WRITE_MAC_ADDRESS */ - {1, oid_null_function}, - /* 0x1C OID_RT_PRO_READ_MAC_ADDRESS */ - {1, oid_null_function}, - /* 0x1D OID_RT_PRO_WRITE_CIS_DATA */ - {1, oid_null_function}, - /* 0x1E OID_RT_PRO_READ_CIS_DATA */ - {1, oid_null_function}, - /* 0x1F OID_RT_PRO_WRITE_POWER_CONTROL */ - {1, oid_null_function} -}; - -static const struct oid_obj_priv oid_rtl_seg_81_80_20[] = { - /* 0x20 OID_RT_PRO_READ_POWER_CONTROL */ - {1, oid_null_function}, - /* 0x21 OID_RT_PRO_WRITE_EEPROM */ - {1, oid_null_function}, - /* 0x22 OID_RT_PRO_READ_EEPROM */ - {1, oid_null_function}, - /* 0x23 */ - {1, oid_rt_pro_reset_tx_packet_sent_hdl}, - /* 0x24 */ - {1, oid_rt_pro_query_tx_packet_sent_hdl}, - /* 0x25 */ - {1, oid_rt_pro_reset_rx_packet_received_hdl}, - /* 0x26 */ - {1, oid_rt_pro_query_rx_packet_received_hdl}, - /* 0x27 */ - {1, oid_rt_pro_query_rx_packet_crc32_error_hdl}, - /* 0x28 OID_RT_PRO_QUERY_CURRENT_ADDRESS */ - {1, oid_null_function}, - /* 0x29 OID_RT_PRO_QUERY_PERMANENT_ADDRESS */ - {1, oid_null_function}, - /* 0x2A OID_RT_PRO_SET_PHILIPS_RF_PARAMETERS */ - {1, oid_null_function}, - /* 0x2B OID_RT_PRO_SET_CARRIER_SUPPRESSION_TX */ - {1, oid_rt_pro_set_carrier_suppression_tx_hdl}, - /* 0x2C OID_RT_PRO_RECEIVE_PACKET */ - {1, oid_null_function}, - /* 0x2D OID_RT_PRO_WRITE_EEPROM_BYTE */ - {1, oid_null_function}, - /* 0x2E OID_RT_PRO_READ_EEPROM_BYTE */ - {1, oid_null_function}, - /* 0x2F */ - {1, oid_rt_pro_set_modulation_hdl} -}; - -static const struct oid_obj_priv oid_rtl_seg_81_80_40[] = { - {1, oid_null_function}, /* 0x40 */ - {1, oid_null_function}, /* 0x41 */ - {1, oid_null_function}, /* 0x42 */ - {1, oid_rt_pro_set_single_tone_tx_hdl}, /* 0x43 */ - {1, oid_null_function}, /* 0x44 */ - {1, oid_null_function} /* 0x45 */ -}; - -static const struct oid_obj_priv oid_rtl_seg_81_80_80[] = { - {1, oid_null_function}, /* 0x80 OID_RT_DRIVER_OPTION */ - {1, oid_null_function}, /* 0x81 OID_RT_RF_OFF */ - {1, oid_null_function} /* 0x82 OID_RT_AUTH_STATUS */ - -}; - -static const struct oid_obj_priv oid_rtl_seg_81_85[] = { - /* 0x00 OID_RT_WIRELESS_MODE */ - {1, oid_rt_wireless_mode_hdl} -}; #else /* _RTL871X_MP_IOCTL_C_ */ -extern struct oid_obj_priv oid_rtl_seg_81_80_00[32]; -extern struct oid_obj_priv oid_rtl_seg_81_80_20[16]; -extern struct oid_obj_priv oid_rtl_seg_81_80_40[6]; -extern struct oid_obj_priv oid_rtl_seg_81_80_80[3]; -extern struct oid_obj_priv oid_rtl_seg_81_85[1]; extern struct oid_obj_priv oid_rtl_seg_81_87[5]; extern struct oid_obj_priv oid_rtl_seg_87_11_00[32]; extern struct oid_obj_priv oid_rtl_seg_87_11_20[5]; diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c index db2add576418..c23f6b376111 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ b/drivers/staging/rtl8712/rtl871x_recv.c @@ -374,7 +374,7 @@ static sint ap2sta_data_frame(struct _adapter *adapter, if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && check_fwstate(pmlmepriv, _FW_LINKED)) { /* if NULL-frame, drop packet */ - if ((GetFrameSubType(ptr)) == IEEE80211_STYPE_NULLFUNC) + if ((GetFrameSubType(ptr)) == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC)) return _FAIL; /* drop QoS-SubType Data, including QoS NULL, * excluding QoS-Data diff --git a/drivers/staging/rtl8712/rtl871x_security.c b/drivers/staging/rtl8712/rtl871x_security.c index 63d63f7be481..e0a1c30a8fe6 100644 --- a/drivers/staging/rtl8712/rtl871x_security.c +++ b/drivers/staging/rtl8712/rtl871x_security.c @@ -1045,9 +1045,9 @@ static void aes_cipher(u8 *key, uint hdrlen, else a4_exists = 1; - if ((frtype == IEEE80211_STYPE_DATA_CFACK) || - (frtype == IEEE80211_STYPE_DATA_CFPOLL) || - (frtype == IEEE80211_STYPE_DATA_CFACKPOLL)) { + if ((frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFACK)) || + (frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFPOLL)) || + (frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFACKPOLL))) { qc_exists = 1; if (hdrlen != WLAN_HDR_A3_QOS_LEN) hdrlen += 2; @@ -1225,9 +1225,9 @@ static void aes_decipher(u8 *key, uint hdrlen, a4_exists = 0; else a4_exists = 1; - if ((frtype == IEEE80211_STYPE_DATA_CFACK) || - (frtype == IEEE80211_STYPE_DATA_CFPOLL) || - (frtype == IEEE80211_STYPE_DATA_CFACKPOLL)) { + if ((frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFACK)) || + (frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFPOLL)) || + (frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFACKPOLL))) { qc_exists = 1; if (hdrlen != WLAN_HDR_A3_QOS_LEN) hdrlen += 2; diff --git a/drivers/staging/rtl8712/rtl871x_sta_mgt.c b/drivers/staging/rtl8712/rtl871x_sta_mgt.c index 706e9db0fc5b..2c806a0105bf 100644 --- a/drivers/staging/rtl8712/rtl871x_sta_mgt.c +++ b/drivers/staging/rtl8712/rtl871x_sta_mgt.c @@ -257,7 +257,6 @@ struct sta_info *r8712_get_bcmc_stainfo(struct _adapter *padapter) return r8712_get_stainfo(pstapriv, bc_addr); } - u8 r8712_access_ctrl(struct wlan_acl_pool *pacl_list, u8 *mac_addr) { return true; diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index bb4de927fb02..090345bad223 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -846,7 +846,6 @@ static inline struct tx_servq *get_sta_pending(struct _adapter *padapter, struct __queue **ppstapending, struct sta_info *psta, sint up) { - struct tx_servq *ptxservq; struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits; diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index dc21e7743349..2434b13c8b12 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -36,7 +36,6 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, static void r871xu_dev_remove(struct usb_interface *pusb_intf); static const struct usb_device_id rtl871x_usb_id_tbl[] = { - /* RTL8188SU */ /* Realtek */ {USB_DEVICE(0x0BDA, 0x8171)}, @@ -361,7 +360,7 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, /* step 1. */ pnetdev = r8712_init_netdev(); if (!pnetdev) - goto error; + goto put_dev; padapter = netdev_priv(pnetdev); disable_ht_for_spec_devid(pdid, padapter); pdvobjpriv = &padapter->dvobjpriv; @@ -380,17 +379,15 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, /* step 3. * initialize the dvobj_priv */ - if (!padapter->dvobj_init) { - goto error; - } else { - status = padapter->dvobj_init(padapter); - if (status != _SUCCESS) - goto error; - } + + status = padapter->dvobj_init(padapter); + if (status != _SUCCESS) + goto free_netdev; + /* step 4. */ status = r8712_init_drv_sw(padapter); if (status) - goto error; + goto dvobj_deinit; /* step 5. read efuse/eeprom data and get mac_addr */ { int i, offset; @@ -570,17 +567,20 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, } /* step 6. Load the firmware asynchronously */ if (rtl871x_load_fw(padapter)) - goto error; + goto deinit_drv_sw; spin_lock_init(&padapter->lock_rx_ff0_filter); mutex_init(&padapter->mutex_start); return 0; -error: + +deinit_drv_sw: + r8712_free_drv_sw(padapter); +dvobj_deinit: + padapter->dvobj_deinit(padapter); +free_netdev: + free_netdev(pnetdev); +put_dev: usb_put_dev(udev); usb_set_intfdata(pusb_intf, NULL); - if (padapter && padapter->dvobj_deinit) - padapter->dvobj_deinit(padapter); - if (pnetdev) - free_netdev(pnetdev); return -ENODEV; } @@ -612,6 +612,7 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf) r8712_stop_drv_timers(padapter); r871x_dev_unload(padapter); r8712_free_drv_sw(padapter); + free_netdev(pnetdev); /* decrease the reference count of the usb device structure * when disconnect diff --git a/drivers/staging/rtl8712/xmit_linux.c b/drivers/staging/rtl8712/xmit_linux.c index 1f67d86c606f..90d34cf9d2ff 100644 --- a/drivers/staging/rtl8712/xmit_linux.c +++ b/drivers/staging/rtl8712/xmit_linux.c @@ -62,7 +62,6 @@ sint r8712_endofpktfile(struct pkt_file *pfile) return (pfile->pkt_len == 0); } - void r8712_set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib) { struct ethhdr etherhdr; diff --git a/drivers/staging/rtl8723bs/Makefile b/drivers/staging/rtl8723bs/Makefile index dfe410283ca0..fe45200ff53c 100644 --- a/drivers/staging/rtl8723bs/Makefile +++ b/drivers/staging/rtl8723bs/Makefile @@ -28,14 +28,12 @@ r8723bs-y = \ hal/HalPwrSeqCmd.o \ hal/odm.o \ hal/odm_CfoTracking.o \ - hal/odm_debug.o \ hal/odm_DIG.o \ hal/odm_DynamicBBPowerSaving.o \ hal/odm_DynamicTxPower.o \ hal/odm_EdcaTurboCheck.o \ hal/odm_HWConfig.o \ hal/odm_NoiseMonitor.o \ - hal/odm_PathDiv.o \ hal/odm_RegConfig8723B.o \ hal/odm_RTL8723B.o \ hal/rtl8723b_cmd.o \ diff --git a/drivers/staging/rtl8723bs/TODO b/drivers/staging/rtl8723bs/TODO index afa620ceb2d8..3d8f5a634a10 100644 --- a/drivers/staging/rtl8723bs/TODO +++ b/drivers/staging/rtl8723bs/TODO @@ -1,6 +1,4 @@ TODO: -- find and remove remaining code valid only for 5 GHz. Most of the obvious - ones have been removed, but things like channel > 14 still exist. - find and remove any code for other chips that is left over - convert any remaining unusual variable types - find codes that can use %pM and %Nph formatting diff --git a/drivers/staging/rtl8723bs/core/rtw_ap.c b/drivers/staging/rtl8723bs/core/rtw_ap.c index 4a9bd4825fab..a6fcb5e9d637 100644 --- a/drivers/staging/rtl8723bs/core/rtw_ap.c +++ b/drivers/staging/rtl8723bs/core/rtw_ap.c @@ -59,116 +59,112 @@ static void update_BCNTIM(struct adapter *padapter) unsigned char *pie = pnetwork_mlmeext->IEs; /* update TIM IE */ - /* if (pstapriv->tim_bitmap) */ - if (true) { - u8 *p, *dst_ie, *premainder_ie = NULL, *pbackup_remainder_ie = NULL; - __le16 tim_bitmap_le; - uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen; - - tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap); - - p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, - WLAN_EID_TIM, - &tim_ielen, - pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_ - ); - if (p && tim_ielen > 0) { - tim_ielen += 2; + u8 *p, *dst_ie, *premainder_ie = NULL, *pbackup_remainder_ie = NULL; + __le16 tim_bitmap_le; + uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen; - premainder_ie = p + tim_ielen; + tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap); - tim_ie_offset = (signed int)(p - pie); + p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, + WLAN_EID_TIM, + &tim_ielen, + pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_ + ); + if (p && tim_ielen > 0) { + tim_ielen += 2; - remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen; + premainder_ie = p + tim_ielen; - /* append TIM IE from dst_ie offset */ - dst_ie = p; - } else { - tim_ielen = 0; + tim_ie_offset = (signed int)(p - pie); - /* calculate head_len */ - offset = _FIXED_IE_LENGTH_; + remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen; - /* get ssid_ie len */ - p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, - WLAN_EID_SSID, - &tmp_len, - (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_) - ); - if (p) - offset += tmp_len + 2; + /* append TIM IE from dst_ie offset */ + dst_ie = p; + } else { + tim_ielen = 0; - /* get supported rates len */ - p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, - WLAN_EID_SUPP_RATES, &tmp_len, - (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_) - ); - if (p) - offset += tmp_len + 2; + /* calculate head_len */ + offset = _FIXED_IE_LENGTH_; - /* DS Parameter Set IE, len =3 */ - offset += 3; + /* get ssid_ie len */ + p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, + WLAN_EID_SSID, + &tmp_len, + (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_) + ); + if (p) + offset += tmp_len + 2; - premainder_ie = pie + offset; + /* get supported rates len */ + p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, + WLAN_EID_SUPP_RATES, &tmp_len, + (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_) + ); + if (p) + offset += tmp_len + 2; - remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen; + /* DS Parameter Set IE, len =3 */ + offset += 3; - /* append TIM IE from offset */ - dst_ie = pie + offset; - } + premainder_ie = pie + offset; - if (remainder_ielen > 0) { - pbackup_remainder_ie = rtw_malloc(remainder_ielen); - if (pbackup_remainder_ie && premainder_ie) - memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen); - } + remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen; - *dst_ie++ = WLAN_EID_TIM; + /* append TIM IE from offset */ + dst_ie = pie + offset; + } - if ((pstapriv->tim_bitmap & 0xff00) && (pstapriv->tim_bitmap & 0x00fe)) - tim_ielen = 5; - else - tim_ielen = 4; + if (remainder_ielen > 0) { + pbackup_remainder_ie = rtw_malloc(remainder_ielen); + if (pbackup_remainder_ie && premainder_ie) + memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen); + } - *dst_ie++ = tim_ielen; + *dst_ie++ = WLAN_EID_TIM; - *dst_ie++ = 0;/* DTIM count */ - *dst_ie++ = 1;/* DTIM period */ + if ((pstapriv->tim_bitmap & 0xff00) && (pstapriv->tim_bitmap & 0x00fe)) + tim_ielen = 5; + else + tim_ielen = 4; - if (pstapriv->tim_bitmap & BIT(0))/* for bc/mc frames */ - *dst_ie++ = BIT(0);/* bitmap ctrl */ - else - *dst_ie++ = 0; + *dst_ie++ = tim_ielen; - if (tim_ielen == 4) { - __le16 pvb; + *dst_ie++ = 0;/* DTIM count */ + *dst_ie++ = 1;/* DTIM period */ - if (pstapriv->tim_bitmap & 0xff00) - pvb = cpu_to_le16(pstapriv->tim_bitmap >> 8); - else - pvb = tim_bitmap_le; + if (pstapriv->tim_bitmap & BIT(0))/* for bc/mc frames */ + *dst_ie++ = BIT(0);/* bitmap ctrl */ + else + *dst_ie++ = 0; - *dst_ie++ = le16_to_cpu(pvb); + if (tim_ielen == 4) { + __le16 pvb; - } else if (tim_ielen == 5) { - memcpy(dst_ie, &tim_bitmap_le, 2); - dst_ie += 2; - } + if (pstapriv->tim_bitmap & 0xff00) + pvb = cpu_to_le16(pstapriv->tim_bitmap >> 8); + else + pvb = tim_bitmap_le; - /* copy remainder IE */ - if (pbackup_remainder_ie) { - memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen); + *dst_ie++ = le16_to_cpu(pvb); - kfree(pbackup_remainder_ie); - } + } else if (tim_ielen == 5) { + memcpy(dst_ie, &tim_bitmap_le, 2); + dst_ie += 2; + } + + /* copy remainder IE */ + if (pbackup_remainder_ie) { + memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen); - offset = (uint)(dst_ie - pie); - pnetwork_mlmeext->IELength = offset + remainder_ielen; + kfree(pbackup_remainder_ie); } + + offset = (uint)(dst_ie - pie); + pnetwork_mlmeext->IELength = offset + remainder_ielen; } -u8 chk_sta_is_alive(struct sta_info *psta); -u8 chk_sta_is_alive(struct sta_info *psta) +static u8 chk_sta_is_alive(struct sta_info *psta) { sta_update_last_rx_pkts(psta); @@ -177,7 +173,7 @@ u8 chk_sta_is_alive(struct sta_info *psta) void expire_timeout_chk(struct adapter *padapter) { - struct list_head *phead, *plist; + struct list_head *phead, *plist, *tmp; u8 updated = false; struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; @@ -188,13 +184,9 @@ void expire_timeout_chk(struct adapter *padapter) spin_lock_bh(&pstapriv->auth_list_lock); phead = &pstapriv->auth_list; - plist = get_next(phead); - /* check auth_queue */ - while (phead != plist) { - psta = container_of(plist, struct sta_info, auth_list); - - plist = get_next(plist); + list_for_each_safe(plist, tmp, phead) { + psta = list_entry(plist, struct sta_info, auth_list); if (psta->expire_to > 0) { psta->expire_to--; @@ -217,12 +209,9 @@ void expire_timeout_chk(struct adapter *padapter) spin_lock_bh(&pstapriv->asoc_list_lock); phead = &pstapriv->asoc_list; - plist = get_next(phead); - /* check asoc_queue */ - while (phead != plist) { - psta = container_of(plist, struct sta_info, asoc_list); - plist = get_next(plist); + list_for_each_safe(plist, tmp, phead) { + psta = list_entry(plist, struct sta_info, asoc_list); if (chk_sta_is_alive(psta) || !psta->expire_to) { psta->expire_to = pstapriv->expire_to; psta->keep_alive_trycnt = 0; @@ -352,11 +341,7 @@ void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level) shortGIrate = query_ra_short_GI(psta); if (pcur_network->Configuration.DSConfig > 14) { - if (tx_ra_bitmap & 0xffff000) - sta_band |= WIRELESS_11_5N; - - if (tx_ra_bitmap & 0xff0) - sta_band |= WIRELESS_11A; + sta_band |= WIRELESS_INVALID; } else { if (tx_ra_bitmap & 0xffff000) sta_band |= WIRELESS_11_24N; @@ -422,7 +407,7 @@ void update_bmc_sta(struct adapter *padapter) } else if (network_type == WIRELESS_INVALID) { /* error handling */ if (pcur_network->Configuration.DSConfig > 14) - network_type = WIRELESS_11A; + network_type = WIRELESS_INVALID; else network_type = WIRELESS_11B; } @@ -653,7 +638,7 @@ static void update_hw_ht_param(struct adapter *padapter) /* pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3; */ } -void start_bss_network(struct adapter *padapter, u8 *pbuf) +void start_bss_network(struct adapter *padapter) { u8 *p; u8 val8, cur_channel, cur_bwmode, cur_ch_offset; @@ -1125,9 +1110,6 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) case WIRELESS_11BG_24N: pbss_network->NetworkTypeInUse = Ndis802_11OFDM24; break; - case WIRELESS_11A: - pbss_network->NetworkTypeInUse = Ndis802_11OFDM5; - break; default: pbss_network->NetworkTypeInUse = Ndis802_11OFDM24; break; @@ -1210,11 +1192,8 @@ int rtw_acl_add_sta(struct adapter *padapter, u8 *addr) spin_lock_bh(&(pacl_node_q->lock)); phead = get_list_head(pacl_node_q); - plist = get_next(phead); - - while (phead != plist) { - paclnode = container_of(plist, struct rtw_wlan_acl_node, list); - plist = get_next(plist); + list_for_each(plist, phead) { + paclnode = list_entry(plist, struct rtw_wlan_acl_node, list); if (!memcmp(paclnode->addr, addr, ETH_ALEN)) { if (paclnode->valid == true) { @@ -1256,7 +1235,7 @@ int rtw_acl_add_sta(struct adapter *padapter, u8 *addr) void rtw_acl_remove_sta(struct adapter *padapter, u8 *addr) { - struct list_head *plist, *phead; + struct list_head *plist, *phead, *tmp; struct rtw_wlan_acl_node *paclnode; struct sta_priv *pstapriv = &padapter->stapriv; struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; @@ -1266,11 +1245,8 @@ void rtw_acl_remove_sta(struct adapter *padapter, u8 *addr) spin_lock_bh(&(pacl_node_q->lock)); phead = get_list_head(pacl_node_q); - plist = get_next(phead); - - while (phead != plist) { - paclnode = container_of(plist, struct rtw_wlan_acl_node, list); - plist = get_next(plist); + list_for_each_safe(plist, tmp, phead) { + paclnode = list_entry(plist, struct rtw_wlan_acl_node, list); if ( !memcmp(paclnode->addr, addr, ETH_ALEN) || @@ -1716,13 +1692,9 @@ void associated_clients_update(struct adapter *padapter, u8 updated) spin_lock_bh(&pstapriv->asoc_list_lock); phead = &pstapriv->asoc_list; - plist = get_next(phead); - /* check asoc_queue */ - while (phead != plist) { - psta = container_of(plist, struct sta_info, asoc_list); - - plist = get_next(plist); + list_for_each(plist, phead) { + psta = list_entry(plist, struct sta_info, asoc_list); VCS_update(padapter, psta); } @@ -1960,7 +1932,7 @@ u8 ap_free_sta( void rtw_sta_flush(struct adapter *padapter) { - struct list_head *phead, *plist; + struct list_head *phead, *plist, *tmp; struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; @@ -1972,13 +1944,9 @@ void rtw_sta_flush(struct adapter *padapter) spin_lock_bh(&pstapriv->asoc_list_lock); phead = &pstapriv->asoc_list; - plist = get_next(phead); - /* free sta asoc_queue */ - while (phead != plist) { - psta = container_of(plist, struct sta_info, asoc_list); - - plist = get_next(plist); + list_for_each_safe(plist, tmp, phead) { + psta = list_entry(plist, struct sta_info, asoc_list); list_del_init(&psta->asoc_list); pstapriv->asoc_list_cnt--; @@ -2039,7 +2007,6 @@ void ap_sta_info_defer_update(struct adapter *padapter, struct sta_info *psta) /* restore hw setting from sw data structures */ void rtw_ap_restore_network(struct adapter *padapter) { - struct mlme_priv *mlmepriv = &padapter->mlmepriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct sta_priv *pstapriv = &padapter->stapriv; struct sta_info *psta; @@ -2058,7 +2025,7 @@ void rtw_ap_restore_network(struct adapter *padapter) pmlmeext->cur_bwmode ); - start_bss_network(padapter, (u8 *)&mlmepriv->cur_network.network); + start_bss_network(padapter); if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) || (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) { @@ -2075,13 +2042,10 @@ void rtw_ap_restore_network(struct adapter *padapter) spin_lock_bh(&pstapriv->asoc_list_lock); phead = &pstapriv->asoc_list; - plist = get_next(phead); - - while (phead != plist) { + list_for_each(plist, phead) { int stainfo_offset; - psta = container_of(plist, struct sta_info, asoc_list); - plist = get_next(plist); + psta = list_entry(plist, struct sta_info, asoc_list); stainfo_offset = rtw_stainfo_offset(pstapriv, psta); if (stainfo_offset_valid(stainfo_offset)) @@ -2160,7 +2124,7 @@ void start_ap_mode(struct adapter *padapter) void stop_ap_mode(struct adapter *padapter) { - struct list_head *phead, *plist; + struct list_head *phead, *plist, *tmp; struct rtw_wlan_acl_node *paclnode; struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; @@ -2184,10 +2148,8 @@ void stop_ap_mode(struct adapter *padapter) /* for ACL */ spin_lock_bh(&(pacl_node_q->lock)); phead = get_list_head(pacl_node_q); - plist = get_next(phead); - while (phead != plist) { - paclnode = container_of(plist, struct rtw_wlan_acl_node, list); - plist = get_next(plist); + list_for_each_safe(plist, tmp, phead) { + paclnode = list_entry(plist, struct rtw_wlan_acl_node, list); if (paclnode->valid) { paclnode->valid = false; diff --git a/drivers/staging/rtl8723bs/core/rtw_cmd.c b/drivers/staging/rtl8723bs/core/rtw_cmd.c index e1a8f8b47edd..04956ccf485c 100644 --- a/drivers/staging/rtl8723bs/core/rtw_cmd.c +++ b/drivers/staging/rtl8723bs/core/rtw_cmd.c @@ -4,8 +4,6 @@ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. * ******************************************************************************/ -#define _RTW_CMD_C_ - #include <drv_types.h> #include <rtw_debug.h> #include <hal_btcoex.h> @@ -157,9 +155,9 @@ static struct cmd_hdl wlancmds[] = { }; /* -Caller and the rtw_cmd_thread can protect cmd_q by spin_lock. -No irqsave is necessary. -*/ + * Caller and the rtw_cmd_thread can protect cmd_q by spin_lock. + * No irqsave is necessary. + */ int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv) { @@ -225,6 +223,7 @@ void _rtw_free_evt_priv(struct evt_priv *pevtpriv) while (!rtw_cbuf_empty(pevtpriv->c2h_queue)) { void *c2h = rtw_cbuf_pop(pevtpriv->c2h_queue); + if (c2h && c2h != (void *)pevtpriv) kfree(c2h); } @@ -243,14 +242,14 @@ void _rtw_free_cmd_priv(struct cmd_priv *pcmdpriv) } /* -Calling Context: - -rtw_enqueue_cmd can only be called between kernel thread, -since only spin_lock is used. - -ISR/Call-Back functions can't call this sub-function. - -*/ + * Calling Context: + * + * rtw_enqueue_cmd can only be called between kernel thread, + * since only spin_lock is used. + * + * ISR/Call-Back functions can't call this sub-function. + * + */ int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj) { @@ -529,10 +528,11 @@ post_process: } /* -rtw_sitesurvey_cmd(~) - ### NOTE:#### (!!!!) - MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock -*/ + * rtw_sitesurvey_cmd(~) + * ### NOTE:#### (!!!!) + * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock + */ + u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, int ssid_num, struct rtw_ieee80211_channel *ch, int ch_num) { @@ -565,6 +565,7 @@ u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, /* prepare ssid list */ if (ssid) { int i; + for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) { if (ssid[i].SsidLength) { memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid)); @@ -576,6 +577,7 @@ u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, /* prepare channel list */ if (ch) { int i; + for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) { if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) { memcpy(&psurveyPara->ch[i], &ch[i], sizeof(struct rtw_ieee80211_channel)); @@ -671,7 +673,7 @@ int rtw_startbss_cmd(struct adapter *padapter, int flags) if (flags & RTW_CMDF_DIRECTLY) { /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ - start_bss_network(padapter, (u8 *)&(padapter->mlmepriv.cur_network.network)); + start_bss_network(padapter); } else { /* need enqueue, prepare cmd_obj and enqueue */ pcmd = rtw_zmalloc(sizeof(struct cmd_obj)); @@ -695,7 +697,7 @@ int rtw_startbss_cmd(struct adapter *padapter, int flags) res = rtw_enqueue_cmd(pcmdpriv, pcmd); if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) { - rtw_sctx_wait(&sctx, __func__); + rtw_sctx_wait(&sctx); if (mutex_lock_interruptible(&pcmdpriv->sctx_mutex) == 0) { if (sctx.status == RTW_SCTX_SUBMITTED) pcmd->sctx = NULL; @@ -1337,6 +1339,7 @@ u8 traffic_status_watchdog(struct adapter *padapter, u8 from_timer) static void dynamic_chk_wk_hdl(struct adapter *padapter) { struct mlme_priv *pmlmepriv; + pmlmepriv = &(padapter->mlmepriv); if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) diff --git a/drivers/staging/rtl8723bs/core/rtw_debug.c b/drivers/staging/rtl8723bs/core/rtw_debug.c index 79fd968bb147..576b039f741c 100644 --- a/drivers/staging/rtl8723bs/core/rtw_debug.c +++ b/drivers/staging/rtl8723bs/core/rtw_debug.c @@ -10,60 +10,56 @@ #include <rtw_debug.h> #include <hal_btcoex.h> -u32 GlobalDebugLevel = _drv_err_; - #include <rtw_version.h> -void sd_f0_reg_dump(void *sel, struct adapter *adapter) +static void dump_4_regs(struct adapter *adapter, int offset) { + u32 reg[4]; int i; - for (i = 0x0; i <= 0xff; i++) { - if (i%16 == 0) - netdev_dbg(adapter->pnetdev, "0x%02x ", i); - - DBG_871X_SEL(sel, "%02x ", rtw_sd_f0_read8(adapter, i)); + for (i = 0; i < 4; i++) + reg[i] = rtw_read32(adapter, offset + i); - if (i%16 == 15) - DBG_871X_SEL(sel, "\n"); - else if (i%8 == 7) - DBG_871X_SEL(sel, "\t"); - } + netdev_dbg(adapter->pnetdev, "0x%03x 0x%08x 0x%08x 0x%08x 0x%08x\n", + i, reg[0], reg[1], reg[2], reg[3]); } -void mac_reg_dump(void *sel, struct adapter *adapter) +void mac_reg_dump(struct adapter *adapter) { - int i, j = 1; + int i; netdev_dbg(adapter->pnetdev, "======= MAC REG =======\n"); - for (i = 0x0; i < 0x800; i += 4) { - if (j%4 == 1) - netdev_dbg(adapter->pnetdev, "0x%03x", i); - DBG_871X_SEL(sel, " 0x%08x ", rtw_read32(adapter, i)); - if ((j++)%4 == 0) - DBG_871X_SEL(sel, "\n"); - } + for (i = 0x0; i < 0x800; i += 4) + dump_4_regs(adapter, i); } -void bb_reg_dump(void *sel, struct adapter *adapter) +void bb_reg_dump(struct adapter *adapter) { - int i, j = 1; + int i; netdev_dbg(adapter->pnetdev, "======= BB REG =======\n"); - for (i = 0x800; i < 0x1000 ; i += 4) { - if (j%4 == 1) - netdev_dbg(adapter->pnetdev, "0x%03x", i); - DBG_871X_SEL(sel, " 0x%08x ", rtw_read32(adapter, i)); - if ((j++)%4 == 0) - DBG_871X_SEL(sel, "\n"); - } + + for (i = 0x800; i < 0x1000 ; i += 4) + dump_4_regs(adapter, i); +} + +static void dump_4_rf_regs(struct adapter *adapter, int path, int offset) +{ + u8 reg[4]; + int i; + + for (i = 0; i < 4; i++) + reg[i] = rtw_hal_read_rfreg(adapter, path, offset + i, + 0xffffffff); + + netdev_dbg(adapter->pnetdev, "0x%02x 0x%08x 0x%08x 0x%08x 0x%08x\n", + i, reg[0], reg[1], reg[2], reg[3]); } -void rf_reg_dump(void *sel, struct adapter *adapter) +void rf_reg_dump(struct adapter *adapter) { - int i, j = 1, path; - u32 value; + int i, path; u8 rf_type = 0; u8 path_nums = 0; @@ -77,13 +73,7 @@ void rf_reg_dump(void *sel, struct adapter *adapter) for (path = 0; path < path_nums; path++) { netdev_dbg(adapter->pnetdev, "RF_Path(%x)\n", path); - for (i = 0; i < 0x100; i++) { - value = rtw_hal_read_rfreg(adapter, path, i, 0xffffffff); - if (j%4 == 1) - netdev_dbg(adapter->pnetdev, "0x%02x ", i); - DBG_871X_SEL(sel, " 0x%08x ", value); - if ((j++)%4 == 0) - DBG_871X_SEL(sel, "\n"); - } + for (i = 0; i < 0x100; i++) + dump_4_rf_regs(adapter, path, i); } } diff --git a/drivers/staging/rtl8723bs/core/rtw_eeprom.c b/drivers/staging/rtl8723bs/core/rtw_eeprom.c deleted file mode 100644 index be0eda1604d0..000000000000 --- a/drivers/staging/rtl8723bs/core/rtw_eeprom.c +++ /dev/null @@ -1,210 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#define _RTW_EEPROM_C_ - -#include <drv_conf.h> -#include <osdep_service.h> -#include <drv_types.h> - -void up_clk(_adapter *padapter, u16 *x) -{ -_func_enter_; - *x = *x | _EESK; - rtw_write8(padapter, EE_9346CR, (u8)*x); - udelay(CLOCK_RATE); - -_func_exit_; - -} - -void down_clk(_adapter *padapter, u16 *x) -{ -_func_enter_; - *x = *x & ~_EESK; - rtw_write8(padapter, EE_9346CR, (u8)*x); - udelay(CLOCK_RATE); -_func_exit_; -} - -void shift_out_bits(_adapter *padapter, u16 data, u16 count) -{ - u16 x, mask; -_func_enter_; - - if (padapter->bSurpriseRemoved) - goto out; - - mask = 0x01 << (count - 1); - x = rtw_read8(padapter, EE_9346CR); - - x &= ~(_EEDO | _EEDI); - - do { - x &= ~_EEDI; - if (data & mask) - x |= _EEDI; - if (padapter->bSurpriseRemoved) - goto out; - - rtw_write8(padapter, EE_9346CR, (u8)x); - udelay(CLOCK_RATE); - up_clk(padapter, &x); - down_clk(padapter, &x); - mask = mask >> 1; - } while (mask); - if (padapter->bSurpriseRemoved) - goto out; - - x &= ~_EEDI; - rtw_write8(padapter, EE_9346CR, (u8)x); -out: -_func_exit_; -} - -u16 shift_in_bits(_adapter *padapter) -{ - u16 x, d = 0, i; -_func_enter_; - if (padapter->bSurpriseRemoved) - goto out; - - x = rtw_read8(padapter, EE_9346CR); - - x &= ~(_EEDO | _EEDI); - d = 0; - - for (i = 0; i < 16; i++) { - d = d << 1; - up_clk(padapter, &x); - if (padapter->bSurpriseRemoved) - goto out; - - x = rtw_read8(padapter, EE_9346CR); - - x &= ~(_EEDI); - if (x & _EEDO) - d |= 1; - - down_clk(padapter, &x); - } -out: -_func_exit_; - - return d; -} - -void standby(_adapter *padapter) -{ - u8 x; -_func_enter_; - x = rtw_read8(padapter, EE_9346CR); - - x &= ~(_EECS | _EESK); - rtw_write8(padapter, EE_9346CR, x); - - udelay(CLOCK_RATE); - x |= _EECS; - rtw_write8(padapter, EE_9346CR, x); - udelay(CLOCK_RATE); -_func_exit_; -} - -void eeprom_clean(_adapter *padapter) -{ - u16 x; -_func_enter_; - if (padapter->bSurpriseRemoved) - goto out; - - x = rtw_read8(padapter, EE_9346CR); - if (padapter->bSurpriseRemoved) - goto out; - - x &= ~(_EECS | _EEDI); - rtw_write8(padapter, EE_9346CR, (u8)x); - if (padapter->bSurpriseRemoved) - goto out; - - up_clk(padapter, &x); - if (padapter->bSurpriseRemoved) - goto out; - - down_clk(padapter, &x); -out: -_func_exit_; -} - -u16 eeprom_read16(_adapter *padapter, u16 reg) /*ReadEEprom*/ -{ - - u16 x; - u16 data = 0; - -_func_enter_; - - if (padapter->bSurpriseRemoved) - goto out; - - /* select EEPROM, reset bits, set _EECS*/ - x = rtw_read8(padapter, EE_9346CR); - - if (padapter->bSurpriseRemoved) - goto out; - - x &= ~(_EEDI | _EEDO | _EESK | _EEM0); - x |= _EEM1 | _EECS; - rtw_write8(padapter, EE_9346CR, (unsigned char)x); - - /* write the read opcode and register number in that order*/ - /* The opcode is 3bits in length, reg is 6 bits long*/ - shift_out_bits(padapter, EEPROM_READ_OPCODE, 3); - shift_out_bits(padapter, reg, padapter->EepromAddressSize); - - /* Now read the data (16 bits) in from the selected EEPROM word*/ - data = shift_in_bits(padapter); - - eeprom_clean(padapter); -out: -_func_exit_; - return data; - - -} - -/*addr_off : address offset of the entry in eeprom (not the tuple number of eeprom (reg); that is addr_off !=reg)*/ -u8 eeprom_read(_adapter *padapter, u32 addr_off, u8 sz, u8 *rbuf) -{ - u8 quotient, remainder, addr_2align_odd; - u16 reg, stmp, i = 0, idx = 0; -_func_enter_; - reg = (u16)(addr_off >> 1); - addr_2align_odd = (u8)(addr_off & 0x1); - - /*read that start at high part: e.g 1,3,5,7,9,...*/ - if (addr_2align_odd) { - stmp = eeprom_read16(padapter, reg); - rbuf[idx++] = (u8) ((stmp>>8)&0xff); /*return hogh-part of the short*/ - reg++; sz--; - } - - quotient = sz >> 1; - remainder = sz & 0x1; - - for (i = 0; i < quotient; i++) { - stmp = eeprom_read16(padapter, reg+i); - rbuf[idx++] = (u8) (stmp&0xff); - rbuf[idx++] = (u8) ((stmp>>8)&0xff); - } - - reg = reg+i; - if (remainder) { /*end of read at lower part of short : 0,2,4,6,...*/ - stmp = eeprom_read16(padapter, reg); - rbuf[idx] = (u8)(stmp & 0xff); - } -_func_exit_; - return true; -} diff --git a/drivers/staging/rtl8723bs/core/rtw_efuse.c b/drivers/staging/rtl8723bs/core/rtw_efuse.c index a28a06d5a576..430e2d81924c 100644 --- a/drivers/staging/rtl8723bs/core/rtw_efuse.c +++ b/drivers/staging/rtl8723bs/core/rtw_efuse.c @@ -4,8 +4,6 @@ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. * ******************************************************************************/ -#define _RTW_EFUSE_C_ - #include <drv_types.h> #include <rtw_debug.h> #include <hal_data.h> @@ -40,7 +38,6 @@ Efuse_Read1ByteFromFakeContent( { if (Offset >= EFUSE_MAX_HW_SIZE) return false; - /* DbgPrint("Read fake content, offset = %d\n", Offset); */ if (fakeEfuseBank == 0) *Value = fakeEfuseContent[Offset]; else @@ -252,9 +249,8 @@ bool bPseudoTest) u8 bResult; u8 readbyte; - if (bPseudoTest) { + if (bPseudoTest) return Efuse_Read1ByteFromFakeContent(padapter, addr, data); - } /* <20130121, Kordan> For SMIC EFUSE specificatoin. */ /* 0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8]) */ @@ -294,9 +290,8 @@ u8 efuse_OneByteWrite(struct adapter *padapter, u16 addr, u8 data, bool bPseudoT u8 bResult = false; u32 efuseValue = 0; - if (bPseudoTest) { + if (bPseudoTest) return Efuse_Write1ByteToFakeContent(padapter, addr, data); - } /* -----------------e-fuse reg ctrl --------------------------------- */ @@ -322,11 +317,10 @@ u8 efuse_OneByteWrite(struct adapter *padapter, u16 addr, u8 data, bool bPseudoT tmpidx++; } - if (tmpidx < 100) { + if (tmpidx < 100) bResult = true; - } else { + else bResult = false; - } /* disable Efuse program enable */ PHY_SetMacReg(padapter, EFUSE_TEST, BIT(11), 0); diff --git a/drivers/staging/rtl8723bs/core/rtw_ieee80211.c b/drivers/staging/rtl8723bs/core/rtw_ieee80211.c index ae057eefeeb3..0f0fcd9dc652 100644 --- a/drivers/staging/rtl8723bs/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8723bs/core/rtw_ieee80211.c @@ -96,10 +96,7 @@ bool rtw_is_cckratesonly_included(u8 *rate) int rtw_check_network_type(unsigned char *rate, int ratelen, int channel) { if (channel > 14) { - if (rtw_is_cckrates_included(rate)) - return WIRELESS_INVALID; - else - return WIRELESS_11A; + return WIRELESS_INVALID; } else { /* could be pure B, pure G, or B/G */ if (rtw_is_cckratesonly_included(rate)) return WIRELESS_11B; @@ -239,12 +236,10 @@ int rtw_ies_remove_ie(u8 *ies, uint *ies_len, uint offset, u8 eid, u8 *oui, u8 o while (1) { target_ie = rtw_get_ie_ex(start, search_len, eid, oui, oui_len, NULL, &target_ielen); if (target_ie && target_ielen) { - u8 buf[MAX_IE_SZ] = {0}; u8 *remain_ies = target_ie + target_ielen; uint remain_len = search_len - (remain_ies - start); - memcpy(buf, remain_ies, remain_len); - memcpy(target_ie, buf, remain_len); + memcpy(target_ie, remain_ies, remain_len); *ies_len = *ies_len - target_ielen; ret = _SUCCESS; @@ -268,10 +263,6 @@ void rtw_set_supported_rate(u8 *SupportedRates, uint mode) break; case WIRELESS_11G: - case WIRELESS_11A: - case WIRELESS_11_5N: - case WIRELESS_11A_5N:/* Todo: no basic rate for ofdm ? */ - case WIRELESS_11_5AC: memcpy(SupportedRates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN); break; @@ -329,14 +320,7 @@ int rtw_generate_ie(struct registry_priv *pregistrypriv) ie = rtw_set_ie(ie, WLAN_EID_SSID, pdev_network->Ssid.SsidLength, pdev_network->Ssid.Ssid, &sz); /* supported rates */ - if (pregistrypriv->wireless_mode == WIRELESS_11ABGN) { - if (pdev_network->Configuration.DSConfig > 14) - wireless_mode = WIRELESS_11A_5N; - else - wireless_mode = WIRELESS_11BG_24N; - } else { - wireless_mode = pregistrypriv->wireless_mode; - } + wireless_mode = pregistrypriv->wireless_mode; rtw_set_supported_rate(pdev_network->SupportedRates, wireless_mode); @@ -361,8 +345,8 @@ int rtw_generate_ie(struct registry_priv *pregistrypriv) } /* HT Cap. */ - if (((pregistrypriv->wireless_mode&WIRELESS_11_5N) || (pregistrypriv->wireless_mode&WIRELESS_11_24N)) - && (pregistrypriv->ht_enable == true)) { + if ((pregistrypriv->wireless_mode & WIRELESS_11_24N) && + (pregistrypriv->ht_enable == true)) { /* todo: */ } @@ -877,7 +861,7 @@ static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen, } /** - * ieee802_11_parse_elems - Parse information elements in management frames + * rtw_ieee802_11_parse_elems - Parse information elements in management frames * @start: Pointer to the start of IEs * @len: Length of IE buffer in octets * @elems: Data structure for parsed elements diff --git a/drivers/staging/rtl8723bs/core/rtw_io.c b/drivers/staging/rtl8723bs/core/rtw_io.c index c860ab7d618c..856e23398c03 100644 --- a/drivers/staging/rtl8723bs/core/rtw_io.c +++ b/drivers/staging/rtl8723bs/core/rtw_io.c @@ -25,8 +25,6 @@ jackson@realtek.com.tw */ -#define _RTW_IO_C_ - #include <drv_types.h> #include <rtw_debug.h> @@ -35,7 +33,7 @@ jackson@realtek.com.tw #define rtw_cpu_to_le16(val) val #define rtw_cpu_to_le32(val) val -u8 _rtw_read8(struct adapter *adapter, u32 addr) +u8 rtw_read8(struct adapter *adapter, u32 addr) { /* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */ struct io_priv *pio_priv = &adapter->iopriv; @@ -47,7 +45,7 @@ u8 _rtw_read8(struct adapter *adapter, u32 addr) return _read8(pintfhdl, addr); } -u16 _rtw_read16(struct adapter *adapter, u32 addr) +u16 rtw_read16(struct adapter *adapter, u32 addr) { u16 r_val; /* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */ @@ -61,7 +59,7 @@ u16 _rtw_read16(struct adapter *adapter, u32 addr) return rtw_le16_to_cpu(r_val); } -u32 _rtw_read32(struct adapter *adapter, u32 addr) +u32 rtw_read32(struct adapter *adapter, u32 addr) { u32 r_val; /* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */ @@ -76,7 +74,7 @@ u32 _rtw_read32(struct adapter *adapter, u32 addr) } -int _rtw_write8(struct adapter *adapter, u32 addr, u8 val) +int rtw_write8(struct adapter *adapter, u32 addr, u8 val) { /* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */ struct io_priv *pio_priv = &adapter->iopriv; @@ -90,7 +88,7 @@ int _rtw_write8(struct adapter *adapter, u32 addr, u8 val) return RTW_STATUS_CODE(ret); } -int _rtw_write16(struct adapter *adapter, u32 addr, u16 val) +int rtw_write16(struct adapter *adapter, u32 addr, u16 val) { /* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */ struct io_priv *pio_priv = &adapter->iopriv; @@ -103,7 +101,7 @@ int _rtw_write16(struct adapter *adapter, u32 addr, u16 val) ret = _write16(pintfhdl, addr, val); return RTW_STATUS_CODE(ret); } -int _rtw_write32(struct adapter *adapter, u32 addr, u32 val) +int rtw_write32(struct adapter *adapter, u32 addr, u32 val) { /* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */ struct io_priv *pio_priv = &adapter->iopriv; @@ -118,26 +116,7 @@ int _rtw_write32(struct adapter *adapter, u32 addr, u32 val) return RTW_STATUS_CODE(ret); } -u8 _rtw_sd_f0_read8(struct adapter *adapter, u32 addr) -{ - u8 r_val = 0x00; - struct io_priv *pio_priv = &adapter->iopriv; - struct intf_hdl *pintfhdl = &(pio_priv->intf); - u8 (*_sd_f0_read8)(struct intf_hdl *pintfhdl, u32 addr); - - _sd_f0_read8 = pintfhdl->io_ops._sd_f0_read8; - - if (_sd_f0_read8) - r_val = _sd_f0_read8(pintfhdl, addr); - else - netdev_warn(adapter->pnetdev, - FUNC_ADPT_FMT " _sd_f0_read8 callback is NULL\n", - FUNC_ADPT_ARG(adapter)); - - return r_val; -} - -u32 _rtw_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem) +u32 rtw_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem) { u32 (*_write_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem); struct io_priv *pio_priv = &adapter->iopriv; diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rtl8723bs/core/rtw_mlme.c index 4707dba90397..2dd75e007239 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c @@ -4,8 +4,6 @@ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. * ******************************************************************************/ -#define _RTW_MLME_C_ - #include <linux/etherdevice.h> #include <drv_types.h> #include <rtw_debug.h> @@ -244,15 +242,11 @@ struct wlan_network *_rtw_find_network(struct __queue *scanned_queue, u8 *addr) /* spin_lock_bh(&scanned_queue->lock); */ phead = get_list_head(scanned_queue); - plist = get_next(phead); - - while (plist != phead) { - pnetwork = container_of(plist, struct wlan_network, list); + list_for_each(plist, phead) { + pnetwork = list_entry(plist, struct wlan_network, list); if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN)) break; - - plist = get_next(plist); } if (plist == phead) @@ -266,7 +260,7 @@ exit: void rtw_free_network_queue(struct adapter *padapter, u8 isfreeall) { - struct list_head *phead, *plist; + struct list_head *phead, *plist, *tmp; struct wlan_network *pnetwork; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct __queue *scanned_queue = &pmlmepriv->scanned_queue; @@ -274,13 +268,9 @@ void rtw_free_network_queue(struct adapter *padapter, u8 isfreeall) spin_lock_bh(&scanned_queue->lock); phead = get_list_head(scanned_queue); - plist = get_next(phead); - - while (phead != plist) { - - pnetwork = container_of(plist, struct wlan_network, list); + list_for_each_safe(plist, tmp, phead) { - plist = get_next(plist); + pnetwork = list_entry(plist, struct wlan_network, list); _rtw_free_network(pmlmepriv, pnetwork, isfreeall); @@ -422,15 +412,11 @@ struct wlan_network *_rtw_find_same_network(struct __queue *scanned_queue, struc struct wlan_network *found = NULL; phead = get_list_head(scanned_queue); - plist = get_next(phead); - - while (plist != phead) { - found = container_of(plist, struct wlan_network, list); + list_for_each(plist, phead) { + found = list_entry(plist, struct wlan_network, list); if (is_same_network(&network->network, &found->network, 0)) break; - - plist = get_next(plist); } if (plist == phead) @@ -448,21 +434,14 @@ struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue) phead = get_list_head(scanned_queue); - plist = get_next(phead); - - while (1) { - - if (phead == plist) - break; + list_for_each(plist, phead) { - pwlan = container_of(plist, struct wlan_network, list); + pwlan = list_entry(plist, struct wlan_network, list); if (!pwlan->fixed) { if (oldest == NULL || time_after(oldest->last_scanned, pwlan->last_scanned)) oldest = pwlan; } - - plist = get_next(plist); } return oldest; @@ -549,13 +528,8 @@ void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *t spin_lock_bh(&queue->lock); phead = get_list_head(queue); - plist = get_next(phead); - - while (1) { - if (phead == plist) - break; - - pnetwork = container_of(plist, struct wlan_network, list); + list_for_each(plist, phead) { + pnetwork = list_entry(plist, struct wlan_network, list); rtw_bug_check(pnetwork, pnetwork, pnetwork, pnetwork); @@ -571,8 +545,6 @@ void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *t if (oldest == NULL || time_after(oldest->last_scanned, pnetwork->last_scanned)) oldest = pnetwork; - plist = get_next(plist); - } /* If we didn't find a match, then get a new network slot to initialize @@ -1189,7 +1161,7 @@ static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_net /* define REJOIN */ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf) { - static u8 retry; + static u8 __maybe_unused retry; struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL; struct sta_priv *pstapriv = &adapter->stapriv; struct mlme_priv *pmlmepriv = &(adapter->mlmepriv); @@ -1788,17 +1760,10 @@ int rtw_select_roaming_candidate(struct mlme_priv *mlme) spin_lock_bh(&(mlme->scanned_queue.lock)); phead = get_list_head(queue); - mlme->pscanned = get_next(phead); - - while (phead != mlme->pscanned) { + list_for_each(mlme->pscanned, phead) { - pnetwork = container_of(mlme->pscanned, struct wlan_network, list); - if (!pnetwork) { - ret = _FAIL; - goto exit; - } - - mlme->pscanned = get_next(mlme->pscanned); + pnetwork = list_entry(mlme->pscanned, struct wlan_network, + list); rtw_check_roaming_candidate(mlme, &candidate, pnetwork); @@ -1892,17 +1857,10 @@ int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv) } phead = get_list_head(queue); - pmlmepriv->pscanned = get_next(phead); - - while (phead != pmlmepriv->pscanned) { - - pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list); - if (!pnetwork) { - ret = _FAIL; - goto exit; - } + list_for_each(pmlmepriv->pscanned, phead) { - pmlmepriv->pscanned = get_next(pmlmepriv->pscanned); + pnetwork = list_entry(pmlmepriv->pscanned, + struct wlan_network, list); rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork); @@ -2226,16 +2184,6 @@ void rtw_update_registrypriv_dev_network(struct adapter *adapter) case WIRELESS_11BG_24N: pdev_network->NetworkTypeInUse = (Ndis802_11OFDM24); break; - case WIRELESS_11A: - case WIRELESS_11A_5N: - pdev_network->NetworkTypeInUse = (Ndis802_11OFDM5); - break; - case WIRELESS_11ABGN: - if (pregistrypriv->channel > 14) - pdev_network->NetworkTypeInUse = (Ndis802_11OFDM5); - else - pdev_network->NetworkTypeInUse = (Ndis802_11OFDM24); - break; default: /* TODO */ break; @@ -2353,12 +2301,11 @@ void rtw_build_wmm_ie_ht(struct adapter *padapter, u8 *out_ie, uint *pout_len) { unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; int out_len; - u8 *pframe; if (padapter->mlmepriv.qospriv.qos_option == 0) { out_len = *pout_len; - pframe = rtw_set_ie(out_ie+out_len, WLAN_EID_VENDOR_SPECIFIC, - _WMM_IE_Length_, WMM_IE, pout_len); + rtw_set_ie(out_ie+out_len, WLAN_EID_VENDOR_SPECIFIC, + _WMM_IE_Length_, WMM_IE, pout_len); padapter->mlmepriv.qospriv.qos_option = 1; } @@ -2369,7 +2316,7 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ { u32 ielen, out_len; enum ieee80211_max_ampdu_length_exp max_rx_ampdu_factor; - unsigned char *p, *pframe; + unsigned char *p; struct ieee80211_ht_cap ht_capie; u8 cbw40_enable = 0, stbc_rx_enable = 0, rf_type = 0, operation_bw = 0; struct registry_priv *pregistrypriv = &padapter->registrypriv; @@ -2492,8 +2439,8 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ else ht_capie.ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00); - pframe = rtw_set_ie(out_ie+out_len, WLAN_EID_HT_CAPABILITY, - sizeof(struct ieee80211_ht_cap), (unsigned char *)&ht_capie, pout_len); + rtw_set_ie(out_ie+out_len, WLAN_EID_HT_CAPABILITY, + sizeof(struct ieee80211_ht_cap), (unsigned char *)&ht_capie, pout_len); phtpriv->ht_option = true; @@ -2501,7 +2448,7 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ p = rtw_get_ie(in_ie, WLAN_EID_HT_OPERATION, &ielen, in_len); if (p && (ielen == sizeof(struct ieee80211_ht_addt_info))) { out_len = *pout_len; - pframe = rtw_set_ie(out_ie+out_len, WLAN_EID_HT_OPERATION, ielen, p+2, pout_len); + rtw_set_ie(out_ie+out_len, WLAN_EID_HT_OPERATION, ielen, p+2, pout_len); } } @@ -2516,7 +2463,6 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len, u8 channe int len; /* struct sta_info *bmc_sta, *psta; */ struct ieee80211_ht_cap *pht_capie; - struct ieee80211_ht_addt_info *pht_addtinfo; /* struct recv_reorder_ctrl *preorder_ctrl; */ struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct ht_priv *phtpriv = &pmlmepriv->htpriv; @@ -2553,7 +2499,6 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len, u8 channe len = 0; p = rtw_get_ie(pie+sizeof(struct ndis_802_11_fix_ie), WLAN_EID_HT_OPERATION, &len, ie_len-sizeof(struct ndis_802_11_fix_ie)); if (p && len > 0) { - pht_addtinfo = (struct ieee80211_ht_addt_info *)(p+2); /* todo: */ } diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c index 9031cf7657ae..c128d462c6c7 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c @@ -4,8 +4,6 @@ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. * ******************************************************************************/ -#define _RTW_MLME_EXT_C_ - #include <drv_types.h> #include <rtw_debug.h> #include <rtw_wifi_regd.h> @@ -48,7 +46,6 @@ static struct action_handler OnAction_tbl[] = { {RTW_WLAN_CATEGORY_UNPROTECTED_WNM, "ACTION_UNPROTECTED_WNM", &DoReserved}, {RTW_WLAN_CATEGORY_SELF_PROTECTED, "ACTION_SELF_PROTECTED", &DoReserved}, {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &DoReserved}, - {RTW_WLAN_CATEGORY_VHT, "ACTION_VHT", &DoReserved}, {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &DoReserved}, }; @@ -81,135 +78,95 @@ static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = { {{}, 0}, /* 0x06, RT_CHANNEL_DOMAIN_2G_NULL */ }; -static struct rt_channel_plan_5g RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = { - {{}, 0}, /* 0x00, RT_CHANNEL_DOMAIN_5G_NULL */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 19}, /* 0x01, RT_CHANNEL_DOMAIN_5G_ETSI1 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24}, /* 0x02, RT_CHANNEL_DOMAIN_5G_ETSI2 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165}, 22}, /* 0x03, RT_CHANNEL_DOMAIN_5G_ETSI3 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24}, /* 0x04, RT_CHANNEL_DOMAIN_5G_FCC1 */ - {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9}, /* 0x05, RT_CHANNEL_DOMAIN_5G_FCC2 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13}, /* 0x06, RT_CHANNEL_DOMAIN_5G_FCC3 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12}, /* 0x07, RT_CHANNEL_DOMAIN_5G_FCC4 */ - {{149, 153, 157, 161, 165}, 5}, /* 0x08, RT_CHANNEL_DOMAIN_5G_FCC5 */ - {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, /* 0x09, RT_CHANNEL_DOMAIN_5G_FCC6 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 20}, /* 0x0A, RT_CHANNEL_DOMAIN_5G_FCC7_IC1 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, 165}, 20}, /* 0x0B, RT_CHANNEL_DOMAIN_5G_KCC1 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 19}, /* 0x0C, RT_CHANNEL_DOMAIN_5G_MKK1 */ - {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, /* 0x0D, RT_CHANNEL_DOMAIN_5G_MKK2 */ - {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11}, /* 0x0E, RT_CHANNEL_DOMAIN_5G_MKK3 */ - {{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 15}, /* 0x0F, RT_CHANNEL_DOMAIN_5G_NCC1 */ - {{56, 60, 64, 149, 153, 157, 161, 165}, 8}, /* 0x10, RT_CHANNEL_DOMAIN_5G_NCC2 */ - {{149, 153, 157, 161, 165}, 5}, /* 0x11, RT_CHANNEL_DOMAIN_5G_NCC3 */ - {{36, 40, 44, 48}, 4}, /* 0x12, RT_CHANNEL_DOMAIN_5G_ETSI4 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 20}, /* 0x13, RT_CHANNEL_DOMAIN_5G_ETSI5 */ - {{149, 153, 157, 161}, 4}, /* 0x14, RT_CHANNEL_DOMAIN_5G_FCC8 */ - {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, /* 0x15, RT_CHANNEL_DOMAIN_5G_ETSI6 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13}, /* 0x16, RT_CHANNEL_DOMAIN_5G_ETSI7 */ - {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9}, /* 0x17, RT_CHANNEL_DOMAIN_5G_ETSI8 */ - {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11}, /* 0x18, RT_CHANNEL_DOMAIN_5G_ETSI9 */ - {{149, 153, 157, 161, 165}, 5}, /* 0x19, RT_CHANNEL_DOMAIN_5G_ETSI10 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165}, 16}, /* 0x1A, RT_CHANNEL_DOMAIN_5G_ETSI11 */ - {{52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 17}, /* 0x1B, RT_CHANNEL_DOMAIN_5G_NCC4 */ - {{149, 153, 157, 161}, 4}, /* 0x1C, RT_CHANNEL_DOMAIN_5G_ETSI12 */ - {{36, 40, 44, 48, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 17}, /* 0x1D, RT_CHANNEL_DOMAIN_5G_FCC9 */ - {{36, 40, 44, 48, 100, 104, 108, 112, 116, 132, 136, 140}, 12}, /* 0x1E, RT_CHANNEL_DOMAIN_5G_ETSI13 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161}, 20}, /* 0x1F, RT_CHANNEL_DOMAIN_5G_FCC10 */ - - /* Driver self defined for old channel plan Compatible , Remember to modify if have new channel plan definition ===== */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 21}, /* 0x20, RT_CHANNEL_DOMAIN_5G_FCC */ - {{36, 40, 44, 48}, 4}, /* 0x21, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS */ - {{36, 40, 44, 48, 149, 153, 157, 161}, 8}, /* 0x22, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS */ -}; - static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = { /* 0x00 ~ 0x1F , Old Define ===== */ - {0x02, 0x20}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */ - {0x02, 0x0A}, /* 0x01, RT_CHANNEL_DOMAIN_IC */ - {0x01, 0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */ - {0x01, 0x00}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */ - {0x01, 0x00}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */ - {0x03, 0x00}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */ - {0x03, 0x00}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */ - {0x01, 0x09}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */ - {0x03, 0x09}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */ - {0x03, 0x00}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */ - {0x00, 0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */ - {0x02, 0x0F}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */ - {0x01, 0x08}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */ - {0x02, 0x06}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */ - {0x02, 0x0B}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */ - {0x02, 0x09}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */ - {0x01, 0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */ - {0x02, 0x05}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */ - {0x01, 0x21}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ - {0x00, 0x04}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */ - {0x02, 0x10}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */ - {0x00, 0x21}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */ - {0x00, 0x22}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */ - {0x03, 0x21}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ - {0x06, 0x08}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */ - {0x02, 0x08}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */ - {0x00, 0x00}, /* 0x1A, */ - {0x00, 0x00}, /* 0x1B, */ - {0x00, 0x00}, /* 0x1C, */ - {0x00, 0x00}, /* 0x1D, */ - {0x00, 0x00}, /* 0x1E, */ - {0x06, 0x04}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */ + {0x02}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */ + {0x02}, /* 0x01, RT_CHANNEL_DOMAIN_IC */ + {0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */ + {0x01}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */ + {0x01}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */ + {0x03}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */ + {0x03}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */ + {0x01}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */ + {0x03}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */ + {0x03}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */ + {0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */ + {0x02}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */ + {0x01}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */ + {0x02}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */ + {0x02}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */ + {0x02}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */ + {0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */ + {0x02}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */ + {0x01}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ + {0x00}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */ + {0x02}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */ + {0x00}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */ + {0x00}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */ + {0x03}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ + {0x06}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */ + {0x02}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */ + {0x00}, /* 0x1A, */ + {0x00}, /* 0x1B, */ + {0x00}, /* 0x1C, */ + {0x00}, /* 0x1D, */ + {0x00}, /* 0x1E, */ + {0x06}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */ /* 0x20 ~ 0x7F , New Define ===== */ - {0x00, 0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */ - {0x01, 0x00}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */ - {0x02, 0x00}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */ - {0x03, 0x00}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */ - {0x04, 0x00}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */ - {0x02, 0x04}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */ - {0x00, 0x01}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */ - {0x03, 0x0C}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */ - {0x00, 0x0B}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */ - {0x00, 0x05}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */ - {0x00, 0x00}, /* 0x2A, */ - {0x00, 0x00}, /* 0x2B, */ - {0x00, 0x00}, /* 0x2C, */ - {0x00, 0x00}, /* 0x2D, */ - {0x00, 0x00}, /* 0x2E, */ - {0x00, 0x00}, /* 0x2F, */ - {0x00, 0x06}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */ - {0x00, 0x07}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */ - {0x00, 0x08}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */ - {0x00, 0x09}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */ - {0x02, 0x0A}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */ - {0x00, 0x02}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */ - {0x00, 0x03}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */ - {0x03, 0x0D}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */ - {0x03, 0x0E}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */ - {0x02, 0x0F}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */ - {0x00, 0x00}, /* 0x3A, */ - {0x00, 0x00}, /* 0x3B, */ - {0x00, 0x00}, /* 0x3C, */ - {0x00, 0x00}, /* 0x3D, */ - {0x00, 0x00}, /* 0x3E, */ - {0x00, 0x00}, /* 0x3F, */ - {0x02, 0x10}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */ - {0x05, 0x00}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_NULL */ - {0x01, 0x12}, /* 0x42, RT_CHANNEL_DOMAIN_ETSI1_ETSI4 */ - {0x02, 0x05}, /* 0x43, RT_CHANNEL_DOMAIN_FCC1_FCC2 */ - {0x02, 0x11}, /* 0x44, RT_CHANNEL_DOMAIN_FCC1_NCC3 */ - {0x00, 0x13}, /* 0x45, RT_CHANNEL_DOMAIN_WORLD_ETSI5 */ - {0x02, 0x14}, /* 0x46, RT_CHANNEL_DOMAIN_FCC1_FCC8 */ - {0x00, 0x15}, /* 0x47, RT_CHANNEL_DOMAIN_WORLD_ETSI6 */ - {0x00, 0x16}, /* 0x48, RT_CHANNEL_DOMAIN_WORLD_ETSI7 */ - {0x00, 0x17}, /* 0x49, RT_CHANNEL_DOMAIN_WORLD_ETSI8 */ - {0x00, 0x18}, /* 0x50, RT_CHANNEL_DOMAIN_WORLD_ETSI9 */ - {0x00, 0x19}, /* 0x51, RT_CHANNEL_DOMAIN_WORLD_ETSI10 */ - {0x00, 0x1A}, /* 0x52, RT_CHANNEL_DOMAIN_WORLD_ETSI11 */ - {0x02, 0x1B}, /* 0x53, RT_CHANNEL_DOMAIN_FCC1_NCC4 */ - {0x00, 0x1C}, /* 0x54, RT_CHANNEL_DOMAIN_WORLD_ETSI12 */ - {0x02, 0x1D}, /* 0x55, RT_CHANNEL_DOMAIN_FCC1_FCC9 */ - {0x00, 0x1E}, /* 0x56, RT_CHANNEL_DOMAIN_WORLD_ETSI13 */ - {0x02, 0x1F}, /* 0x57, RT_CHANNEL_DOMAIN_FCC1_FCC10 */ + {0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */ + {0x01}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */ + {0x02}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */ + {0x03}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */ + {0x04}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */ + {0x02}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */ + {0x00}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */ + {0x03}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */ + {0x00}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */ + {0x00}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */ + {0x00}, /* 0x2A, */ + {0x00}, /* 0x2B, */ + {0x00}, /* 0x2C, */ + {0x00}, /* 0x2D, */ + {0x00}, /* 0x2E, */ + {0x00}, /* 0x2F, */ + {0x00}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */ + {0x00}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */ + {0x00}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */ + {0x00}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */ + {0x02}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */ + {0x00}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */ + {0x00}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */ + {0x03}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */ + {0x03}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */ + {0x02}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */ + {0x00}, /* 0x3A, */ + {0x00}, /* 0x3B, */ + {0x00}, /* 0x3C, */ + {0x00}, /* 0x3D, */ + {0x00}, /* 0x3E, */ + {0x00}, /* 0x3F, */ + {0x02}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */ + {0x05}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_NULL */ + {0x01}, /* 0x42, RT_CHANNEL_DOMAIN_ETSI1_ETSI4 */ + {0x02}, /* 0x43, RT_CHANNEL_DOMAIN_FCC1_FCC2 */ + {0x02}, /* 0x44, RT_CHANNEL_DOMAIN_FCC1_NCC3 */ + {0x00}, /* 0x45, RT_CHANNEL_DOMAIN_WORLD_ETSI5 */ + {0x02}, /* 0x46, RT_CHANNEL_DOMAIN_FCC1_FCC8 */ + {0x00}, /* 0x47, RT_CHANNEL_DOMAIN_WORLD_ETSI6 */ + {0x00}, /* 0x48, RT_CHANNEL_DOMAIN_WORLD_ETSI7 */ + {0x00}, /* 0x49, RT_CHANNEL_DOMAIN_WORLD_ETSI8 */ + {0x00}, /* 0x50, RT_CHANNEL_DOMAIN_WORLD_ETSI9 */ + {0x00}, /* 0x51, RT_CHANNEL_DOMAIN_WORLD_ETSI10 */ + {0x00}, /* 0x52, RT_CHANNEL_DOMAIN_WORLD_ETSI11 */ + {0x02}, /* 0x53, RT_CHANNEL_DOMAIN_FCC1_NCC4 */ + {0x00}, /* 0x54, RT_CHANNEL_DOMAIN_WORLD_ETSI12 */ + {0x02}, /* 0x55, RT_CHANNEL_DOMAIN_FCC1_FCC9 */ + {0x00}, /* 0x56, RT_CHANNEL_DOMAIN_WORLD_ETSI13 */ + {0x02}, /* 0x57, RT_CHANNEL_DOMAIN_FCC1_FCC10 */ }; /* use the combination for max channel numbers */ -static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03, 0x02}; +static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03}; /* Search the @param ch in given @param ch_set * @ch_set: the given channel set @@ -231,23 +188,6 @@ int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch) return i; } -/* Check the @param ch is fit with setband setting of @param adapter - * @adapter: the given adapter - * @ch: the given channel number - * - * return true when check valid, false not valid - */ -bool rtw_mlme_band_check(struct adapter *adapter, const u32 ch) -{ - if (adapter->setband == GHZ24_50 /* 2.4G and 5G */ - || (adapter->setband == GHZ_24 && ch < 35) /* 2.4G only */ - || (adapter->setband == GHZ_50 && ch > 35) /* 5G only */ - ) { - return true; - } - return false; -} - /**************************************************************************** Following are the initialization functions for WiFi MLME @@ -395,8 +335,8 @@ static void init_channel_list(struct adapter *padapter, struct rt_channel_info * static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, struct rt_channel_info *channel_set) { u8 index, chanset_size = 0; - u8 b5GBand = false, b2_4GBand = false; - u8 Index2G = 0, Index5G = 0; + u8 b2_4GBand = false; + u8 Index2G = 0; memset(channel_set, 0, sizeof(struct rt_channel_info)*MAX_CHANNEL_NUM); @@ -422,7 +362,6 @@ static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, struct rt_c else if ((channel_set[chanset_size].ChannelNum >= 12 && channel_set[chanset_size].ChannelNum <= 14)) channel_set[chanset_size].ScanType = SCAN_PASSIVE; } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == ChannelPlan || - RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan || RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) { /* channel 12~13, passive scan */ if (channel_set[chanset_size].ChannelNum <= 11) channel_set[chanset_size].ScanType = SCAN_ACTIVE; @@ -435,20 +374,6 @@ static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, struct rt_c } } - if (b5GBand) { - for (index = 0; index < RTW_ChannelPlan5G[Index5G].Len; index++) { - if (RTW_ChannelPlan5G[Index5G].Channel[index] <= 48 - || RTW_ChannelPlan5G[Index5G].Channel[index] >= 149) { - channel_set[chanset_size].ChannelNum = RTW_ChannelPlan5G[Index5G].Channel[index]; - if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan)/* passive scan for all 5G channels */ - channel_set[chanset_size].ScanType = SCAN_PASSIVE; - else - channel_set[chanset_size].ScanType = SCAN_ACTIVE; - chanset_size++; - } - } - } - return chanset_size; } @@ -1021,7 +946,7 @@ unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame) u16 capab_info; struct rtw_ieee802_11_elems elems; struct sta_info *pstat; - unsigned char reassoc, *p, *pos, *wpa_ie; + unsigned char *p, *pos, *wpa_ie; unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; int i, ie_len, wpa_ie_len, left; unsigned char supportRate[16]; @@ -1041,13 +966,10 @@ unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame) return _FAIL; frame_type = GetFrameSubType(pframe); - if (frame_type == WIFI_ASSOCREQ) { - reassoc = 0; + if (frame_type == WIFI_ASSOCREQ) ie_offset = _ASOCREQ_IE_OFFSET_; - } else { /* WIFI_REASSOCREQ */ - reassoc = 1; + else /* WIFI_REASSOCREQ */ ie_offset = _REASOCREQ_IE_OFFSET_; - } if (pkt_len < sizeof(struct ieee80211_hdr_3addr) + ie_offset) @@ -1726,7 +1648,7 @@ unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_fra struct recv_reorder_ctrl *preorder_ctrl; unsigned char *frame_body; unsigned char category, action; - unsigned short tid, status, reason_code = 0; + unsigned short tid, status; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); u8 *pframe = precv_frame->u.hdr.rx_data; @@ -1795,9 +1717,6 @@ unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_fra ~BIT((frame_body[3] >> 4) & 0xf); psta->htpriv.candidate_tid_bitmap &= ~BIT((frame_body[3] >> 4) & 0xf); - - /* reason_code = frame_body[4] | (frame_body[5] << 8); */ - reason_code = get_unaligned_le16(&frame_body[4]); } else if ((frame_body[3] & BIT(3)) == BIT(3)) { tid = (frame_body[3] >> 4) & 0x0F; @@ -2142,7 +2061,7 @@ s32 dump_mgntframe_and_wait(struct adapter *padapter, struct xmit_frame *pmgntfr ret = rtw_hal_mgnt_xmit(padapter, pmgntframe); if (ret == _SUCCESS) - ret = rtw_sctx_wait(&sctx, __func__); + ret = rtw_sctx_wait(&sctx); spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL); pxmitbuf->sctx = NULL; @@ -2226,7 +2145,6 @@ void issue_beacon(struct adapter *padapter, int timeout_ms) struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); - u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; pmgntframe = alloc_mgtxmitframe(pxmitpriv); if (!pmgntframe) @@ -2248,7 +2166,7 @@ void issue_beacon(struct adapter *padapter, int timeout_ms) fctrl = &(pwlanhdr->frame_control); *(fctrl) = 0; - memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); + eth_broadcast_addr(pwlanhdr->addr1); memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN); @@ -2457,9 +2375,13 @@ void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p u8 *ssid_ie; signed int ssid_ielen; signed int ssid_ielen_diff; - u8 buf[MAX_IE_SZ]; + u8 *buf; u8 *ies = pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr); + buf = rtw_zmalloc(MAX_IE_SZ); + if (!buf) + return; + ssid_ie = rtw_get_ie(ies+_FIXED_IE_LENGTH_, WLAN_EID_SSID, &ssid_ielen, (pframe-ies)-_FIXED_IE_LENGTH_); @@ -2487,6 +2409,7 @@ void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p pframe += ssid_ielen_diff; pattrib->pktlen += ssid_ielen_diff; } + kfree (buf); } } else { /* timestamp will be inserted by hardware */ @@ -2567,7 +2490,6 @@ static int _issue_probereq(struct adapter *padapter, struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); int bssrate_len = 0; - u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; pmgntframe = alloc_mgtxmitframe(pxmitpriv); if (!pmgntframe) @@ -2594,8 +2516,8 @@ static int _issue_probereq(struct adapter *padapter, memcpy(pwlanhdr->addr3, da, ETH_ALEN); } else { /* broadcast probe request frame */ - memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); - memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN); + eth_broadcast_addr(pwlanhdr->addr1); + eth_broadcast_addr(pwlanhdr->addr3); } memcpy(pwlanhdr->addr2, mac, ETH_ALEN); @@ -4483,61 +4405,6 @@ static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid } } - if (pregistrypriv->wireless_mode & WIRELESS_11A) { - do { - if ((i == MAX_CHANNEL_NUM) || - (chplan_sta[i].ChannelNum == 0)) - break; - - if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] == 0)) - break; - - if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - i++; - j++; - k++; - } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; -/* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ - chplan_new[k].ScanType = SCAN_PASSIVE; - i++; - k++; - } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - j++; - k++; - } - } while (1); - - /* change AP not support channel to Passive scan */ - while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) { - chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; -/* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ - chplan_new[k].ScanType = SCAN_PASSIVE; - i++; - k++; - } - - /* add channel AP supported */ - while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] != 0)) { - chplan_new[k].ChannelNum = chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - j++; - k++; - } - } else { - /* keep original STA 5G channel plan */ - while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) { - chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = chplan_sta[i].ScanType; - i++; - k++; - } - } - pmlmeext->update_channel_plan_by_ap_done = 1; } @@ -4548,10 +4415,6 @@ static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) { if (chplan_new[i].ChannelNum == channel) { if (chplan_new[i].ScanType == SCAN_PASSIVE) { - /* 5G Bnad 2, 3 (DFS) doesn't change to active scan */ - if (channel >= 52 && channel <= 144) - break; - chplan_new[i].ScanType = SCAN_ACTIVE; } break; @@ -5125,24 +4988,9 @@ void _linked_info_dump(struct adapter *padapter) if (padapter->bLinkInfoDump) { - if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) { + if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB); - } else if ((pmlmeinfo->state&0x03) == _HW_STATE_AP_) { - struct list_head *phead, *plist; - - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - plist = get_next(phead); - while (phead != plist) { - psta = container_of(plist, struct sta_info, asoc_list); - plist = get_next(plist); - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - } for (i = 0; i < NUM_STA; i++) { if (pdvobj->macid[i]) { if (i != 1) /* skip bc/mc sta */ @@ -5151,11 +4999,7 @@ void _linked_info_dump(struct adapter *padapter) } } rtw_hal_set_def_var(padapter, HAL_DEF_DBG_RX_INFO_DUMP, NULL); - - } - - } static u8 chk_ap_is_alive(struct adapter *padapter, struct sta_info *psta) @@ -5452,9 +5296,7 @@ u8 createbss_hdl(struct adapter *padapter, u8 *pbuf) /* u32 initialgain; */ if (pmlmeinfo->state == WIFI_FW_AP_STATE) { - struct wlan_bssid_ex *network = &padapter->mlmepriv.cur_network.network; - - start_bss_network(padapter, (u8 *)network); + start_bss_network(padapter); return H2C_SUCCESS; } @@ -5692,7 +5534,6 @@ static int rtw_scan_ch_decision(struct adapter *padapter, struct rtw_ieee80211_c set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value); if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED) && set_idx >= 0 - && rtw_mlme_band_check(padapter, in[i].hw_value) ) { if (j >= out_num) { netdev_dbg(padapter->pnetdev, @@ -5716,23 +5557,20 @@ static int rtw_scan_ch_decision(struct adapter *padapter, struct rtw_ieee80211_c if (j == 0) { for (i = 0; i < pmlmeext->max_chan_nums; i++) { - if (rtw_mlme_band_check(padapter, pmlmeext->channel_set[i].ChannelNum)) { - - if (j >= out_num) { - netdev_dbg(padapter->pnetdev, - FUNC_ADPT_FMT " out_num:%u not enough\n", - FUNC_ADPT_ARG(padapter), - out_num); - break; - } + if (j >= out_num) { + netdev_dbg(padapter->pnetdev, + FUNC_ADPT_FMT " out_num:%u not enough\n", + FUNC_ADPT_ARG(padapter), + out_num); + break; + } - out[j].hw_value = pmlmeext->channel_set[i].ChannelNum; + out[j].hw_value = pmlmeext->channel_set[i].ChannelNum; - if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE) - out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN; + if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE) + out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN; - j++; - } + j++; } } @@ -5997,10 +5835,40 @@ exit: return res; } +static struct fwevent wlanevents[] = { + {0, rtw_dummy_event_callback}, /*0*/ + {0, NULL}, + {0, NULL}, + {0, NULL}, + {0, NULL}, + {0, NULL}, + {0, NULL}, + {0, NULL}, + {0, &rtw_survey_event_callback}, /*8*/ + {sizeof(struct surveydone_event), &rtw_surveydone_event_callback}, /*9*/ + + {0, &rtw_joinbss_event_callback}, /*10*/ + {sizeof(struct stassoc_event), &rtw_stassoc_event_callback}, + {sizeof(struct stadel_event), &rtw_stadel_event_callback}, + {0, &rtw_atimdone_event_callback}, + {0, rtw_dummy_event_callback}, + {0, NULL}, /*15*/ + {0, NULL}, + {0, NULL}, + {0, NULL}, + {0, rtw_fwdbg_event_callback}, + {0, NULL}, /*20*/ + {0, NULL}, + {0, NULL}, + {0, &rtw_cpwm_event_callback}, + {0, NULL}, + {0, &rtw_wmm_event_callback}, + +}; u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf) { - u8 evt_code, evt_seq; + u8 evt_code; u16 evt_sz; uint *peventbuf; void (*event_callback)(struct adapter *dev, u8 *pbuf); @@ -6011,19 +5879,8 @@ u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf) peventbuf = (uint *)pbuf; evt_sz = (u16)(*peventbuf&0xffff); - evt_seq = (u8)((*peventbuf>>24)&0x7f); evt_code = (u8)((*peventbuf>>16)&0xff); - - #ifdef CHECK_EVENT_SEQ - /* checking event sequence... */ - if (evt_seq != (atomic_read(&pevt_priv->event_seq) & 0x7f)) { - pevt_priv->event_seq = (evt_seq+1)&0x7f; - - goto _abort_event_; - } - #endif - /* checking if event code is valid */ if (evt_code >= MAX_C2HEVT) goto _abort_event_; @@ -6063,7 +5920,7 @@ u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf) u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf) { struct sta_info *psta_bmc; - struct list_head *xmitframe_plist, *xmitframe_phead; + struct list_head *xmitframe_plist, *xmitframe_phead, *tmp; struct xmit_frame *pxmitframe = NULL; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; struct sta_priv *pstapriv = &padapter->stapriv; @@ -6080,12 +5937,9 @@ u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf) spin_lock_bh(&pxmitpriv->lock); xmitframe_phead = get_list_head(&psta_bmc->sleep_q); - xmitframe_plist = get_next(xmitframe_phead); - - while (xmitframe_phead != xmitframe_plist) { - pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list); - - xmitframe_plist = get_next(xmitframe_plist); + list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) { + pxmitframe = list_entry(xmitframe_plist, + struct xmit_frame, list); list_del_init(&pxmitframe->list); diff --git a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c index 251b9abdf591..a392d5b4caf2 100644 --- a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c +++ b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c @@ -4,8 +4,6 @@ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. * ******************************************************************************/ -#define _RTW_PWRCTRL_C_ - #include <drv_types.h> #include <rtw_debug.h> #include <hal_data.h> diff --git a/drivers/staging/rtl8723bs/core/rtw_recv.c b/drivers/staging/rtl8723bs/core/rtw_recv.c index 668a703dee7f..d4c1725718d9 100644 --- a/drivers/staging/rtl8723bs/core/rtw_recv.c +++ b/drivers/staging/rtl8723bs/core/rtw_recv.c @@ -4,8 +4,6 @@ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. * ******************************************************************************/ -#define _RTW_RECV_C_ - #include <drv_types.h> #include <rtw_debug.h> #include <linux/jiffies.h> @@ -1646,16 +1644,10 @@ static int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_n /* Rx Reorder initialize condition. */ if (preorder_ctrl->indicate_seq == 0xFFFF) { preorder_ctrl->indicate_seq = seq_num; - - /* DbgPrint("check_indicate_seq, 1st->indicate_seq =%d\n", precvpriv->indicate_seq); */ } - /* DbgPrint("enter->check_indicate_seq(): IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num); */ - /* Drop out the packet which SeqNum is smaller than WinStart */ if (SN_LESS(seq_num, preorder_ctrl->indicate_seq)) { - /* DbgPrint("CheckRxTsIndicateSeq(): Packet Drop! IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num); */ - return false; } @@ -1668,8 +1660,6 @@ static int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_n preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) & 0xFFF; } else if (SN_LESS(wend, seq_num)) { - /* DbgPrint("CheckRxTsIndicateSeq(): Window Shift! IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num); */ - /* boundary situation, when seq_num cross 0xFFF */ if (seq_num >= (wsize - 1)) preorder_ctrl->indicate_seq = seq_num + 1 - wsize; @@ -1678,8 +1668,6 @@ static int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_n pdbgpriv->dbg_rx_ampdu_window_shift_cnt++; } - /* DbgPrint("exit->check_indicate_seq(): IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num); */ - return true; } @@ -1691,8 +1679,6 @@ static int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, un union recv_frame *pnextrframe; struct rx_pkt_attrib *pnextattrib; - /* DbgPrint("+enqueue_reorder_recvframe()\n"); */ - /* spin_lock_irqsave(&ppending_recvframe_queue->lock, irql); */ /* spin_lock(&ppending_recvframe_queue->lock); */ @@ -1713,8 +1699,6 @@ static int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, un else break; - /* DbgPrint("enqueue_reorder_recvframe():while\n"); */ - } @@ -1753,8 +1737,6 @@ static int recv_indicatepkts_in_order(struct adapter *padapter, struct recv_reor struct dvobj_priv *psdpriv = padapter->dvobj; struct debug_priv *pdbgpriv = &psdpriv->drv_dbg; - /* DbgPrint("+recv_indicatepkts_in_order\n"); */ - /* spin_lock_irqsave(&ppending_recvframe_queue->lock, irql); */ /* spin_lock(&ppending_recvframe_queue->lock); */ @@ -1796,11 +1778,8 @@ static int recv_indicatepkts_in_order(struct adapter *padapter, struct recv_reor /* pTS->RxIndicateState = RXTS_INDICATE_PROCESSING; */ /* Indicate packets */ - /* RT_ASSERT((index<=REORDER_WIN_SIZE), ("RxReorderIndicatePacket(): Rx Reorder buffer full!!\n")); */ - /* indicate this recv_frame */ - /* DbgPrint("recv_indicatepkts_in_order, indicate_seq =%d, seq_num =%d\n", precvpriv->indicate_seq, pattrib->seq_num); */ if (!pattrib->amsdu) { if ((padapter->bDriverStopped == false) && (padapter->bSurpriseRemoved == false)) @@ -1823,8 +1802,6 @@ static int recv_indicatepkts_in_order(struct adapter *padapter, struct recv_reor break; } - /* DbgPrint("recv_indicatepkts_in_order():while\n"); */ - } /* spin_unlock(&ppending_recvframe_queue->lock); */ @@ -1894,7 +1871,6 @@ static int recv_indicatepkt_reorder(struct adapter *padapter, union recv_frame * /* s3. Insert all packet into Reorder Queue to maintain its ordering. */ if (!enqueue_reorder_recvframe(preorder_ctrl, prframe)) { - /* DbgPrint("recv_indicatepkt_reorder, enqueue_reorder_recvframe fail!\n"); */ /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); */ /* return _FAIL; */ goto _err_exit; @@ -2123,7 +2099,7 @@ static void rtw_signal_stat_timer_hdl(struct timer_list *t) u8 avg_signal_strength = 0; u8 avg_signal_qual = 0; u32 num_signal_strength = 0; - u32 num_signal_qual = 0; + u32 __maybe_unused num_signal_qual = 0; u8 _alpha = 5; /* this value is based on converging_constant = 5000 and sampling_interval = 1000 */ if (adapter->recvpriv.is_signal_dbg) { diff --git a/drivers/staging/rtl8723bs/core/rtw_security.c b/drivers/staging/rtl8723bs/core/rtw_security.c index 7823055ed32d..a99f439328f1 100644 --- a/drivers/staging/rtl8723bs/core/rtw_security.c +++ b/drivers/staging/rtl8723bs/core/rtw_security.c @@ -4,11 +4,10 @@ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. * ******************************************************************************/ -#define _RTW_SECURITY_C_ - -#include <linux/crc32poly.h> +#include <linux/crc32.h> #include <drv_types.h> #include <rtw_debug.h> +#include <crypto/aes.h> static const char * const _security_type_str[] = { "N/A", @@ -31,118 +30,6 @@ const char *security_type_str(u8 value) /* WEP related ===== */ -struct arc4context { - u32 x; - u32 y; - u8 state[256]; -}; - - -static void arcfour_init(struct arc4context *parc4ctx, u8 *key, u32 key_len) -{ - u32 t, u; - u32 keyindex; - u32 stateindex; - u8 *state; - u32 counter; - - state = parc4ctx->state; - parc4ctx->x = 0; - parc4ctx->y = 0; - for (counter = 0; counter < 256; counter++) - state[counter] = (u8)counter; - keyindex = 0; - stateindex = 0; - for (counter = 0; counter < 256; counter++) { - t = state[counter]; - stateindex = (stateindex + key[keyindex] + t) & 0xff; - u = state[stateindex]; - state[stateindex] = (u8)t; - state[counter] = (u8)u; - if (++keyindex >= key_len) - keyindex = 0; - } -} - -static u32 arcfour_byte(struct arc4context *parc4ctx) -{ - u32 x; - u32 y; - u32 sx, sy; - u8 *state; - - state = parc4ctx->state; - x = (parc4ctx->x + 1) & 0xff; - sx = state[x]; - y = (sx + parc4ctx->y) & 0xff; - sy = state[y]; - parc4ctx->x = x; - parc4ctx->y = y; - state[y] = (u8)sx; - state[x] = (u8)sy; - return state[(sx + sy) & 0xff]; -} - -static void arcfour_encrypt(struct arc4context *parc4ctx, u8 *dest, u8 *src, u32 len) -{ - u32 i; - - for (i = 0; i < len; i++) - dest[i] = src[i] ^ (unsigned char)arcfour_byte(parc4ctx); -} - -static signed int bcrc32initialized; -static u32 crc32_table[256]; - - -static u8 crc32_reverseBit(u8 data) -{ - return((u8)((data<<7)&0x80) | ((data<<5)&0x40) | ((data<<3)&0x20) | ((data<<1)&0x10) | ((data>>1)&0x08) | ((data>>3)&0x04) | ((data>>5)&0x02) | ((data>>7)&0x01)); -} - -static void crc32_init(void) -{ - if (bcrc32initialized == 1) - return; - else { - signed int i, j; - u32 c; - u8 *p = (u8 *)&c, *p1; - u8 k; - - c = 0x12340000; - - for (i = 0; i < 256; ++i) { - k = crc32_reverseBit((u8)i); - for (c = ((u32)k) << 24, j = 8; j > 0; --j) - c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY_BE : (c << 1); - p1 = (u8 *)&crc32_table[i]; - - p1[0] = crc32_reverseBit(p[3]); - p1[1] = crc32_reverseBit(p[2]); - p1[2] = crc32_reverseBit(p[1]); - p1[3] = crc32_reverseBit(p[0]); - } - bcrc32initialized = 1; - } -} - -static __le32 getcrc32(u8 *buf, signed int len) -{ - u8 *p; - u32 crc; - - if (bcrc32initialized == 0) - crc32_init(); - - crc = 0xffffffff; /* preload shift register, per CRC-32 spec */ - - for (p = buf; len > 0; ++p, --len) - crc = crc32_table[(crc ^ *p) & 0xff] ^ (crc >> 8); - return cpu_to_le32(~crc); /* transmit complement, per CRC-32 spec */ -} - - /* Need to consider the fragment situation */ @@ -150,7 +37,6 @@ void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe) { /* exclude ICV */ unsigned char crc[4]; - struct arc4context mycontext; signed int curfragnum, length; u32 keylength; @@ -161,6 +47,7 @@ void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe) struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib; struct security_priv *psecuritypriv = &padapter->securitypriv; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct arc4_ctx *ctx = &psecuritypriv->xmit_arc4_ctx; if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL) return; @@ -182,18 +69,18 @@ void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe) length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; - *((__le32 *)crc) = getcrc32(payload, length); + *((__le32 *)crc) = ~crc32_le(~0, payload, length); - arcfour_init(&mycontext, wepkey, 3+keylength); - arcfour_encrypt(&mycontext, payload, payload, length); - arcfour_encrypt(&mycontext, payload+length, crc, 4); + arc4_setkey(ctx, wepkey, 3 + keylength); + arc4_crypt(ctx, payload, payload, length); + arc4_crypt(ctx, payload + length, crc, 4); } else { length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; - *((__le32 *)crc) = getcrc32(payload, length); - arcfour_init(&mycontext, wepkey, 3+keylength); - arcfour_encrypt(&mycontext, payload, payload, length); - arcfour_encrypt(&mycontext, payload+length, crc, 4); + *((__le32 *)crc) = ~crc32_le(~0, payload, length); + arc4_setkey(ctx, wepkey, 3 + keylength); + arc4_crypt(ctx, payload, payload, length); + arc4_crypt(ctx, payload + length, crc, 4); pframe += pxmitpriv->frag_len; pframe = (u8 *)round_up((SIZE_PTR)(pframe), 4); @@ -206,13 +93,13 @@ void rtw_wep_decrypt(struct adapter *padapter, u8 *precvframe) { /* exclude ICV */ u8 crc[4]; - struct arc4context mycontext; signed int length; u32 keylength; u8 *pframe, *payload, *iv, wepkey[16]; u8 keyindex; struct rx_pkt_attrib *prxattrib = &(((union recv_frame *)precvframe)->u.hdr.attrib); struct security_priv *psecuritypriv = &padapter->securitypriv; + struct arc4_ctx *ctx = &psecuritypriv->recv_arc4_ctx; pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data; @@ -230,11 +117,11 @@ void rtw_wep_decrypt(struct adapter *padapter, u8 *precvframe) payload = pframe+prxattrib->iv_len+prxattrib->hdrlen; /* decrypt payload include icv */ - arcfour_init(&mycontext, wepkey, 3+keylength); - arcfour_encrypt(&mycontext, payload, payload, length); + arc4_setkey(ctx, wepkey, 3 + keylength); + arc4_crypt(ctx, payload, payload, length); /* calculate icv and compare the icv */ - *((u32 *)crc) = le32_to_cpu(getcrc32(payload, length-4)); + *((u32 *)crc) = le32_to_cpu(~crc32_le(~0, payload, length - 4)); } } @@ -579,7 +466,6 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe) u8 ttkey[16]; u8 crc[4]; u8 hw_hdr_offset = 0; - struct arc4context mycontext; signed int curfragnum, length; u8 *pframe, *payload, *iv, *prwskey; @@ -587,6 +473,7 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe) struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib; struct security_priv *psecuritypriv = &padapter->securitypriv; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct arc4_ctx *ctx = &psecuritypriv->xmit_arc4_ctx; u32 res = _SUCCESS; if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL) @@ -619,18 +506,19 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe) if ((curfragnum+1) == pattrib->nr_frags) { /* 4 the last fragment */ length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; - *((__le32 *)crc) = getcrc32(payload, length);/* modified by Amy*/ + *((__le32 *)crc) = ~crc32_le(~0, payload, length); - arcfour_init(&mycontext, rc4key, 16); - arcfour_encrypt(&mycontext, payload, payload, length); - arcfour_encrypt(&mycontext, payload+length, crc, 4); + arc4_setkey(ctx, rc4key, 16); + arc4_crypt(ctx, payload, payload, length); + arc4_crypt(ctx, payload + length, crc, 4); } else { length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; - *((__le32 *)crc) = getcrc32(payload, length);/* modified by Amy*/ - arcfour_init(&mycontext, rc4key, 16); - arcfour_encrypt(&mycontext, payload, payload, length); - arcfour_encrypt(&mycontext, payload+length, crc, 4); + *((__le32 *)crc) = ~crc32_le(~0, payload, length); + + arc4_setkey(ctx, rc4key, 16); + arc4_crypt(ctx, payload, payload, length); + arc4_crypt(ctx, payload + length, crc, 4); pframe += pxmitpriv->frag_len; pframe = (u8 *)round_up((SIZE_PTR)(pframe), 4); @@ -650,7 +538,6 @@ u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe) u8 rc4key[16]; u8 ttkey[16]; u8 crc[4]; - struct arc4context mycontext; signed int length; u8 *pframe, *payload, *iv, *prwskey; @@ -658,6 +545,7 @@ u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe) struct sta_info *stainfo; struct rx_pkt_attrib *prxattrib = &((union recv_frame *)precvframe)->u.hdr.attrib; struct security_priv *psecuritypriv = &padapter->securitypriv; + struct arc4_ctx *ctx = &psecuritypriv->recv_arc4_ctx; u32 res = _SUCCESS; pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data; @@ -727,10 +615,10 @@ u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe) /* 4 decrypt payload include icv */ - arcfour_init(&mycontext, rc4key, 16); - arcfour_encrypt(&mycontext, payload, payload, length); + arc4_setkey(ctx, rc4key, 16); + arc4_crypt(ctx, payload, payload, length); - *((u32 *)crc) = le32_to_cpu(getcrc32(payload, length-4)); + *((u32 *)crc) = le32_to_cpu(~crc32_le(~0, payload, length - 4)); if (crc[3] != payload[length - 1] || crc[2] != payload[length - 2] || crc[1] != payload[length - 3] || crc[0] != payload[length - 4]) @@ -749,44 +637,6 @@ exit: #define MAX_MSG_SIZE 2048 -/*****************************/ -/******** SBOX Table *********/ -/*****************************/ - - static const u8 sbox_table[256] = { - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, - 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, - 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, - 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, - 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, - 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, - 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, - 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, - 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, - 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, - 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, - 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, - 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, - 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, - 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, - 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, - 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 - }; /*****************************/ /**** Function Prototypes ****/ @@ -815,13 +665,7 @@ static void construct_ctr_preload(u8 *ctr_preload, u8 *pn_vector, signed int c, uint frtype); /* for CONFIG_IEEE80211W, none 11w also can use */ -static void xor_128(u8 *a, u8 *b, u8 *out); -static void xor_32(u8 *a, u8 *b, u8 *out); -static u8 sbox(u8 a); -static void next_key(u8 *key, signed int round); -static void byte_sub(u8 *in, u8 *out); -static void shift_row(u8 *in, u8 *out); -static void mix_column(u8 *in, u8 *out); + static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext); @@ -830,171 +674,13 @@ static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext); /* Performs a 128 bit AES encrypt with */ /* 128 bit data. */ /****************************************/ -static void xor_128(u8 *a, u8 *b, u8 *out) -{ - signed int i; - - for (i = 0; i < 16; i++) - out[i] = a[i] ^ b[i]; -} - - -static void xor_32(u8 *a, u8 *b, u8 *out) -{ - signed int i; - - for (i = 0; i < 4; i++) - out[i] = a[i] ^ b[i]; -} - - -static u8 sbox(u8 a) -{ - return sbox_table[(signed int)a]; -} - - -static void next_key(u8 *key, signed int round) -{ - u8 rcon; - u8 sbox_key[4]; - static const u8 rcon_table[12] = { - 0x01, 0x02, 0x04, 0x08, - 0x10, 0x20, 0x40, 0x80, - 0x1b, 0x36, 0x36, 0x36 - }; - sbox_key[0] = sbox(key[13]); - sbox_key[1] = sbox(key[14]); - sbox_key[2] = sbox(key[15]); - sbox_key[3] = sbox(key[12]); - - rcon = rcon_table[round]; - - xor_32(&key[0], sbox_key, &key[0]); - key[0] = key[0] ^ rcon; - - xor_32(&key[4], &key[0], &key[4]); - xor_32(&key[8], &key[4], &key[8]); - xor_32(&key[12], &key[8], &key[12]); -} - - -static void byte_sub(u8 *in, u8 *out) -{ - signed int i; - - for (i = 0; i < 16; i++) - out[i] = sbox(in[i]); -} - - -static void shift_row(u8 *in, u8 *out) -{ - out[0] = in[0]; - out[1] = in[5]; - out[2] = in[10]; - out[3] = in[15]; - out[4] = in[4]; - out[5] = in[9]; - out[6] = in[14]; - out[7] = in[3]; - out[8] = in[8]; - out[9] = in[13]; - out[10] = in[2]; - out[11] = in[7]; - out[12] = in[12]; - out[13] = in[1]; - out[14] = in[6]; - out[15] = in[11]; -} - -static void mix_column(u8 *in, u8 *out) -{ - signed int i; - u8 add1b[4]; - u8 add1bf7[4]; - u8 rotl[4]; - u8 swap_halfs[4]; - u8 andf7[4]; - u8 rotr[4]; - u8 temp[4]; - u8 tempb[4]; - - for (i = 0; i < 4; i++) { - if ((in[i] & 0x80) == 0x80) - add1b[i] = 0x1b; - else - add1b[i] = 0x00; - } - - swap_halfs[0] = in[2]; /* Swap halfs */ - swap_halfs[1] = in[3]; - swap_halfs[2] = in[0]; - swap_halfs[3] = in[1]; - - rotl[0] = in[3]; /* Rotate left 8 bits */ - rotl[1] = in[0]; - rotl[2] = in[1]; - rotl[3] = in[2]; - - andf7[0] = in[0] & 0x7f; - andf7[1] = in[1] & 0x7f; - andf7[2] = in[2] & 0x7f; - andf7[3] = in[3] & 0x7f; - - for (i = 3; i > 0; i--) { /* logical shift left 1 bit */ - andf7[i] = andf7[i] << 1; - if ((andf7[i-1] & 0x80) == 0x80) - andf7[i] = (andf7[i] | 0x01); - } - andf7[0] = andf7[0] << 1; - andf7[0] = andf7[0] & 0xfe; - - xor_32(add1b, andf7, add1bf7); - - xor_32(in, add1bf7, rotr); - - temp[0] = rotr[0]; /* Rotate right 8 bits */ - rotr[0] = rotr[1]; - rotr[1] = rotr[2]; - rotr[2] = rotr[3]; - rotr[3] = temp[0]; - - xor_32(add1bf7, rotr, temp); - xor_32(swap_halfs, rotl, tempb); - xor_32(temp, tempb, out); -} - static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext) { - signed int round; - signed int i; - u8 intermediatea[16]; - u8 intermediateb[16]; - u8 round_key[16]; + struct crypto_aes_ctx ctx; - for (i = 0; i < 16; i++) - round_key[i] = key[i]; - - for (round = 0; round < 11; round++) { - if (round == 0) { - xor_128(round_key, data, ciphertext); - next_key(round_key, round); - } else if (round == 10) { - byte_sub(ciphertext, intermediatea); - shift_row(intermediatea, intermediateb); - xor_128(intermediateb, round_key, ciphertext); - } else { /* 1 - 9 */ - byte_sub(ciphertext, intermediatea); - shift_row(intermediatea, intermediateb); - mix_column(&intermediateb[0], &intermediatea[0]); - mix_column(&intermediateb[4], &intermediatea[4]); - mix_column(&intermediateb[8], &intermediatea[8]); - mix_column(&intermediateb[12], &intermediatea[12]); - xor_128(intermediatea, round_key, ciphertext); - next_key(round_key, round); - } - } + aes_expandkey(&ctx, key, 16); + aes_encrypt(&ctx, ciphertext, data); + memzero_explicit(&ctx, sizeof(ctx)); } /************************************************/ @@ -1758,274 +1444,6 @@ BIP_exit: return res; } -/* AES tables*/ -const u32 Te0[256] = { - 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, - 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, - 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, - 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, - 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, - 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, - 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, - 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, - 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, - 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, - 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, - 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, - 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, - 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, - 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, - 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, - 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, - 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, - 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, - 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, - 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, - 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, - 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, - 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, - 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, - 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, - 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, - 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, - 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, - 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, - 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, - 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, - 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, - 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, - 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, - 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, - 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, - 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, - 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, - 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, - 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, - 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, - 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, - 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, - 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, - 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, - 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, - 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, - 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, - 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, - 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, - 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, - 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, - 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, - 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, - 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, - 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, - 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, - 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, - 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, - 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, - 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, - 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, - 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, -}; - -const u32 Td0[256] = { - 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, - 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, - 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, - 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, - 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, - 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, - 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, - 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, - 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, - 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, - 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, - 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, - 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, - 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, - 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, - 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, - 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, - 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, - 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, - 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, - 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, - 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, - 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, - 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, - 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, - 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, - 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, - 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, - 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, - 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, - 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, - 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, - 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, - 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, - 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, - 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, - 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, - 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, - 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, - 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, - 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, - 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, - 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, - 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, - 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, - 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, - 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, - 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, - 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, - 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, - 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, - 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, - 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, - 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, - 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, - 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, - 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, - 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, - 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, - 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, - 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, - 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, - 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, - 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, -}; - -const u8 Td4s[256] = { - 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, - 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, - 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, - 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, - 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, - 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, - 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, - 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, - 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, - 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, - 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, - 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, - 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, - 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, - 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, - 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, - 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, - 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, - 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, - 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, - 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, - 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, - 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, - 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, - 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, - 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, - 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, - 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, - 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, - 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, - 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, - 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, -}; - -const u8 rcons[] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 - /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ -}; - -/** - * Expand the cipher key into the encryption key schedule. - * - * @return the number of rounds for the given cipher key size. - */ -static void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[]) -{ - int i; - u32 temp; - - rk[0] = GETU32(cipherKey); - rk[1] = GETU32(cipherKey + 4); - rk[2] = GETU32(cipherKey + 8); - rk[3] = GETU32(cipherKey + 12); - for (i = 0; i < 10; i++) { - temp = rk[3]; - rk[4] = rk[0] ^ - TE421(temp) ^ TE432(temp) ^ TE443(temp) ^ TE414(temp) ^ - RCON(i); - rk[5] = rk[1] ^ rk[4]; - rk[6] = rk[2] ^ rk[5]; - rk[7] = rk[3] ^ rk[6]; - rk += 4; - } -} - -static void rijndaelEncrypt(u32 rk[/*44*/], u8 pt[16], u8 ct[16]) -{ - u32 s0, s1, s2, s3, t0, t1, t2, t3; - int Nr = 10; - int r; - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(pt) ^ rk[0]; - s1 = GETU32(pt + 4) ^ rk[1]; - s2 = GETU32(pt + 8) ^ rk[2]; - s3 = GETU32(pt + 12) ^ rk[3]; - -#define ROUND(i, d, s) \ - do { \ - d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \ - d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \ - d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \ - d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]; \ - } while (0) - - /* Nr - 1 full rounds: */ - r = Nr >> 1; - for (;;) { - ROUND(1, t, s); - rk += 8; - if (--r == 0) - break; - ROUND(0, s, t); - } - -#undef ROUND - - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0]; - PUTU32(ct, s0); - s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1]; - PUTU32(ct + 4, s1); - s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2]; - PUTU32(ct + 8, s2); - s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3]; - PUTU32(ct + 12, s3); -} - -static void *aes_encrypt_init(u8 *key, size_t len) -{ - u32 *rk; - - if (len != 16) - return NULL; - rk = rtw_malloc(AES_PRIV_SIZE); - if (rk == NULL) - return NULL; - rijndaelKeySetupEnc(rk, key); - return rk; -} - -static void aes_128_encrypt(void *ctx, u8 *plain, u8 *crypt) -{ - rijndaelEncrypt(ctx, plain, crypt); -} - static void gf_mulx(u8 *pad) { int i, carry; @@ -2039,11 +1457,6 @@ static void gf_mulx(u8 *pad) pad[AES_BLOCK_SIZE - 1] ^= 0x87; } -static void aes_encrypt_deinit(void *ctx) -{ - kfree_sensitive(ctx); -} - /** * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128 * @key: 128-bit key for the hash operation @@ -2058,15 +1471,16 @@ static void aes_encrypt_deinit(void *ctx) * (SP) 800-38B. */ static int omac1_aes_128_vector(u8 *key, size_t num_elem, - u8 *addr[], size_t *len, u8 *mac) + u8 *addr[], size_t *len, u8 *mac) { - void *ctx; + struct crypto_aes_ctx ctx; u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; u8 *pos, *end; size_t i, e, left, total_len; + int ret; - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) + ret = aes_expandkey(&ctx, key, 16); + if (ret) return -1; memset(cbc, 0, AES_BLOCK_SIZE); @@ -2089,12 +1503,12 @@ static int omac1_aes_128_vector(u8 *key, size_t num_elem, } } if (left > AES_BLOCK_SIZE) - aes_128_encrypt(ctx, cbc, cbc); + aes_encrypt(&ctx, cbc, cbc); left -= AES_BLOCK_SIZE; } memset(pad, 0, AES_BLOCK_SIZE); - aes_128_encrypt(ctx, pad, pad); + aes_encrypt(&ctx, pad, pad); gf_mulx(pad); if (left || total_len == 0) { @@ -2112,8 +1526,8 @@ static int omac1_aes_128_vector(u8 *key, size_t num_elem, for (i = 0; i < AES_BLOCK_SIZE; i++) pad[i] ^= cbc[i]; - aes_128_encrypt(ctx, pad, mac); - aes_encrypt_deinit(ctx); + aes_encrypt(&ctx, pad, mac); + memzero_explicit(&ctx, sizeof(ctx)); return 0; } diff --git a/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c b/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c index 85663182b388..67ca219f95bf 100644 --- a/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c +++ b/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c @@ -4,8 +4,6 @@ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. * ******************************************************************************/ -#define _RTW_STA_MGT_C_ - #include <drv_types.h> #include <rtw_debug.h> @@ -119,7 +117,6 @@ void kfree_all_stainfo(struct sta_priv *pstapriv); void kfree_all_stainfo(struct sta_priv *pstapriv) { struct list_head *plist, *phead; - struct sta_info *psta = NULL; spin_lock_bh(&pstapriv->sta_hash_lock); @@ -127,7 +124,6 @@ void kfree_all_stainfo(struct sta_priv *pstapriv) plist = get_next(phead); while (phead != plist) { - psta = container_of(plist, struct sta_info, list); plist = get_next(plist); } @@ -152,13 +148,11 @@ u32 _rtw_free_sta_priv(struct sta_priv *pstapriv) spin_lock_bh(&pstapriv->sta_hash_lock); for (index = 0; index < NUM_STA; index++) { phead = &(pstapriv->sta_hash[index]); - plist = get_next(phead); - - while (phead != plist) { + list_for_each(plist, phead) { int i; - psta = container_of(plist, struct sta_info, hash_list); - plist = get_next(plist); + psta = list_entry(plist, struct sta_info, + hash_list); for (i = 0; i < 16 ; i++) { preorder_ctrl = &psta->recvreorder_ctrl[i]; @@ -429,7 +423,7 @@ exit: /* free all stainfo which in sta_hash[all] */ void rtw_free_all_stainfo(struct adapter *padapter) { - struct list_head *plist, *phead; + struct list_head *plist, *phead, *tmp; s32 index; struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; @@ -442,12 +436,8 @@ void rtw_free_all_stainfo(struct adapter *padapter) for (index = 0; index < NUM_STA; index++) { phead = &(pstapriv->sta_hash[index]); - plist = get_next(phead); - - while (phead != plist) { - psta = container_of(plist, struct sta_info, hash_list); - - plist = get_next(plist); + list_for_each_safe(plist, tmp, phead) { + psta = list_entry(plist, struct sta_info, hash_list); if (pbcmc_stainfo != psta) rtw_free_stainfo(padapter, psta); @@ -479,17 +469,14 @@ struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) spin_lock_bh(&pstapriv->sta_hash_lock); phead = &(pstapriv->sta_hash[index]); - plist = get_next(phead); - - while (phead != plist) { - psta = container_of(plist, struct sta_info, hash_list); + list_for_each(plist, phead) { + psta = list_entry(plist, struct sta_info, hash_list); if ((!memcmp(psta->hwaddr, addr, ETH_ALEN))) /* if found the matched address */ break; psta = NULL; - plist = get_next(plist); } spin_unlock_bh(&pstapriv->sta_hash_lock); @@ -499,7 +486,6 @@ struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) u32 rtw_init_bcmc_stainfo(struct adapter *padapter) { struct sta_info *psta; - u32 res = _SUCCESS; NDIS_802_11_MAC_ADDRESS bcast_addr = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; struct sta_priv *pstapriv = &padapter->stapriv; @@ -507,15 +493,12 @@ u32 rtw_init_bcmc_stainfo(struct adapter *padapter) psta = rtw_alloc_stainfo(pstapriv, bcast_addr); - if (!psta) { - res = _FAIL; - goto exit; - } + if (!psta) + return _FAIL; /* default broadcast & multicast use macid 1 */ psta->mac_id = 1; -exit: return _SUCCESS; } @@ -539,10 +522,8 @@ u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr) spin_lock_bh(&(pacl_node_q->lock)); phead = get_list_head(pacl_node_q); - plist = get_next(phead); - while (phead != plist) { - paclnode = container_of(plist, struct rtw_wlan_acl_node, list); - plist = get_next(plist); + list_for_each(plist, phead) { + paclnode = list_entry(plist, struct rtw_wlan_acl_node, list); if (!memcmp(paclnode->addr, mac_addr, ETH_ALEN)) if (paclnode->valid == true) { diff --git a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c index f9bd7c167da7..c06b74f6569a 100644 --- a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c @@ -55,9 +55,6 @@ u8 networktype_to_raid_ex(struct adapter *adapter, struct sta_info *psta) if (cur_rf_type == RF_1T1R) { rf_type = RF_1T1R; - } else if (IsSupportedVHT(psta->wireless_mode)) { - if (psta->ra_mask & 0xffc00000) - rf_type = RF_2T2R; } else if (IsSupportedHT(psta->wireless_mode)) { if (psta->ra_mask & 0xfff00000) rf_type = RF_2T2R; @@ -67,7 +64,6 @@ u8 networktype_to_raid_ex(struct adapter *adapter, struct sta_info *psta) case WIRELESS_11B: raid = RATEID_IDX_B; break; - case WIRELESS_11A: case WIRELESS_11G: raid = RATEID_IDX_G; break; @@ -75,8 +71,6 @@ u8 networktype_to_raid_ex(struct adapter *adapter, struct sta_info *psta) raid = RATEID_IDX_BG; break; case WIRELESS_11_24N: - case WIRELESS_11_5N: - case WIRELESS_11A_5N: case WIRELESS_11G_24N: if (rf_type == RF_2T2R) raid = RATEID_IDX_GN_N2SS; @@ -342,9 +336,7 @@ u8 rtw_get_center_ch(u8 channel, u8 chnl_bw, u8 chnl_offset) { u8 center_ch = channel; - if (chnl_bw == CHANNEL_WIDTH_80) { - center_ch = 7; - } else if (chnl_bw == CHANNEL_WIDTH_40) { + if (chnl_bw == CHANNEL_WIDTH_40) { if (chnl_offset == HAL_PRIME_CHNL_OFFSET_LOWER) center_ch = channel + 2; else @@ -381,14 +373,6 @@ void set_channel_bwmode(struct adapter *padapter, unsigned char channel, unsigne center_ch = rtw_get_center_ch(channel, bwmode, channel_offset); - if (bwmode == CHANNEL_WIDTH_80) { - if (center_ch > channel) - chnl_offset80 = HAL_PRIME_CHNL_OFFSET_LOWER; - else if (center_ch < channel) - chnl_offset80 = HAL_PRIME_CHNL_OFFSET_UPPER; - else - chnl_offset80 = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - } /* set Channel */ if (mutex_lock_interruptible(&(adapter_to_dvobj(padapter)->setch_mutex))) @@ -777,6 +761,32 @@ int WMM_param_handler(struct adapter *padapter, struct ndis_80211_var_ie *pIE) return true; } +static void sort_wmm_ac_params(u32 *inx, u32 *edca) +{ + u32 i, j, change_inx = false; + + /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */ + for (i = 0; i < 4; i++) { + for (j = i + 1; j < 4; j++) { + /* compare CW and AIFS */ + if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF)) { + change_inx = true; + } else if ((edca[j] & 0xFFFF) == (edca[i] & 0xFFFF)) { + /* compare TXOP */ + if ((edca[j] >> 16) > (edca[i] >> 16)) + change_inx = true; + } + + if (change_inx) { + swap(edca[i], edca[j]); + swap(inx[i], inx[j]); + + change_inx = false; + } + } + } +} + void WMMOnAssocRsp(struct adapter *padapter) { u8 ACI, ACM, AIFS, ECWMin, ECWMax, aSifsTime; @@ -801,7 +811,7 @@ void WMMOnAssocRsp(struct adapter *padapter) AIFS = aSifsTime + (2 * pmlmeinfo->slotTime); - if (pmlmeext->cur_wireless_mode & (WIRELESS_11G | WIRELESS_11A)) { + if (pmlmeext->cur_wireless_mode & WIRELESS_11G) { ECWMin = 4; ECWMax = 10; } else if (pmlmeext->cur_wireless_mode & WIRELESS_11B) { @@ -873,35 +883,8 @@ void WMMOnAssocRsp(struct adapter *padapter) inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3; - if (pregpriv->wifi_spec == 1) { - u32 j, tmp, change_inx = false; - - /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */ - for (i = 0; i < 4; i++) { - for (j = i+1; j < 4; j++) { - /* compare CW and AIFS */ - if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF)) { - change_inx = true; - } else if ((edca[j] & 0xFFFF) == (edca[i] & 0xFFFF)) { - /* compare TXOP */ - if ((edca[j] >> 16) > (edca[i] >> 16)) - change_inx = true; - } - - if (change_inx) { - tmp = edca[i]; - edca[i] = edca[j]; - edca[j] = tmp; - - tmp = inx[i]; - inx[i] = inx[j]; - inx[j] = tmp; - - change_inx = false; - } - } - } - } + if (pregpriv->wifi_spec == 1) + sort_wmm_ac_params(inx, edca); for (i = 0; i < 4; i++) pxmitpriv->wmm_para_seq[i] = inx[i]; @@ -926,9 +909,6 @@ static void bwmode_update_check(struct adapter *padapter, struct ndis_80211_var_ if (phtpriv->ht_option == false) return; - if (pmlmeext->cur_bwmode >= CHANNEL_WIDTH_80) - return; - if (pIE->Length > sizeof(struct HT_info_element)) return; @@ -1255,34 +1235,34 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) /* parsing HT_CAP_IE */ p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, bssid->IELength - _FIXED_IE_LENGTH_); if (p && len > 0) { - pht_cap = (struct ieee80211_ht_cap *)(p + 2); - ht_cap_info = le16_to_cpu(pht_cap->cap_info); + pht_cap = (struct ieee80211_ht_cap *)(p + 2); + ht_cap_info = le16_to_cpu(pht_cap->cap_info); } else { - ht_cap_info = 0; + ht_cap_info = 0; } /* parsing HT_INFO_IE */ p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, WLAN_EID_HT_OPERATION, &len, bssid->IELength - _FIXED_IE_LENGTH_); if (p && len > 0) { - pht_info = (struct HT_info_element *)(p + 2); - ht_info_infos_0 = pht_info->infos[0]; + pht_info = (struct HT_info_element *)(p + 2); + ht_info_infos_0 = pht_info->infos[0]; } else { - ht_info_infos_0 = 0; + ht_info_infos_0 = 0; } if (ht_cap_info != cur_network->BcnInfo.ht_cap_info || - ((ht_info_infos_0&0x03) != (cur_network->BcnInfo.ht_info_infos_0&0x03))) { - { - /* bcn_info_update */ - cur_network->BcnInfo.ht_cap_info = ht_cap_info; - cur_network->BcnInfo.ht_info_infos_0 = ht_info_infos_0; - /* to do : need to check that whether modify related register of BB or not */ - } - /* goto _mismatch; */ + ((ht_info_infos_0&0x03) != (cur_network->BcnInfo.ht_info_infos_0&0x03))) { + { + /* bcn_info_update */ + cur_network->BcnInfo.ht_cap_info = ht_cap_info; + cur_network->BcnInfo.ht_info_infos_0 = ht_info_infos_0; + /* to do : need to check that whether modify related register of BB or not */ + } + /* goto _mismatch; */ } /* Checking for channel */ p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, WLAN_EID_DS_PARAMS, &len, bssid->IELength - _FIXED_IE_LENGTH_); if (p) { - bcn_channel = *(p + 2); + bcn_channel = *(p + 2); } else {/* In 5G, some ap do not have DSSET IE checking HT info for channel */ rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, WLAN_EID_HT_OPERATION, &len, bssid->IELength - _FIXED_IE_LENGTH_); @@ -1293,7 +1273,7 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) } if (bcn_channel != Adapter->mlmeextpriv.cur_channel) - goto _mismatch; + goto _mismatch; /* checking SSID */ ssid_len = 0; @@ -1496,6 +1476,33 @@ void set_sta_rate(struct adapter *padapter, struct sta_info *psta) Update_RA_Entry(padapter, psta); } +static u32 get_realtek_assoc_AP_vender(struct ndis_80211_var_ie *pIE) +{ + u32 Vender = HT_IOT_PEER_REALTEK; + + if (pIE->Length >= 5) { + if (pIE->data[4] == 1) + /* if (pIE->data[5] & RT_HT_CAP_USE_LONG_PREAMBLE) */ + /* bssDesc->BssHT.RT2RT_HT_Mode |= RT_HT_CAP_USE_LONG_PREAMBLE; */ + if (pIE->data[5] & RT_HT_CAP_USE_92SE) + /* bssDesc->BssHT.RT2RT_HT_Mode |= RT_HT_CAP_USE_92SE; */ + Vender = HT_IOT_PEER_REALTEK_92SE; + + if (pIE->data[5] & RT_HT_CAP_USE_SOFTAP) + Vender = HT_IOT_PEER_REALTEK_SOFTAP; + + if (pIE->data[4] == 2) { + if (pIE->data[6] & RT_HT_CAP_USE_JAGUAR_BCUT) + Vender = HT_IOT_PEER_REALTEK_JAGUAR_BCUTAP; + + if (pIE->data[6] & RT_HT_CAP_USE_JAGUAR_CCUT) + Vender = HT_IOT_PEER_REALTEK_JAGUAR_CCUTAP; + } + } + + return Vender; +} + unsigned char check_assoc_AP(u8 *pframe, uint len) { unsigned int i; @@ -1506,47 +1513,24 @@ unsigned char check_assoc_AP(u8 *pframe, uint len) switch (pIE->ElementID) { case WLAN_EID_VENDOR_SPECIFIC: - if ((!memcmp(pIE->data, ARTHEROS_OUI1, 3)) || (!memcmp(pIE->data, ARTHEROS_OUI2, 3))) { + if ((!memcmp(pIE->data, ARTHEROS_OUI1, 3)) || (!memcmp(pIE->data, ARTHEROS_OUI2, 3))) return HT_IOT_PEER_ATHEROS; - } else if ((!memcmp(pIE->data, BROADCOM_OUI1, 3)) || - (!memcmp(pIE->data, BROADCOM_OUI2, 3)) || - (!memcmp(pIE->data, BROADCOM_OUI3, 3))) { + else if ((!memcmp(pIE->data, BROADCOM_OUI1, 3)) || + (!memcmp(pIE->data, BROADCOM_OUI2, 3)) || + (!memcmp(pIE->data, BROADCOM_OUI3, 3))) return HT_IOT_PEER_BROADCOM; - } else if (!memcmp(pIE->data, MARVELL_OUI, 3)) { + else if (!memcmp(pIE->data, MARVELL_OUI, 3)) return HT_IOT_PEER_MARVELL; - } else if (!memcmp(pIE->data, RALINK_OUI, 3)) { + else if (!memcmp(pIE->data, RALINK_OUI, 3)) return HT_IOT_PEER_RALINK; - } else if (!memcmp(pIE->data, CISCO_OUI, 3)) { + else if (!memcmp(pIE->data, CISCO_OUI, 3)) return HT_IOT_PEER_CISCO; - } else if (!memcmp(pIE->data, REALTEK_OUI, 3)) { - u32 Vender = HT_IOT_PEER_REALTEK; - - if (pIE->Length >= 5) { - if (pIE->data[4] == 1) - /* if (pIE->data[5] & RT_HT_CAP_USE_LONG_PREAMBLE) */ - /* bssDesc->BssHT.RT2RT_HT_Mode |= RT_HT_CAP_USE_LONG_PREAMBLE; */ - if (pIE->data[5] & RT_HT_CAP_USE_92SE) - /* bssDesc->BssHT.RT2RT_HT_Mode |= RT_HT_CAP_USE_92SE; */ - Vender = HT_IOT_PEER_REALTEK_92SE; - - if (pIE->data[5] & RT_HT_CAP_USE_SOFTAP) - Vender = HT_IOT_PEER_REALTEK_SOFTAP; - - if (pIE->data[4] == 2) { - if (pIE->data[6] & RT_HT_CAP_USE_JAGUAR_BCUT) - Vender = HT_IOT_PEER_REALTEK_JAGUAR_BCUTAP; - - if (pIE->data[6] & RT_HT_CAP_USE_JAGUAR_CCUT) - Vender = HT_IOT_PEER_REALTEK_JAGUAR_CCUTAP; - } - } - - return Vender; - } else if (!memcmp(pIE->data, AIRGOCAP_OUI, 3)) { + else if (!memcmp(pIE->data, REALTEK_OUI, 3)) + return get_realtek_assoc_AP_vender(pIE); + else if (!memcmp(pIE->data, AIRGOCAP_OUI, 3)) return HT_IOT_PEER_AIRGO; - } else { + else break; - } default: break; @@ -1620,7 +1604,7 @@ void update_capinfo(struct adapter *Adapter, u16 updateCap) pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME; } else { /* Filen: See 802.11-2007 p.90 */ - if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N | WIRELESS_11A | WIRELESS_11_5N | WIRELESS_11AC)) { + if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N)) { pmlmeinfo->slotTime = SHORT_SLOT_TIME; } else if (pmlmeext->cur_wireless_mode & (WIRELESS_11G)) { if ((updateCap & cShortSlotTime) /* && (!(pMgntInfo->pHTInfo->RT2RT_HT_Mode & RT_HT_CAP_USE_LONG_PREAMBLE)) */) @@ -1650,9 +1634,7 @@ void update_wireless_mode(struct adapter *padapter) if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable)) pmlmeinfo->HT_enable = 1; - if (pmlmeinfo->VHT_enable) - network_type = WIRELESS_11AC; - else if (pmlmeinfo->HT_enable) + if (pmlmeinfo->HT_enable) network_type = WIRELESS_11_24N; if (rtw_is_cckratesonly_included(rate)) @@ -1716,7 +1698,7 @@ int update_sta_support_rate(struct adapter *padapter, u8 *pvar_ie, uint var_ie_l void process_addba_req(struct adapter *padapter, u8 *paddba_req, u8 *addr) { struct sta_info *psta; - u16 tid, start_seq, param; + u16 tid, param; struct recv_reorder_ctrl *preorder_ctrl; struct sta_priv *pstapriv = &padapter->stapriv; struct ADDBA_request *preq = (struct ADDBA_request *)paddba_req; @@ -1726,8 +1708,6 @@ void process_addba_req(struct adapter *padapter, u8 *paddba_req, u8 *addr) psta = rtw_get_stainfo(pstapriv, addr); if (psta) { - start_seq = le16_to_cpu(preq->BA_starting_seqctrl) >> 4; - param = le16_to_cpu(preq->BA_para_set); tid = (param>>2)&0x0f; diff --git a/drivers/staging/rtl8723bs/core/rtw_xmit.c b/drivers/staging/rtl8723bs/core/rtw_xmit.c index bd3acdd7d75f..79e4d7df1ef5 100644 --- a/drivers/staging/rtl8723bs/core/rtw_xmit.c +++ b/drivers/staging/rtl8723bs/core/rtw_xmit.c @@ -4,8 +4,6 @@ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. * ******************************************************************************/ -#define _RTW_XMIT_C_ - #include <drv_types.h> #include <rtw_debug.h> @@ -323,15 +321,12 @@ void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv) u8 query_ra_short_GI(struct sta_info *psta) { - u8 sgi = false, sgi_20m = false, sgi_40m = false, sgi_80m = false; + u8 sgi = false, sgi_20m = false, sgi_40m = false; sgi_20m = psta->htpriv.sgi_20m; sgi_40m = psta->htpriv.sgi_40m; switch (psta->bw_mode) { - case CHANNEL_WIDTH_80: - sgi = sgi_80m; - break; case CHANNEL_WIDTH_40: sgi = sgi_40m; break; @@ -647,7 +642,7 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p pattrib->pktlen = pktfile.pkt_len; - if (ETH_P_IP == pattrib->ether_type) { + if (pattrib->ether_type == ETH_P_IP) { /* The following is for DHCP and ARP packet, we use cck1M to tx these packets and let LPS awake some time */ /* to prevent DHCP protocol fail */ @@ -657,7 +652,7 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p pattrib->dhcp_pkt = 0; if (pktfile.pkt_len > 282) {/* MINIMUM_DHCP_PACKET_SIZE) { */ - if (ETH_P_IP == pattrib->ether_type) {/* IP header */ + if (pattrib->ether_type == ETH_P_IP) {/* IP header */ if (((tmp[21] == 68) && (tmp[23] == 67)) || ((tmp[21] == 67) && (tmp[23] == 68))) { /* 68 : UDP BOOTP client */ @@ -675,7 +670,7 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p if (piphdr->protocol == 0x1) /* protocol type in ip header 0x1 is ICMP */ pattrib->icmp_pkt = 1; } - } else if (0x888e == pattrib->ether_type) { + } else if (pattrib->ether_type == 0x888e) { netdev_dbg(padapter->pnetdev, "send eapol packet\n"); } @@ -1725,18 +1720,14 @@ exit: void rtw_free_xmitframe_queue(struct xmit_priv *pxmitpriv, struct __queue *pframequeue) { - struct list_head *plist, *phead; + struct list_head *plist, *phead, *tmp; struct xmit_frame *pxmitframe; spin_lock_bh(&pframequeue->lock); phead = get_list_head(pframequeue); - plist = get_next(phead); - - while (phead != plist) { - pxmitframe = container_of(plist, struct xmit_frame, list); - - plist = get_next(plist); + list_for_each_safe(plist, tmp, phead) { + pxmitframe = list_entry(plist, struct xmit_frame, list); rtw_free_xmitframe(pxmitpriv, pxmitframe); } @@ -2128,7 +2119,7 @@ signed int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct x static void dequeue_xmitframes_to_sleeping_queue(struct adapter *padapter, struct sta_info *psta, struct __queue *pframequeue) { signed int ret; - struct list_head *plist, *phead; + struct list_head *plist, *phead, *tmp; u8 ac_index; struct tx_servq *ptxservq; struct pkt_attrib *pattrib; @@ -2136,12 +2127,8 @@ static void dequeue_xmitframes_to_sleeping_queue(struct adapter *padapter, struc struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits; phead = get_list_head(pframequeue); - plist = get_next(phead); - - while (phead != plist) { - pxmitframe = container_of(plist, struct xmit_frame, list); - - plist = get_next(plist); + list_for_each_safe(plist, tmp, phead) { + pxmitframe = list_entry(plist, struct xmit_frame, list); pattrib = &pxmitframe->attrib; @@ -2201,7 +2188,7 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta) { u8 update_mask = 0, wmmps_ac = 0; struct sta_info *psta_bmc; - struct list_head *xmitframe_plist, *xmitframe_phead; + struct list_head *xmitframe_plist, *xmitframe_phead, *tmp; struct xmit_frame *pxmitframe = NULL; struct sta_priv *pstapriv = &padapter->stapriv; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; @@ -2211,12 +2198,9 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta) spin_lock_bh(&pxmitpriv->lock); xmitframe_phead = get_list_head(&psta->sleep_q); - xmitframe_plist = get_next(xmitframe_phead); - - while (xmitframe_phead != xmitframe_plist) { - pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list); - - xmitframe_plist = get_next(xmitframe_plist); + list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) { + pxmitframe = list_entry(xmitframe_plist, struct xmit_frame, + list); list_del_init(&pxmitframe->list); @@ -2285,12 +2269,9 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta) if ((pstapriv->sta_dz_bitmap&0xfffe) == 0x0) { /* no any sta in ps mode */ xmitframe_phead = get_list_head(&psta_bmc->sleep_q); - xmitframe_plist = get_next(xmitframe_phead); - - while (xmitframe_phead != xmitframe_plist) { - pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list); - - xmitframe_plist = get_next(xmitframe_plist); + list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) { + pxmitframe = list_entry(xmitframe_plist, + struct xmit_frame, list); list_del_init(&pxmitframe->list); @@ -2324,7 +2305,7 @@ _exit: void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *psta) { u8 wmmps_ac = 0; - struct list_head *xmitframe_plist, *xmitframe_phead; + struct list_head *xmitframe_plist, *xmitframe_phead, *tmp; struct xmit_frame *pxmitframe = NULL; struct sta_priv *pstapriv = &padapter->stapriv; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; @@ -2332,12 +2313,9 @@ void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *pst spin_lock_bh(&pxmitpriv->lock); xmitframe_phead = get_list_head(&psta->sleep_q); - xmitframe_plist = get_next(xmitframe_phead); - - while (xmitframe_phead != xmitframe_plist) { - pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list); - - xmitframe_plist = get_next(xmitframe_plist); + list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) { + pxmitframe = list_entry(xmitframe_plist, struct xmit_frame, + list); switch (pxmitframe->attrib.priority) { case 1: @@ -2524,7 +2502,7 @@ void rtw_sctx_init(struct submit_ctx *sctx, int timeout_ms) sctx->status = RTW_SCTX_SUBMITTED; } -int rtw_sctx_wait(struct submit_ctx *sctx, const char *msg) +int rtw_sctx_wait(struct submit_ctx *sctx) { int ret = _FAIL; unsigned long expire; @@ -2565,7 +2543,7 @@ int rtw_ack_tx_wait(struct xmit_priv *pxmitpriv, u32 timeout_ms) pack_tx_ops->timeout_ms = timeout_ms; pack_tx_ops->status = RTW_SCTX_SUBMITTED; - return rtw_sctx_wait(pack_tx_ops, __func__); + return rtw_sctx_wait(pack_tx_ops); } void rtw_ack_tx_done(struct xmit_priv *pxmitpriv, int status) diff --git a/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c b/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c index 503790924532..dc58bb87f1b0 100644 --- a/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c +++ b/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c @@ -38,110 +38,44 @@ static u8 halbtc8723b1ant_BtRssiState( (pCoexSta->preBtRssiState == BTC_RSSI_STATE_LOW) || (pCoexSta->preBtRssiState == BTC_RSSI_STATE_STAY_LOW) ) { - if (btRssi >= (rssiThresh + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT)) { + if (btRssi >= (rssiThresh + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT)) btRssiState = BTC_RSSI_STATE_HIGH; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_BT_RSSI_STATE, - ("[BTCoex], BT Rssi state switch to High\n") - ); - } else { + else btRssiState = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_BT_RSSI_STATE, - ("[BTCoex], BT Rssi state stay at Low\n") - ); - } } else { - if (btRssi < rssiThresh) { + if (btRssi < rssiThresh) btRssiState = BTC_RSSI_STATE_LOW; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_BT_RSSI_STATE, - ("[BTCoex], BT Rssi state switch to Low\n") - ); - } else { + else btRssiState = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_BT_RSSI_STATE, - ("[BTCoex], BT Rssi state stay at High\n") - ); - } } } else if (levelNum == 3) { - if (rssiThresh > rssiThresh1) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_BT_RSSI_STATE, - ("[BTCoex], BT Rssi thresh error!!\n") - ); + if (rssiThresh > rssiThresh1) return pCoexSta->preBtRssiState; - } if ( (pCoexSta->preBtRssiState == BTC_RSSI_STATE_LOW) || (pCoexSta->preBtRssiState == BTC_RSSI_STATE_STAY_LOW) ) { - if (btRssi >= (rssiThresh + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT)) { + if (btRssi >= (rssiThresh + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT)) btRssiState = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_BT_RSSI_STATE, - ("[BTCoex], BT Rssi state switch to Medium\n") - ); - } else { + else btRssiState = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_BT_RSSI_STATE, - ("[BTCoex], BT Rssi state stay at Low\n") - ); - } } else if ( (pCoexSta->preBtRssiState == BTC_RSSI_STATE_MEDIUM) || (pCoexSta->preBtRssiState == BTC_RSSI_STATE_STAY_MEDIUM) ) { - if (btRssi >= (rssiThresh1 + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT)) { + if (btRssi >= (rssiThresh1 + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT)) btRssiState = BTC_RSSI_STATE_HIGH; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_BT_RSSI_STATE, - ("[BTCoex], BT Rssi state switch to High\n") - ); - } else if (btRssi < rssiThresh) { + else if (btRssi < rssiThresh) btRssiState = BTC_RSSI_STATE_LOW; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_BT_RSSI_STATE, - ("[BTCoex], BT Rssi state switch to Low\n") - ); - } else { + else btRssiState = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_BT_RSSI_STATE, - ("[BTCoex], BT Rssi state stay at Medium\n") - ); - } } else { - if (btRssi < rssiThresh1) { + if (btRssi < rssiThresh1) btRssiState = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_BT_RSSI_STATE, - ("[BTCoex], BT Rssi state switch to Medium\n") - ); - } else { + else btRssiState = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_BT_RSSI_STATE, - ("[BTCoex], BT Rssi state stay at High\n") - ); - } } } @@ -297,7 +231,7 @@ static void halbtc8723b1ant_LimitedRx( u8 rxAggSize = aggBufSize; /* */ - /* Rx Aggregation related setting */ + /* Rx Aggregation related setting */ /* */ pBtCoexist->fBtcSet( pBtCoexist, BTC_SET_BL_TO_REJ_AP_AGG_PKT, &bRejectRxAgg @@ -316,18 +250,12 @@ static void halbtc8723b1ant_LimitedRx( static void halbtc8723b1ant_QueryBtInfo(struct btc_coexist *pBtCoexist) { - u8 H2C_Parameter[1] = {0}; + u8 H2C_Parameter[1] = {0}; pCoexSta->bC2hBtInfoReqSent = true; H2C_Parameter[0] |= BIT0; /* trigger */ - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_EXEC, - ("[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", H2C_Parameter[0]) - ); - pBtCoexist->fBtcFillH2c(pBtCoexist, 0x61, 1, H2C_Parameter); } @@ -367,18 +295,6 @@ static void halbtc8723b1ant_MonitorBtCtr(struct btc_coexist *pBtCoexist) if ((pCoexSta->lowPriorityTx >= 1050) && (!pCoexSta->bC2hBtInquiryPage)) pCoexSta->popEventCnt++; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ( - "[BTCoex], Hi-Pri Rx/Tx: %d/%d, Lo-Pri Rx/Tx: %d/%d\n", - regHPRx, - regHPTx, - regLPRx, - regLPTx - ) - ); - /* reset counter */ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0xc); @@ -445,15 +361,15 @@ static void halbtc8723b1ant_MonitorWiFiCtr(struct btc_coexist *pBtCoexist) ) ) { if (nCCKLockCounter < 5) - nCCKLockCounter++; + nCCKLockCounter++; } else { if (nCCKLockCounter > 0) - nCCKLockCounter--; + nCCKLockCounter--; } } else { if (nCCKLockCounter > 0) - nCCKLockCounter--; + nCCKLockCounter--; } } else { if (nCCKLockCounter > 0) @@ -463,14 +379,14 @@ static void halbtc8723b1ant_MonitorWiFiCtr(struct btc_coexist *pBtCoexist) if (!pCoexSta->bPreCCKLock) { if (nCCKLockCounter >= 5) - pCoexSta->bCCKLock = true; + pCoexSta->bCCKLock = true; else - pCoexSta->bCCKLock = false; + pCoexSta->bCCKLock = false; } else { if (nCCKLockCounter == 0) - pCoexSta->bCCKLock = false; + pCoexSta->bCCKLock = false; else - pCoexSta->bCCKLock = true; + pCoexSta->bCCKLock = true; } pCoexSta->bPreCCKLock = pCoexSta->bCCKLock; @@ -586,14 +502,8 @@ static u8 halbtc8723b1ant_ActionAlgorithm(struct btc_coexist *pBtCoexist) pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn); - if (!pBtLinkInfo->bBtLinkExist) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], No BT link exists!!!\n") - ); + if (!pBtLinkInfo->bBtLinkExist) return algorithm; - } if (pBtLinkInfo->bScoExist) numOfDiffProfile++; @@ -606,151 +516,62 @@ static u8 halbtc8723b1ant_ActionAlgorithm(struct btc_coexist *pBtCoexist) if (numOfDiffProfile == 1) { if (pBtLinkInfo->bScoExist) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT Profile = SCO only\n") - ); algorithm = BT_8723B_1ANT_COEX_ALGO_SCO; } else { if (pBtLinkInfo->bHidExist) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT Profile = HID only\n") - ); algorithm = BT_8723B_1ANT_COEX_ALGO_HID; } else if (pBtLinkInfo->bA2dpExist) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT Profile = A2DP only\n") - ); algorithm = BT_8723B_1ANT_COEX_ALGO_A2DP; } else if (pBtLinkInfo->bPanExist) { - if (bBtHsOn) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT Profile = PAN(HS) only\n") - ); + if (bBtHsOn) algorithm = BT_8723B_1ANT_COEX_ALGO_PANHS; - } else { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT Profile = PAN(EDR) only\n") - ); + else algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR; - } } } } else if (numOfDiffProfile == 2) { if (pBtLinkInfo->bScoExist) { if (pBtLinkInfo->bHidExist) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT Profile = SCO + HID\n") - ); algorithm = BT_8723B_1ANT_COEX_ALGO_HID; } else if (pBtLinkInfo->bA2dpExist) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT Profile = SCO + A2DP ==> SCO\n") - ); algorithm = BT_8723B_1ANT_COEX_ALGO_SCO; } else if (pBtLinkInfo->bPanExist) { - if (bBtHsOn) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT Profile = SCO + PAN(HS)\n") - ); + if (bBtHsOn) algorithm = BT_8723B_1ANT_COEX_ALGO_SCO; - } else { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT Profile = SCO + PAN(EDR)\n") - ); + else algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; - } } } else { if (pBtLinkInfo->bHidExist && pBtLinkInfo->bA2dpExist) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT Profile = HID + A2DP\n") - ); algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP; } else if (pBtLinkInfo->bHidExist && pBtLinkInfo->bPanExist) { - if (bBtHsOn) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT Profile = HID + PAN(HS)\n") - ); + if (bBtHsOn) algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP; - } else { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT Profile = HID + PAN(EDR)\n") - ); + else algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; - } } else if (pBtLinkInfo->bPanExist && pBtLinkInfo->bA2dpExist) { - if (bBtHsOn) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT Profile = A2DP + PAN(HS)\n") - ); + if (bBtHsOn) algorithm = BT_8723B_1ANT_COEX_ALGO_A2DP_PANHS; - } else { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT Profile = A2DP + PAN(EDR)\n") - ); + else algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_A2DP; - } } } } else if (numOfDiffProfile == 3) { if (pBtLinkInfo->bScoExist) { if (pBtLinkInfo->bHidExist && pBtLinkInfo->bA2dpExist) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT Profile = SCO + HID + A2DP ==> HID\n") - ); algorithm = BT_8723B_1ANT_COEX_ALGO_HID; } else if ( pBtLinkInfo->bHidExist && pBtLinkInfo->bPanExist ) { - if (bBtHsOn) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BT Profile = SCO + HID + PAN(HS)\n")); + if (bBtHsOn) algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BT Profile = SCO + HID + PAN(EDR)\n")); + else algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; - } } else if (pBtLinkInfo->bPanExist && pBtLinkInfo->bA2dpExist) { - if (bBtHsOn) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BT Profile = SCO + A2DP + PAN(HS)\n")); + if (bBtHsOn) algorithm = BT_8723B_1ANT_COEX_ALGO_SCO; - } else { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT Profile = SCO + A2DP + PAN(EDR) ==> HID\n") - ); + else algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; - } } } else { if ( @@ -758,21 +579,10 @@ static u8 halbtc8723b1ant_ActionAlgorithm(struct btc_coexist *pBtCoexist) pBtLinkInfo->bPanExist && pBtLinkInfo->bA2dpExist ) { - if (bBtHsOn) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT Profile = HID + A2DP + PAN(HS)\n") - ); + if (bBtHsOn) algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP; - } else { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT Profile = HID + A2DP + PAN(EDR)\n") - ); + else algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP_PANEDR; - } } } } else if (numOfDiffProfile >= 3) { @@ -782,21 +592,9 @@ static u8 halbtc8723b1ant_ActionAlgorithm(struct btc_coexist *pBtCoexist) pBtLinkInfo->bPanExist && pBtLinkInfo->bA2dpExist ) { - if (bBtHsOn) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], Error!!! BT Profile = SCO + HID + A2DP + PAN(HS)\n") - ); - - } else { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT Profile = SCO + HID + A2DP + PAN(EDR) ==>PAN(EDR)+HID\n") - ); + if (!bBtHsOn) algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; - } + } } } @@ -808,7 +606,7 @@ static void halbtc8723b1ant_SetSwPenaltyTxRateAdaptive( struct btc_coexist *pBtCoexist, bool bLowPenaltyRa ) { - u8 H2C_Parameter[6] = {0}; + u8 H2C_Parameter[6] = {0}; H2C_Parameter[0] = 0x6; /* opCode, 0x6 = Retry_Penalty */ @@ -820,15 +618,6 @@ static void halbtc8723b1ant_SetSwPenaltyTxRateAdaptive( H2C_Parameter[5] = 0xf9; /* MCS5 or OFDM36 */ } - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_EXEC, - ( - "[BTCoex], set WiFi Low-Penalty Retry: %s", - (bLowPenaltyRa ? "ON!!" : "OFF!!") - ) - ); - pBtCoexist->fBtcFillH2c(pBtCoexist, 0x69, 6, H2C_Parameter); } @@ -857,32 +646,12 @@ static void halbtc8723b1ant_SetCoexTable( u8 val0x6cc ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW_EXEC, - ("[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0) - ); pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x6c0, val0x6c0); - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW_EXEC, - ("[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4) - ); pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x6c4, val0x6c4); - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW_EXEC, - ("[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8) - ); pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x6c8, val0x6c8); - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW_EXEC, - ("[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc) - ); pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x6cc, val0x6cc); } @@ -895,15 +664,6 @@ static void halbtc8723b1ant_CoexTable( u8 val0x6cc ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW, - ( - "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, 0x6c4 = 0x%x, 0x6cc = 0x%x\n", - (bForceExec ? "force to" : ""), - val0x6c0, val0x6c4, val0x6cc - ) - ); pCoexDm->curVal0x6c0 = val0x6c0; pCoexDm->curVal0x6c4 = val0x6c4; pCoexDm->curVal0x6c8 = val0x6c8; @@ -933,12 +693,6 @@ static void halbtc8723b1ant_CoexTableWithType( struct btc_coexist *pBtCoexist, bool bForceExec, u8 type ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], ********** CoexTable(%d) **********\n", type) - ); - pCoexSta->nCoexTableType = type; switch (type) { @@ -996,15 +750,6 @@ static void halbtc8723b1ant_SetFwIgnoreWlanAct( if (bEnable) H2C_Parameter[0] |= BIT0; /* function enable */ - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_EXEC, - ( - "[BTCoex], set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n", - H2C_Parameter[0] - ) - ); - pBtCoexist->fBtcFillH2c(pBtCoexist, 0x63, 1, H2C_Parameter); } @@ -1012,28 +757,9 @@ static void halbtc8723b1ant_IgnoreWlanAct( struct btc_coexist *pBtCoexist, bool bForceExec, bool bEnable ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW, - ( - "[BTCoex], %s turn Ignore WlanAct %s\n", - (bForceExec ? "force to" : ""), - (bEnable ? "ON" : "OFF") - ) - ); pCoexDm->bCurIgnoreWlanAct = bEnable; if (!bForceExec) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - ( - "[BTCoex], bPreIgnoreWlanAct = %d, bCurIgnoreWlanAct = %d!!\n", - pCoexDm->bPreIgnoreWlanAct, - pCoexDm->bCurIgnoreWlanAct - ) - ); - if (pCoexDm->bPreIgnoreWlanAct == pCoexDm->bCurIgnoreWlanAct) return; } @@ -1057,44 +783,14 @@ static void halbtc8723b1ant_LpsRpwm( struct btc_coexist *pBtCoexist, bool bForceExec, u8 lpsVal, u8 rpwmVal ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW, - ( - "[BTCoex], %s set lps/rpwm = 0x%x/0x%x\n", - (bForceExec ? "force to" : ""), - lpsVal, - rpwmVal - ) - ); pCoexDm->curLps = lpsVal; pCoexDm->curRpwm = rpwmVal; if (!bForceExec) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - ( - "[BTCoex], LPS-RxBeaconMode = 0x%x , LPS-RPWM = 0x%x!!\n", - pCoexDm->curLps, - pCoexDm->curRpwm - ) - ); - if ( (pCoexDm->preLps == pCoexDm->curLps) && (pCoexDm->preRpwm == pCoexDm->curRpwm) ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - ( - "[BTCoex], LPS-RPWM_Last = 0x%x , LPS-RPWM_Now = 0x%x!!\n", - pCoexDm->preRpwm, - pCoexDm->curRpwm - ) - ); - return; } } @@ -1108,12 +804,6 @@ static void halbtc8723b1ant_SwMechanism( struct btc_coexist *pBtCoexist, bool bLowPenaltyRA ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_BT_MONITOR, - ("[BTCoex], SM[LpRA] = %d\n", bLowPenaltyRA) - ); - halbtc8723b1ant_LowPenaltyRa(pBtCoexist, NORMAL_EXEC, bLowPenaltyRA); } @@ -1189,13 +879,10 @@ static void halbtc8723b1ant_SetAntPath( u1Tmp = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x49d); cntBtCalChk++; - if (u1Tmp & BIT0) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], ########### BT is calibrating (wait cnt =%d) ###########\n", cntBtCalChk)); + if (u1Tmp & BIT0) mdelay(50); - } else { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], ********** BT is NOT calibrating (wait cnt =%d)**********\n", cntBtCalChk)); + else break; - } } /* set grant_bt to PTA */ @@ -1318,11 +1005,6 @@ static void halbtc8723b1ant_SetFwPstdma( if (bApEnable) { if (byte1 & BIT4 && !(byte1 & BIT5)) { - BTC_PRINT( - BTC_MSG_INTERFACE, - INTF_NOTIFY, - ("[BTCoex], FW for 1Ant AP mode\n") - ); realByte1 &= ~BIT4; realByte1 |= BIT5; @@ -1343,19 +1025,6 @@ static void halbtc8723b1ant_SetFwPstdma( pCoexDm->psTdmaPara[3] = byte4; pCoexDm->psTdmaPara[4] = realByte5; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_EXEC, - ( - "[BTCoex], PS-TDMA H2C cmd = 0x%x%08x\n", - H2C_Parameter[0], - H2C_Parameter[1] << 24 | - H2C_Parameter[2] << 16 | - H2C_Parameter[3] << 8 | - H2C_Parameter[4] - ) - ); - pBtCoexist->fBtcFillH2c(pBtCoexist, 0x60, 5, H2C_Parameter); } @@ -1369,35 +1038,13 @@ static void halbtc8723b1ant_PsTdma( u8 rssiAdjustVal = 0; u8 psTdmaByte4Val = 0x50, psTdmaByte0Val = 0x51, psTdmaByte3Val = 0x10; s8 nWiFiDurationAdjust = 0x0; - /* u32 fwVer = 0; */ + /* u32 fwVer = 0; */ - /* BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, ("[BTCoex], %s turn %s PS TDMA, type =%d\n", */ - /* (bForceExec? "force to":""), (bTurnOn? "ON":"OFF"), type)); */ pCoexDm->bCurPsTdmaOn = bTurnOn; pCoexDm->curPsTdma = type; pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy); - if (pCoexDm->bCurPsTdmaOn) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ( - "[BTCoex], ********** TDMA(on, %d) **********\n", - pCoexDm->curPsTdma - ) - ); - } else { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ( - "[BTCoex], ********** TDMA(off, %d) **********\n", - pCoexDm->curPsTdma - ) - ); - } - if (!bForceExec) { if ( (pCoexDm->bPrePsTdmaOn == pCoexDm->bCurPsTdmaOn) && @@ -1670,80 +1317,40 @@ static bool halbtc8723b1ant_IsCommonAction(struct btc_coexist *pBtCoexist) if ( !bWifiConnected && - BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE == pCoexDm->btStatus + pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], Wifi non connected-idle + BT non connected-idle!!\n") - ); - /* halbtc8723b1ant_SwMechanism(pBtCoexist, false); */ bCommon = true; } else if ( bWifiConnected && - (BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE == pCoexDm->btStatus) + (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE) ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], Wifi connected + BT non connected-idle!!\n") - ); - /* halbtc8723b1ant_SwMechanism(pBtCoexist, false); */ bCommon = true; } else if ( !bWifiConnected && - (BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == pCoexDm->btStatus) + (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE) ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], Wifi non connected-idle + BT connected-idle!!\n") - ); - /* halbtc8723b1ant_SwMechanism(pBtCoexist, false); */ bCommon = true; } else if ( bWifiConnected && - (BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == pCoexDm->btStatus) + (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE) ) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Wifi connected + BT connected-idle!!\n")); - /* halbtc8723b1ant_SwMechanism(pBtCoexist, false); */ bCommon = true; } else if ( !bWifiConnected && - (BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE != pCoexDm->btStatus) + (pCoexDm->btStatus != BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE) ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], Wifi non connected-idle + BT Busy!!\n") - ); - /* halbtc8723b1ant_SwMechanism(pBtCoexist, false); */ bCommon = true; } else { - if (bWifiBusy) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], Wifi Connected-Busy + BT Busy!!\n") - ); - } else { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], Wifi Connected-Idle + BT Busy!!\n") - ); - } - bCommon = false; } @@ -1759,16 +1366,10 @@ static void halbtc8723b1ant_TdmaDurationAdjustForAcl( s32 result; /* 0: no change, +1: increase WiFi duration, -1: decrease WiFi duration */ u8 retryCount = 0, btInfoExt; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW, - ("[BTCoex], TdmaDurationAdjustForAcl()\n") - ); - if ( - (BT_8723B_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN == wifiStatus) || - (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN == wifiStatus) || - (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT == wifiStatus) + (wifiStatus == BT_8723B_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN) || + (wifiStatus == BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN) || + (wifiStatus == BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT) ) { if ( pCoexDm->curPsTdma != 1 && @@ -1791,11 +1392,6 @@ static void halbtc8723b1ant_TdmaDurationAdjustForAcl( if (!pCoexDm->bAutoTdmaAdjust) { pCoexDm->bAutoTdmaAdjust = true; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - ("[BTCoex], first run TdmaDurationAdjust()!!\n") - ); halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 2); pCoexDm->psTdmaDuAdjType = 2; @@ -1810,9 +1406,6 @@ static void halbtc8723b1ant_TdmaDurationAdjustForAcl( /* acquire the BT TRx retry count from BT_Info byte2 */ retryCount = pCoexSta->btRetryCnt; btInfoExt = pCoexSta->btInfoExt; - /* BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], retryCount = %d\n", retryCount)); */ - /* BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], up =%d, dn =%d, m =%d, n =%d, WaitCount =%d\n", */ - /* up, dn, m, n, WaitCount)); */ if (pCoexSta->lowPriorityTx > 1050 || pCoexSta->lowPriorityRx > 1250) retryCount++; @@ -1833,11 +1426,6 @@ static void halbtc8723b1ant_TdmaDurationAdjustForAcl( up = 0; dn = 0; result = 1; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - ("[BTCoex], Increase wifi duration!!\n") - ); } } else if (retryCount <= 3) { /* <=3 retry in the last 2-second duration */ up--; @@ -1860,7 +1448,6 @@ static void halbtc8723b1ant_TdmaDurationAdjustForAcl( dn = 0; WaitCount = 0; result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], Decrease wifi duration for retryCounter<3!!\n")); } } else { /* retry count > 3, 只要1次 retry count > 3, 則調窄WiFi duration */ if (WaitCount == 1) @@ -1876,11 +1463,6 @@ static void halbtc8723b1ant_TdmaDurationAdjustForAcl( dn = 0; WaitCount = 0; result = -1; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - ("[BTCoex], Decrease wifi duration for retryCounter>3!!\n") - ); } if (result == -1) { @@ -1917,15 +1499,6 @@ static void halbtc8723b1ant_TdmaDurationAdjustForAcl( halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 1); pCoexDm->psTdmaDuAdjType = 1; } - } else { /* no change */ - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - ( - "[BTCoex], ********** TDMA(on, %d) **********\n", - pCoexDm->curPsTdma - ) - ); } if ( @@ -2002,13 +1575,13 @@ static void halbtc8723b1ant_PowerSaveState( /* */ /* */ -/* Software Coex Mechanism start */ +/* Software Coex Mechanism start */ /* */ /* */ /* */ /* */ -/* Non-Software Coex Mechanism start */ +/* Non-Software Coex Mechanism start */ /* */ /* */ static void halbtc8723b1ant_ActionWifiMultiPort(struct btc_coexist *pBtCoexist) @@ -2091,6 +1664,7 @@ static void halbtc8723b1ant_ActionWifiConnectedBtAclBusy( ) { struct btc_bt_link_info *pBtLinkInfo = &pBtCoexist->btLinkInfo; + halbtc8723b1ant_BtRssiState(2, 28, 0); if ((pCoexSta->lowPriorityRx >= 1000) && (pCoexSta->lowPriorityRx != 65535)) @@ -2103,7 +1677,7 @@ static void halbtc8723b1ant_ActionWifiConnectedBtAclBusy( pCoexDm->bAutoTdmaAdjust = false; return; } else if (pBtLinkInfo->bA2dpOnly) { /* A2DP */ - if (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE == wifiStatus) { + if (wifiStatus == BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE) { halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 32); halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4); pCoexDm->bAutoTdmaAdjust = false; @@ -2158,7 +1732,7 @@ static void halbtc8723b1ant_ActionWifiNotConnectedScan( halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0); /* tdma and coex table */ - if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == pCoexDm->btStatus) { + if (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) { if (pBtLinkInfo->bA2dpExist) { halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 32); halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4); @@ -2170,8 +1744,8 @@ static void halbtc8723b1ant_ActionWifiNotConnectedScan( halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4); } } else if ( - (BT_8723B_1ANT_BT_STATUS_SCO_BUSY == pCoexDm->btStatus) || - (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == pCoexDm->btStatus) + (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_SCO_BUSY) || + (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY) ) { halbtc8723b1ant_ActionBtScoHidOnlyBusy( pBtCoexist, BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN @@ -2215,7 +1789,7 @@ static void halbtc8723b1ant_ActionWifiConnectedScan(struct btc_coexist *pBtCoexi halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0); /* tdma and coex table */ - if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == pCoexDm->btStatus) { + if (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) { if (pBtLinkInfo->bA2dpExist) { halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 32); halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4); @@ -2227,8 +1801,8 @@ static void halbtc8723b1ant_ActionWifiConnectedScan(struct btc_coexist *pBtCoexi halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4); } } else if ( - (BT_8723B_1ANT_BT_STATUS_SCO_BUSY == pCoexDm->btStatus) || - (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == pCoexDm->btStatus) + (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_SCO_BUSY) || + (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY) ) { halbtc8723b1ant_ActionBtScoHidOnlyBusy( pBtCoexist, BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN @@ -2271,20 +1845,9 @@ static void halbtc8723b1ant_ActionWifiConnected(struct btc_coexist *pBtCoexist) bool bScan = false, bLink = false, bRoam = false; bool bUnder4way = false, bApEnable = false; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], CoexForWifiConnect() ===>\n") - ); - pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS, &bUnder4way); if (bUnder4way) { halbtc8723b1ant_ActionWifiConnectedSpecialPacket(pBtCoexist); - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], CoexForWifiConnect(), return for wifi is under 4way<===\n") - ); return; } @@ -2296,11 +1859,6 @@ static void halbtc8723b1ant_ActionWifiConnected(struct btc_coexist *pBtCoexist) halbtc8723b1ant_ActionWifiConnectedScan(pBtCoexist); else halbtc8723b1ant_ActionWifiConnectedSpecialPacket(pBtCoexist); - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], CoexForWifiConnect(), return for wifi is under scan<===\n") - ); return; } @@ -2310,7 +1868,7 @@ static void halbtc8723b1ant_ActionWifiConnected(struct btc_coexist *pBtCoexist) /* power save state */ if ( !bApEnable && - BT_8723B_1ANT_BT_STATUS_ACL_BUSY == pCoexDm->btStatus && + pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_BUSY && !pBtCoexist->btLinkInfo.bHidOnly ) { if (pBtCoexist->btLinkInfo.bA2dpOnly) { /* A2DP */ @@ -2341,14 +1899,14 @@ static void halbtc8723b1ant_ActionWifiConnected(struct btc_coexist *pBtCoexist) /* tdma and coex table */ if (!bWifiBusy) { - if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == pCoexDm->btStatus) { + if (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) { halbtc8723b1ant_ActionWifiConnectedBtAclBusy( pBtCoexist, BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE ); } else if ( - (BT_8723B_1ANT_BT_STATUS_SCO_BUSY == pCoexDm->btStatus) || - (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == pCoexDm->btStatus) + (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_SCO_BUSY) || + (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY) ) { halbtc8723b1ant_ActionBtScoHidOnlyBusy(pBtCoexist, BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE); @@ -2361,14 +1919,14 @@ static void halbtc8723b1ant_ActionWifiConnected(struct btc_coexist *pBtCoexist) halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7); } } else { - if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == pCoexDm->btStatus) { + if (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) { halbtc8723b1ant_ActionWifiConnectedBtAclBusy( pBtCoexist, BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY ); } else if ( - (BT_8723B_1ANT_BT_STATUS_SCO_BUSY == pCoexDm->btStatus) || - (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == pCoexDm->btStatus) + (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_SCO_BUSY) || + (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY) ) { halbtc8723b1ant_ActionBtScoHidOnlyBusy( pBtCoexist, @@ -2397,47 +1955,36 @@ static void halbtc8723b1ant_RunSwCoexistMechanism(struct btc_coexist *pBtCoexist } else { switch (pCoexDm->curAlgorithm) { case BT_8723B_1ANT_COEX_ALGO_SCO: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = SCO.\n")); /* halbtc8723b1ant_ActionSco(pBtCoexist); */ break; case BT_8723B_1ANT_COEX_ALGO_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = HID.\n")); /* halbtc8723b1ant_ActionHid(pBtCoexist); */ break; case BT_8723B_1ANT_COEX_ALGO_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = A2DP.\n")); /* halbtc8723b1ant_ActionA2dp(pBtCoexist); */ break; case BT_8723B_1ANT_COEX_ALGO_A2DP_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = A2DP+PAN(HS).\n")); /* halbtc8723b1ant_ActionA2dpPanHs(pBtCoexist); */ break; case BT_8723B_1ANT_COEX_ALGO_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = PAN(EDR).\n")); /* halbtc8723b1ant_ActionPanEdr(pBtCoexist); */ break; case BT_8723B_1ANT_COEX_ALGO_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = HS mode.\n")); /* halbtc8723b1ant_ActionPanHs(pBtCoexist); */ break; case BT_8723B_1ANT_COEX_ALGO_PANEDR_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = PAN+A2DP.\n")); /* halbtc8723b1ant_ActionPanEdrA2dp(pBtCoexist); */ break; case BT_8723B_1ANT_COEX_ALGO_PANEDR_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = PAN(EDR)+HID.\n")); /* halbtc8723b1ant_ActionPanEdrHid(pBtCoexist); */ break; case BT_8723B_1ANT_COEX_ALGO_HID_A2DP_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = HID+A2DP+PAN.\n")); /* halbtc8723b1ant_ActionHidA2dpPanEdr(pBtCoexist); */ break; case BT_8723B_1ANT_COEX_ALGO_HID_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = HID+A2DP.\n")); /* halbtc8723b1ant_ActionHidA2dp(pBtCoexist); */ break; default: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = coexist All Off!!\n")); break; } pCoexDm->preAlgorithm = pCoexDm->curAlgorithm; @@ -2454,27 +2001,19 @@ static void halbtc8723b1ant_RunCoexistMechanism(struct btc_coexist *pBtCoexist) u32 wifiLinkStatus = 0; u32 numOfWifiLink = 0; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], RunCoexistMechanism() ===>\n")); - - if (pBtCoexist->bManualControl) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], RunCoexistMechanism(), return for Manual CTRL <===\n")); + if (pBtCoexist->bManualControl) return; - } - if (pBtCoexist->bStopCoexDm) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], RunCoexistMechanism(), return for Stop Coex DM <===\n")); + if (pBtCoexist->bStopCoexDm) return; - } - if (pCoexSta->bUnderIps) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], wifi is under IPS !!!\n")); + if (pCoexSta->bUnderIps) return; - } if ( - (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == pCoexDm->btStatus) || - (BT_8723B_1ANT_BT_STATUS_SCO_BUSY == pCoexDm->btStatus) || - (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == pCoexDm->btStatus) + (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) || + (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_SCO_BUSY) || + (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY) ){ bIncreaseScanDevNum = true; } @@ -2498,26 +2037,12 @@ static void halbtc8723b1ant_RunCoexistMechanism(struct btc_coexist *pBtCoexist) numOfWifiLink = wifiLinkStatus >> 16; if ((numOfWifiLink >= 2) || (wifiLinkStatus & WIFI_P2P_GO_CONNECTED)) { - BTC_PRINT( - BTC_MSG_INTERFACE, - INTF_NOTIFY, - ( - "############# [BTCoex], Multi-Port numOfWifiLink = %d, wifiLinkStatus = 0x%x\n", - numOfWifiLink, - wifiLinkStatus - ) - ); halbtc8723b1ant_LimitedTx(pBtCoexist, NORMAL_EXEC, 0, 0, 0, 0); halbtc8723b1ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, bBtCtrlAggBufSize, aggBufSize); - if ((pBtLinkInfo->bA2dpExist) && (pCoexSta->bC2hBtInquiryPage)) { - BTC_PRINT( - BTC_MSG_INTERFACE, - INTF_NOTIFY, - ("############# [BTCoex], BT Is Inquirying\n") - ); + if ((pBtLinkInfo->bA2dpExist) && (pCoexSta->bC2hBtInquiryPage)) halbtc8723b1ant_ActionBtInquiry(pBtCoexist); - } else + else halbtc8723b1ant_ActionWifiMultiPort(pBtCoexist); return; @@ -2544,11 +2069,6 @@ static void halbtc8723b1ant_RunCoexistMechanism(struct btc_coexist *pBtCoexist) pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn); if (pCoexSta->bC2hBtInquiryPage) { - BTC_PRINT( - BTC_MSG_INTERFACE, - INTF_NOTIFY, - ("############# [BTCoex], BT Is Inquirying\n") - ); halbtc8723b1ant_ActionBtInquiry(pBtCoexist); return; } else if (bBtHsOn) { @@ -2560,16 +2080,14 @@ static void halbtc8723b1ant_RunCoexistMechanism(struct btc_coexist *pBtCoexist) if (!bWifiConnected) { bool bScan = false, bLink = false, bRoam = false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], wifi is non connected-idle !!!\n")); - pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_SCAN, &bScan); pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_LINK, &bLink); pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_ROAM, &bRoam); if (bScan || bLink || bRoam) { - if (bScan) + if (bScan) halbtc8723b1ant_ActionWifiNotConnectedScan(pBtCoexist); - else + else halbtc8723b1ant_ActionWifiNotConnectedAssoAuth(pBtCoexist); } else halbtc8723b1ant_ActionWifiNotConnected(pBtCoexist); @@ -2596,15 +2114,6 @@ static void halbtc8723b1ant_InitHwConfig( bool bWifiOnly ) { - u32 u4Tmp = 0;/* fwVer; */ - u8 u1Tmpa = 0, u1Tmpb = 0; - - BTC_PRINT( - BTC_MSG_INTERFACE, - INTF_INIT, - ("[BTCoex], 1Ant Init HW Config!!\n") - ); - pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x550, 0x8, 0x1); /* enable TBTT nterrupt */ /* 0x790[5:0]= 0x5 */ @@ -2624,20 +2133,9 @@ static void halbtc8723b1ant_InitHwConfig( /* PTA parameter */ halbtc8723b1ant_CoexTableWithType(pBtCoexist, FORCE_EXEC, 0); - u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x948); - u1Tmpa = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x765); - u1Tmpb = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x67); - - BTC_PRINT( - BTC_MSG_INTERFACE, - INTF_NOTIFY, - ( - "############# [BTCoex], 0x948 = 0x%x, 0x765 = 0x%x, 0x67 = 0x%x\n", - u4Tmp, - u1Tmpa, - u1Tmpb - ) - ); + pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x948); + pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x765); + pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x67); } /* */ @@ -2666,9 +2164,9 @@ void EXhalbtc8723b1ant_PowerOnSetting(struct btc_coexist *pBtCoexist) /* */ /* S0 or S1 setting and Local register setting(By the setting fw can get ant number, S0/S1, ... info) */ /* Local setting bit define */ - /* BIT0: "0" for no antenna inverse; "1" for antenna inverse */ - /* BIT1: "0" for internal switch; "1" for external switch */ - /* BIT2: "0" for one antenna; "1" for two antenna */ + /* BIT0: "0" for no antenna inverse; "1" for antenna inverse */ + /* BIT1: "0" for internal switch; "1" for external switch */ + /* BIT2: "0" for one antenna; "1" for two antenna */ /* NOTE: here default all internal switch and 1-antenna ==> BIT1 = 0 and BIT2 = 0 */ if (pBtCoexist->chipInterface == BTC_INTF_USB) { /* fixed at S0 for USB interface */ @@ -2705,12 +2203,6 @@ void EXhalbtc8723b1ant_InitHwConfig(struct btc_coexist *pBtCoexist, bool bWifiOn void EXhalbtc8723b1ant_InitCoexDm(struct btc_coexist *pBtCoexist) { - BTC_PRINT( - BTC_MSG_INTERFACE, - INTF_INIT, - ("[BTCoex], Coex Mechanism Init!!\n") - ); - pBtCoexist->bStopCoexDm = false; halbtc8723b1ant_InitCoexDm(pBtCoexist); @@ -2730,7 +2222,6 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) bool bRoam = false; bool bScan = false; bool bLink = false; - bool bWifiUnder5G = false; bool bWifiUnderBMode = false; bool bBtHsOn = false; bool bWifiBusy = false; @@ -2778,7 +2269,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = %d/ %d/ %d", "Ant PG Num/ Ant Mech/ Ant Pos:", \ + "\r\n %-35s = %d/ %d/ %d", "Ant PG Num/ Ant Mech/ Ant Pos:", pBoardInfo->pgAntNum, pBoardInfo->btdmAntNum, pBoardInfo->btdmAntPos @@ -2788,7 +2279,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = %s / %d", "BT stack/ hci ext ver", \ + "\r\n %-35s = %s / %d", "BT stack/ hci ext ver", ((pStackInfo->bProfileNotified) ? "Yes" : "No"), pStackInfo->hciVersion ); @@ -2799,7 +2290,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = %d_%x/ 0x%x/ 0x%x(%d)", "CoexVer/ FwVer/ PatchVer", \ + "\r\n %-35s = %d_%x/ 0x%x/ 0x%x(%d)", "CoexVer/ FwVer/ PatchVer", GLCoexVerDate8723b1Ant, GLCoexVer8723b1Ant, fwVer, @@ -2814,7 +2305,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = %d / %d(%d)", "Dot11 channel / HsChnl(HsMode)", \ + "\r\n %-35s = %d / %d(%d)", "Dot11 channel / HsChnl(HsMode)", wifiDot11Chnl, wifiHsChnl, bBtHsOn @@ -2824,7 +2315,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = %02x %02x %02x ", "H2C Wifi inform bt chnl Info", \ + "\r\n %-35s = %02x %02x %02x ", "H2C Wifi inform bt chnl Info", pCoexDm->wifiChnlInfo[0], pCoexDm->wifiChnlInfo[1], pCoexDm->wifiChnlInfo[2] @@ -2836,7 +2327,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = %d/ %d", "Wifi rssi/ HS rssi", \ + "\r\n %-35s = %d/ %d", "Wifi rssi/ HS rssi", wifiRssi - 100, btHsRssi - 100 ); CL_PRINTF(cliBuf); @@ -2847,12 +2338,11 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = %d/ %d/ %d/ %s", "Wifi bLink/ bRoam/ bScan/ bHi-Pri", \ + "\r\n %-35s = %d/ %d/ %d/ %s", "Wifi bLink/ bRoam/ bScan/ bHi-Pri", bLink, bRoam, bScan, ((pCoexSta->bWiFiIsHighPriTask) ? "1" : "0") ); CL_PRINTF(cliBuf); - pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_UNDER_5G, &bWifiUnder5G); pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw); pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy); pBtCoexist->fBtcGet( @@ -2865,10 +2355,10 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = %s / %s/ %s/ AP =%d/ %s ", "Wifi status", \ - (bWifiUnder5G ? "5G" : "2.4G"), - ((bWifiUnderBMode) ? "11b" : ((BTC_WIFI_BW_LEGACY == wifiBw) ? "11bg" : (((BTC_WIFI_BW_HT40 == wifiBw) ? "HT40" : "HT20")))), - ((!bWifiBusy) ? "idle" : ((BTC_WIFI_TRAFFIC_TX == wifiTrafficDir) ? "uplink" : "downlink")), + "\r\n %-35s = %s / %s/ %s/ AP =%d/ %s ", "Wifi status", + ("2.4G"), + ((bWifiUnderBMode) ? "11b" : ((wifiBw == BTC_WIFI_BW_LEGACY) ? "11bg" : (((wifiBw == BTC_WIFI_BW_HT40) ? "HT40" : "HT20")))), + ((!bWifiBusy) ? "idle" : ((wifiTrafficDir == BTC_WIFI_TRAFFIC_TX) ? "uplink" : "downlink")), pCoexSta->nScanAPNum, (pCoexSta->bCCKLock) ? "Lock" : "noLock" ); @@ -2880,7 +2370,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = %d/ %d/ %d/ %d/ %d", "sta/vwifi/hs/p2pGo/p2pGc", \ + "\r\n %-35s = %d/ %d/ %d/ %d/ %d", "sta/vwifi/hs/p2pGo/p2pGc", ((wifiLinkStatus & WIFI_STA_CONNECTED) ? 1 : 0), ((wifiLinkStatus & WIFI_AP_CONNECTED) ? 1 : 0), ((wifiLinkStatus & WIFI_HS_CONNECTED) ? 1 : 0), @@ -2894,9 +2384,9 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = [%s/ %d/ %d/ %d] ", "BT [status/ rssi/ retryCnt/ popCnt]", \ - ((pBtCoexist->btInfo.bBtDisabled) ? ("disabled") : ((pCoexSta->bC2hBtInquiryPage) ? ("inquiry/page scan") : ((BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE == pCoexDm->btStatus) ? "non-connected idle" : - ((BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == pCoexDm->btStatus) ? "connected-idle" : "busy")))), + "\r\n %-35s = [%s/ %d/ %d/ %d] ", "BT [status/ rssi/ retryCnt/ popCnt]", + ((pBtCoexist->btInfo.bBtDisabled) ? ("disabled") : ((pCoexSta->bC2hBtInquiryPage) ? ("inquiry/page scan") : ((pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE) ? "non-connected idle" : + ((pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE) ? "connected-idle" : "busy")))), pCoexSta->btRssi, pCoexSta->btRetryCnt, pCoexSta->popEventCnt ); CL_PRINTF(cliBuf); @@ -2910,7 +2400,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = %d / %d / %d / %d", "SCO/HID/PAN/A2DP", \ + "\r\n %-35s = %d / %d / %d / %d", "SCO/HID/PAN/A2DP", pBtLinkInfo->bScoExist, pBtLinkInfo->bHidExist, pBtLinkInfo->bPanExist, @@ -2921,8 +2411,8 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) if (pStackInfo->bProfileNotified) { pBtCoexist->fBtcDispDbgMsg(pBtCoexist, BTC_DBG_DISP_BT_LINK_INFO); } else { - CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s", "BT Role", \ - (pBtLinkInfo->bSlaveRole) ? "Slave" : "Master"); + CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s", "BT Role", + (pBtLinkInfo->bSlaveRole) ? "Slave" : "Master"); CL_PRINTF(cliBuf); } @@ -2931,7 +2421,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = %s", "BT Info A2DP rate", \ + "\r\n %-35s = %s", "BT Info A2DP rate", (btInfoExt & BIT0) ? "Basic rate" : "EDR rate" ); CL_PRINTF(cliBuf); @@ -2941,7 +2431,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = %02x %02x %02x %02x %02x %02x %02x(%d)", GLBtInfoSrc8723b1Ant[i], \ + "\r\n %-35s = %02x %02x %02x %02x %02x %02x %02x(%d)", GLBtInfoSrc8723b1Ant[i], pCoexSta->btInfoC2h[i][0], pCoexSta->btInfoC2h[i][1], pCoexSta->btInfoC2h[i][2], pCoexSta->btInfoC2h[i][3], pCoexSta->btInfoC2h[i][4], pCoexSta->btInfoC2h[i][5], @@ -2953,7 +2443,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = %s/%s, (0x%x/0x%x)", "PS state, IPS/LPS, (lps/rpwm)", \ + "\r\n %-35s = %s/%s, (0x%x/0x%x)", "PS state, IPS/LPS, (lps/rpwm)", (pCoexSta->bUnderIps ? "IPS ON" : "IPS OFF"), (pCoexSta->bUnderLps ? "LPS ON" : "LPS OFF"), pBtCoexist->btInfo.lpsVal, @@ -2974,7 +2464,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = %d", "SM[LowPenaltyRA]", \ + "\r\n %-35s = %d", "SM[LowPenaltyRA]", pCoexDm->bCurLowPenaltyRa ); CL_PRINTF(cliBuf); @@ -2982,7 +2472,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = %s/ %s/ %d ", "DelBA/ BtCtrlAgg/ AggSize", \ + "\r\n %-35s = %s/ %s/ %d ", "DelBA/ BtCtrlAgg/ AggSize", (pBtCoexist->btInfo.bRejectAggPkt ? "Yes" : "No"), (pBtCoexist->btInfo.bBtCtrlAggBufSize ? "Yes" : "No"), pBtCoexist->btInfo.aggBufSize @@ -2991,7 +2481,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = 0x%x ", "Rate Mask", \ + "\r\n %-35s = 0x%x ", "Rate Mask", pBtCoexist->btInfo.raMask ); CL_PRINTF(cliBuf); @@ -3001,41 +2491,35 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_PRINTF(cliBuf); psTdmaCase = pCoexDm->curPsTdma; - CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %02x %02x %02x %02x %02x case-%d (auto:%d)", "PS TDMA", \ - pCoexDm->psTdmaPara[0], pCoexDm->psTdmaPara[1], - pCoexDm->psTdmaPara[2], pCoexDm->psTdmaPara[3], - pCoexDm->psTdmaPara[4], psTdmaCase, pCoexDm->bAutoTdmaAdjust); - CL_PRINTF(cliBuf); - - CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d", "Coex Table Type", \ - pCoexSta->nCoexTableType); + CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %02x %02x %02x %02x %02x case-%d (auto:%d)", "PS TDMA", + pCoexDm->psTdmaPara[0], pCoexDm->psTdmaPara[1], + pCoexDm->psTdmaPara[2], pCoexDm->psTdmaPara[3], + pCoexDm->psTdmaPara[4], psTdmaCase, pCoexDm->bAutoTdmaAdjust); CL_PRINTF(cliBuf); - CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d", "IgnWlanAct", \ - pCoexDm->bCurIgnoreWlanAct); + CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d", "Coex Table Type", + pCoexSta->nCoexTableType); CL_PRINTF(cliBuf); - /* - CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x ", "Latest error condition(should be 0)", \ - pCoexDm->errorCondition); + CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d", "IgnWlanAct", + pCoexDm->bCurIgnoreWlanAct); CL_PRINTF(cliBuf); - */ } /* Hw setting */ CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Hw setting]============"); CL_PRINTF(cliBuf); - CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", "backup ARFR1/ARFR2/RL/AMaxTime", \ - pCoexDm->backupArfrCnt1, pCoexDm->backupArfrCnt2, pCoexDm->backupRetryLimit, pCoexDm->backupAmpduMaxTime); + CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", "backup ARFR1/ARFR2/RL/AMaxTime", + pCoexDm->backupArfrCnt1, pCoexDm->backupArfrCnt2, pCoexDm->backupRetryLimit, pCoexDm->backupAmpduMaxTime); CL_PRINTF(cliBuf); u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x430); u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x434); u2Tmp[0] = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0x42a); u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x456); - CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", "0x430/0x434/0x42a/0x456", \ - u4Tmp[0], u4Tmp[1], u2Tmp[0], u1Tmp[0]); + CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", "0x430/0x434/0x42a/0x456", + u4Tmp[0], u4Tmp[1], u2Tmp[0], u1Tmp[0]); CL_PRINTF(cliBuf); u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x778); @@ -3043,7 +2527,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x880); CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x778/0x6cc/0x880[29:25]", \ + "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x778/0x6cc/0x880[29:25]", u1Tmp[0], u4Tmp[0], (u4Tmp[1] & 0x3e000000) >> 25 ); CL_PRINTF(cliBuf); @@ -3055,7 +2539,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0x948/ 0x67[5] / 0x764 / 0x76e", \ + "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0x948/ 0x67[5] / 0x764 / 0x76e", u4Tmp[0], ((u1Tmp[0] & 0x20) >> 5), (u4Tmp[1] & 0xffff), u1Tmp[1] ); CL_PRINTF(cliBuf); @@ -3066,7 +2550,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x92c[1:0]/ 0x930[7:0]/0x944[1:0]", \ + "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x92c[1:0]/ 0x930[7:0]/0x944[1:0]", u4Tmp[0] & 0x3, u4Tmp[1] & 0xff, u4Tmp[2] & 0x3 ); CL_PRINTF(cliBuf); @@ -3078,7 +2562,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0x38[11]/0x40/0x4c[24:23]/0x64[0]", \ + "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0x38[11]/0x40/0x4c[24:23]/0x64[0]", ((u1Tmp[0] & 0x8) >> 3), u1Tmp[1], ((u4Tmp[0] & 0x01800000) >> 23), @@ -3091,7 +2575,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = 0x%x/ 0x%x", "0x550(bcn ctrl)/0x522", \ + "\r\n %-35s = 0x%x/ 0x%x", "0x550(bcn ctrl)/0x522", u4Tmp[0], u1Tmp[0] ); CL_PRINTF(cliBuf); @@ -3101,7 +2585,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = 0x%x/ 0x%x", "0xc50(dig)/0x49c(null-drop)", \ + "\r\n %-35s = 0x%x/ 0x%x", "0xc50(dig)/0x49c(null-drop)", u4Tmp[0] & 0xff, u1Tmp[0] ); CL_PRINTF(cliBuf); @@ -3117,14 +2601,14 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) faOfdm = ((u4Tmp[0] & 0xffff0000) >> 16) + ((u4Tmp[1] & 0xffff0000) >> 16) + - (u4Tmp[1] & 0xffff) + (u4Tmp[2] & 0xffff) + \ + (u4Tmp[1] & 0xffff) + (u4Tmp[2] & 0xffff) + ((u4Tmp[3] & 0xffff0000) >> 16) + (u4Tmp[3] & 0xffff); faCck = (u1Tmp[0] << 8) + u1Tmp[1]; CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "OFDM-CCA/OFDM-FA/CCK-FA", \ + "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "OFDM-CCA/OFDM-FA/CCK-FA", u4Tmp[0] & 0xffff, faOfdm, faCck ); CL_PRINTF(cliBuf); @@ -3133,7 +2617,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = %d/ %d/ %d/ %d", "CRC_OK CCK/11g/11n/11n-Agg", \ + "\r\n %-35s = %d/ %d/ %d/ %d", "CRC_OK CCK/11g/11n/11n-Agg", pCoexSta->nCRCOK_CCK, pCoexSta->nCRCOK_11g, pCoexSta->nCRCOK_11n, @@ -3144,7 +2628,7 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = %d/ %d/ %d/ %d", "CRC_Err CCK/11g/11n/11n-Agg", \ + "\r\n %-35s = %d/ %d/ %d/ %d", "CRC_Err CCK/11g/11n/11n-Agg", pCoexSta->nCRCErr_CCK, pCoexSta->nCRCErr_11g, pCoexSta->nCRCErr_11n, @@ -3158,21 +2642,21 @@ void EXhalbtc8723b1ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x6c0/0x6c4/0x6c8(coexTable)", \ + "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x6c0/0x6c4/0x6c8(coexTable)", u4Tmp[0], u4Tmp[1], u4Tmp[2]); CL_PRINTF(cliBuf); CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = %d/ %d", "0x770(high-pri rx/tx)", \ + "\r\n %-35s = %d/ %d", "0x770(high-pri rx/tx)", pCoexSta->highPriorityRx, pCoexSta->highPriorityTx ); CL_PRINTF(cliBuf); CL_SPRINTF( cliBuf, BT_TMP_BUF_SIZE, - "\r\n %-35s = %d/ %d", "0x774(low-pri rx/tx)", \ + "\r\n %-35s = %d/ %d", "0x774(low-pri rx/tx)", pCoexSta->lowPriorityRx, pCoexSta->lowPriorityTx ); CL_PRINTF(cliBuf); @@ -3186,19 +2670,13 @@ void EXhalbtc8723b1ant_IpsNotify(struct btc_coexist *pBtCoexist, u8 type) if (pBtCoexist->bManualControl || pBtCoexist->bStopCoexDm) return; - if (BTC_IPS_ENTER == type) { - BTC_PRINT( - BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], IPS ENTER notify\n") - ); + if (type == BTC_IPS_ENTER) { pCoexSta->bUnderIps = true; halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 0); halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0); halbtc8723b1ant_SetAntPath(pBtCoexist, BTC_ANT_PATH_BT, false, true); - } else if (BTC_IPS_LEAVE == type) { - BTC_PRINT( - BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], IPS LEAVE notify\n") - ); + } else if (type == BTC_IPS_LEAVE) { pCoexSta->bUnderIps = false; halbtc8723b1ant_InitHwConfig(pBtCoexist, false, false); @@ -3212,17 +2690,10 @@ void EXhalbtc8723b1ant_LpsNotify(struct btc_coexist *pBtCoexist, u8 type) if (pBtCoexist->bManualControl || pBtCoexist->bStopCoexDm) return; - if (BTC_LPS_ENABLE == type) { - BTC_PRINT( - BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], LPS ENABLE notify\n") - ); + if (type == BTC_LPS_ENABLE) pCoexSta->bUnderLps = true; - } else if (BTC_LPS_DISABLE == type) { - BTC_PRINT( - BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], LPS DISABLE notify\n") - ); + else if (type == BTC_LPS_DISABLE) pCoexSta->bUnderLps = false; - } } void EXhalbtc8723b1ant_ScanNotify(struct btc_coexist *pBtCoexist, u8 type) @@ -3233,39 +2704,18 @@ void EXhalbtc8723b1ant_ScanNotify(struct btc_coexist *pBtCoexist, u8 type) bool bBtCtrlAggBufSize = false; u8 aggBufSize = 5; - u8 u1Tmpa, u1Tmpb; - u32 u4Tmp; - if (pBtCoexist->bManualControl || pBtCoexist->bStopCoexDm) return; - if (BTC_SCAN_START == type) { + if (type == BTC_SCAN_START) { pCoexSta->bWiFiIsHighPriTask = true; - BTC_PRINT( - BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], SCAN START notify\n") - ); halbtc8723b1ant_PsTdma(pBtCoexist, FORCE_EXEC, false, 8); /* Force antenna setup for no scan result issue */ - u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x948); - u1Tmpa = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x765); - u1Tmpb = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x67); - - - BTC_PRINT( - BTC_MSG_INTERFACE, - INTF_NOTIFY, - ( - "[BTCoex], 0x948 = 0x%x, 0x765 = 0x%x, 0x67 = 0x%x\n", - u4Tmp, - u1Tmpa, - u1Tmpb - ) - ); + pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x948); + pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x765); + pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x67); } else { pCoexSta->bWiFiIsHighPriTask = false; - BTC_PRINT( - BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], SCAN FINISH notify\n") - ); pBtCoexist->fBtcGet( pBtCoexist, BTC_GET_U1_AP_NUM, &pCoexSta->nScanAPNum @@ -3300,14 +2750,12 @@ void EXhalbtc8723b1ant_ScanNotify(struct btc_coexist *pBtCoexist, u8 type) return; } - if (BTC_SCAN_START == type) { - /* BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], SCAN START notify\n")); */ + if (type == BTC_SCAN_START) { if (!bWifiConnected) /* non-connected scan */ halbtc8723b1ant_ActionWifiNotConnectedScan(pBtCoexist); else /* wifi is connected */ halbtc8723b1ant_ActionWifiConnectedScan(pBtCoexist); - } else if (BTC_SCAN_FINISH == type) { - /* BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], SCAN FINISH notify\n")); */ + } else if (type == BTC_SCAN_FINISH) { if (!bWifiConnected) /* non-connected scan */ halbtc8723b1ant_ActionWifiNotConnected(pBtCoexist); else @@ -3330,13 +2778,11 @@ void EXhalbtc8723b1ant_ConnectNotify(struct btc_coexist *pBtCoexist, u8 type) ) return; - if (BTC_ASSOCIATE_START == type) { + if (type == BTC_ASSOCIATE_START) { pCoexSta->bWiFiIsHighPriTask = true; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], CONNECT START notify\n")); pCoexDm->nArpCnt = 0; } else { pCoexSta->bWiFiIsHighPriTask = false; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], CONNECT FINISH notify\n")); /* pCoexDm->nArpCnt = 0; */ } @@ -3358,12 +2804,9 @@ void EXhalbtc8723b1ant_ConnectNotify(struct btc_coexist *pBtCoexist, u8 type) return; } - if (BTC_ASSOCIATE_START == type) { - /* BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], CONNECT START notify\n")); */ + if (type == BTC_ASSOCIATE_START) { halbtc8723b1ant_ActionWifiNotConnectedAssoAuth(pBtCoexist); - } else if (BTC_ASSOCIATE_FINISH == type) { - /* BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], CONNECT FINISH notify\n")); */ - + } else if (type == BTC_ASSOCIATE_FINISH) { pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected); if (!bWifiConnected) /* non-connected scan */ halbtc8723b1ant_ActionWifiNotConnected(pBtCoexist); @@ -3386,9 +2829,7 @@ void EXhalbtc8723b1ant_MediaStatusNotify(struct btc_coexist *pBtCoexist, u8 type ) return; - if (BTC_MEDIA_CONNECT == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], MEDIA connect notify\n")); - + if (type == BTC_MEDIA_CONNECT) { pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_UNDER_B_MODE, &bWifiUnderBMode); /* Set CCK Tx/Rx high Pri except 11b mode */ @@ -3405,7 +2846,6 @@ void EXhalbtc8723b1ant_MediaStatusNotify(struct btc_coexist *pBtCoexist, u8 type pCoexDm->backupRetryLimit = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0x42a); pCoexDm->backupAmpduMaxTime = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x456); } else { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], MEDIA disconnect notify\n")); pCoexDm->nArpCnt = 0; pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x6cd, 0x0); /* CCK Tx */ @@ -3414,13 +2854,13 @@ void EXhalbtc8723b1ant_MediaStatusNotify(struct btc_coexist *pBtCoexist, u8 type /* only 2.4G we need to inform bt the chnl mask */ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_WIFI_CENTRAL_CHNL, &wifiCentralChnl); - if ((BTC_MEDIA_CONNECT == type) && (wifiCentralChnl <= 14)) { + if ((type == BTC_MEDIA_CONNECT) && (wifiCentralChnl <= 14)) { /* H2C_Parameter[0] = 0x1; */ H2C_Parameter[0] = 0x0; H2C_Parameter[1] = wifiCentralChnl; pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw); - if (BTC_WIFI_BW_HT40 == wifiBw) + if (wifiBw == BTC_WIFI_BW_HT40) H2C_Parameter[2] = 0x30; else H2C_Parameter[2] = 0x20; @@ -3430,15 +2870,6 @@ void EXhalbtc8723b1ant_MediaStatusNotify(struct btc_coexist *pBtCoexist, u8 type pCoexDm->wifiChnlInfo[1] = H2C_Parameter[1]; pCoexDm->wifiChnlInfo[2] = H2C_Parameter[2]; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_EXEC, - ( - "[BTCoex], FW write 0x66 = 0x%x\n", - H2C_Parameter[0] << 16 | H2C_Parameter[1] << 8 | H2C_Parameter[2] - ) - ); - pBtCoexist->fBtcFillH2c(pBtCoexist, 0x66, 3, H2C_Parameter); } @@ -3458,23 +2889,12 @@ void EXhalbtc8723b1ant_SpecialPacketNotify(struct btc_coexist *pBtCoexist, u8 ty return; if ( - BTC_PACKET_DHCP == type || - BTC_PACKET_EAPOL == type || - BTC_PACKET_ARP == type + type == BTC_PACKET_DHCP || + type == BTC_PACKET_EAPOL || + type == BTC_PACKET_ARP ) { - if (BTC_PACKET_ARP == type) { - BTC_PRINT( - BTC_MSG_INTERFACE, - INTF_NOTIFY, - ("[BTCoex], special Packet ARP notify\n") - ); - + if (type == BTC_PACKET_ARP) { pCoexDm->nArpCnt++; - BTC_PRINT( - BTC_MSG_INTERFACE, - INTF_NOTIFY, - ("[BTCoex], ARP Packet Count = %d\n", pCoexDm->nArpCnt) - ); if (pCoexDm->nArpCnt >= 10) /* if APR PKT > 10 after connect, do not go to ActionWifiConnectedSpecialPacket(pBtCoexist) */ pCoexSta->bWiFiIsHighPriTask = false; @@ -3482,19 +2902,9 @@ void EXhalbtc8723b1ant_SpecialPacketNotify(struct btc_coexist *pBtCoexist, u8 ty pCoexSta->bWiFiIsHighPriTask = true; } else { pCoexSta->bWiFiIsHighPriTask = true; - BTC_PRINT( - BTC_MSG_INTERFACE, - INTF_NOTIFY, - ("[BTCoex], special Packet DHCP or EAPOL notify\n") - ); } } else { pCoexSta->bWiFiIsHighPriTask = false; - BTC_PRINT( - BTC_MSG_INTERFACE, - INTF_NOTIFY, - ("[BTCoex], special Packet [Type = %d] notify\n", type) - ); } pCoexSta->specialPktPeriodCnt = 0; @@ -3523,9 +2933,9 @@ void EXhalbtc8723b1ant_SpecialPacketNotify(struct btc_coexist *pBtCoexist, u8 ty } if ( - BTC_PACKET_DHCP == type || - BTC_PACKET_EAPOL == type || - ((BTC_PACKET_ARP == type) && (pCoexSta->bWiFiIsHighPriTask)) + type == BTC_PACKET_DHCP || + type == BTC_PACKET_EAPOL || + ((type == BTC_PACKET_ARP) && (pCoexSta->bWiFiIsHighPriTask)) ) halbtc8723b1ant_ActionWifiConnectedSpecialPacket(pBtCoexist); } @@ -3546,26 +2956,13 @@ void EXhalbtc8723b1ant_BtInfoNotify( rspSource = BT_INFO_SRC_8723B_1ANT_WIFI_FW; pCoexSta->btInfoC2hCnt[rspSource]++; - BTC_PRINT( - BTC_MSG_INTERFACE, - INTF_NOTIFY, - ("[BTCoex], Bt info[%d], length =%d, hex data =[", - rspSource, - length) - ); for (i = 0; i < length; i++) { pCoexSta->btInfoC2h[rspSource][i] = tmpBuf[i]; if (i == 1) btInfo = tmpBuf[i]; - if (i == length - 1) - BTC_PRINT( - BTC_MSG_INTERFACE, INTF_NOTIFY, ("0x%02x]\n", tmpBuf[i]) - ); - else - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("0x%02x, ", tmpBuf[i])); } - if (BT_INFO_SRC_8723B_1ANT_WIFI_FW != rspSource) { + if (rspSource != BT_INFO_SRC_8723B_1ANT_WIFI_FW) { pCoexSta->btRetryCnt = pCoexSta->btInfoC2h[rspSource][2] & 0xf; if (pCoexSta->btRetryCnt >= 1) @@ -3586,18 +2983,12 @@ void EXhalbtc8723b1ant_BtInfoNotify( if (!pCoexSta->bBtTxRxMask) { /* BT into is responded by BT FW and BT RF REG 0x3C != 0x15 => Need to switch BT TRx Mask */ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Switch BT TRx Mask since BT RF REG 0x3C != 0x15\n")); pBtCoexist->fBtcSetBtReg(pBtCoexist, BTC_BT_REG_RF, 0x3c, 0x15); } /* Here we need to resend some wifi info to BT */ /* because bt is reset and loss of the info. */ if (pCoexSta->btInfoExt & BIT1) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT ext info bit1 check, send wifi BW&Chnl to BT!!\n") - ); pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected); if (bWifiConnected) EXhalbtc8723b1ant_MediaStatusNotify(pBtCoexist, BTC_MEDIA_CONNECT); @@ -3606,14 +2997,8 @@ void EXhalbtc8723b1ant_BtInfoNotify( } if (pCoexSta->btInfoExt & BIT3) { - if (!pBtCoexist->bManualControl && !pBtCoexist->bStopCoexDm) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n") - ); + if (!pBtCoexist->bManualControl && !pBtCoexist->bStopCoexDm) halbtc8723b1ant_IgnoreWlanAct(pBtCoexist, FORCE_EXEC, false); - } } else { /* BT already NOT ignore Wlan active, do nothing here. */ } @@ -3661,32 +3046,27 @@ void EXhalbtc8723b1ant_BtInfoNotify( if (!(btInfo & BT_INFO_8723B_1ANT_B_CONNECTION)) { pCoexDm->btStatus = BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT Non-Connected idle!!!\n")); } else if (btInfo == BT_INFO_8723B_1ANT_B_CONNECTION) { /* connection exists but no busy */ pCoexDm->btStatus = BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n")); } else if ( (btInfo & BT_INFO_8723B_1ANT_B_SCO_ESCO) || (btInfo & BT_INFO_8723B_1ANT_B_SCO_BUSY) ) { pCoexDm->btStatus = BT_8723B_1ANT_BT_STATUS_SCO_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT SCO busy!!!\n")); } else if (btInfo & BT_INFO_8723B_1ANT_B_ACL_BUSY) { - if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY != pCoexDm->btStatus) + if (pCoexDm->btStatus != BT_8723B_1ANT_BT_STATUS_ACL_BUSY) pCoexDm->bAutoTdmaAdjust = false; pCoexDm->btStatus = BT_8723B_1ANT_BT_STATUS_ACL_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT ACL busy!!!\n")); } else { pCoexDm->btStatus = BT_8723B_1ANT_BT_STATUS_MAX; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT Non-Defined state!!!\n")); } if ( - (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == pCoexDm->btStatus) || - (BT_8723B_1ANT_BT_STATUS_SCO_BUSY == pCoexDm->btStatus) || - (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == pCoexDm->btStatus) + (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) || + (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_SCO_BUSY) || + (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY) ) bBtBusy = true; else @@ -3698,8 +3078,6 @@ void EXhalbtc8723b1ant_BtInfoNotify( void EXhalbtc8723b1ant_HaltNotify(struct btc_coexist *pBtCoexist) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Halt notify\n")); - halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0); halbtc8723b1ant_PsTdma(pBtCoexist, FORCE_EXEC, false, 0); halbtc8723b1ant_SetAntPath(pBtCoexist, BTC_ANT_PATH_BT, false, true); @@ -3713,19 +3091,14 @@ void EXhalbtc8723b1ant_HaltNotify(struct btc_coexist *pBtCoexist) void EXhalbtc8723b1ant_PnpNotify(struct btc_coexist *pBtCoexist, u8 pnpState) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Pnp notify\n")); - - if (BTC_WIFI_PNP_SLEEP == pnpState) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Pnp notify to SLEEP\n")); - + if (pnpState == BTC_WIFI_PNP_SLEEP) { halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0); halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 0); halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2); halbtc8723b1ant_SetAntPath(pBtCoexist, BTC_ANT_PATH_BT, false, true); pBtCoexist->bStopCoexDm = true; - } else if (BTC_WIFI_PNP_WAKE_UP == pnpState) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Pnp notify to WAKE UP\n")); + } else if (pnpState == BTC_WIFI_PNP_WAKE_UP) { pBtCoexist->bStopCoexDm = false; halbtc8723b1ant_InitHwConfig(pBtCoexist, false, false); halbtc8723b1ant_InitCoexDm(pBtCoexist); @@ -3738,16 +3111,10 @@ void EXhalbtc8723b1ant_Periodical(struct btc_coexist *pBtCoexist) static u8 disVerInfoCnt; u32 fwVer = 0, btPatchVer = 0; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], ==========================Periodical ===========================\n")); - if (disVerInfoCnt <= 5) { disVerInfoCnt += 1; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], ****************************************************************\n")); pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_BT_PATCH_VER, &btPatchVer); pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_FW_VER, &fwVer); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", \ - GLCoexVerDate8723b1Ant, GLCoexVer8723b1Ant, fwVer, btPatchVer, btPatchVer)); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], ****************************************************************\n")); } halbtc8723b1ant_MonitorBtCtr(pBtCoexist); diff --git a/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.c b/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.c index 4b570ec75e67..84241619fb3a 100644 --- a/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.c +++ b/drivers/staging/rtl8723bs/hal/HalBtc8723b2Ant.c @@ -46,23 +46,18 @@ static u8 halbtc8723b2ant_BtRssiState( ) { if (btRssi >= (rssiThresh + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT)) { btRssiState = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state switch to High\n")); } else { btRssiState = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state stay at Low\n")); } } else { if (btRssi < rssiThresh) { btRssiState = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state switch to Low\n")); } else { btRssiState = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state stay at High\n")); } } } else if (levelNum == 3) { if (rssiThresh > rssiThresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi thresh error!!\n")); return pCoexSta->preBtRssiState; } @@ -72,10 +67,8 @@ static u8 halbtc8723b2ant_BtRssiState( ) { if (btRssi >= (rssiThresh + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT)) { btRssiState = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state switch to Medium\n")); } else { btRssiState = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state stay at Low\n")); } } else if ( (pCoexSta->preBtRssiState == BTC_RSSI_STATE_MEDIUM) || @@ -83,21 +76,16 @@ static u8 halbtc8723b2ant_BtRssiState( ) { if (btRssi >= (rssiThresh1 + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT)) { btRssiState = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state switch to High\n")); } else if (btRssi < rssiThresh) { btRssiState = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state switch to Low\n")); } else { btRssiState = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state stay at Medium\n")); } } else { if (btRssi < rssiThresh1) { btRssiState = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state switch to Medium\n")); } else { btRssiState = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state stay at High\n")); } } } @@ -127,23 +115,18 @@ static u8 halbtc8723b2ant_WifiRssiState( ) { if (wifiRssi >= (rssiThresh + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT)) { wifiRssiState = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state switch to High\n")); } else { wifiRssiState = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state stay at Low\n")); } } else { if (wifiRssi < rssiThresh) { wifiRssiState = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state switch to Low\n")); } else { wifiRssiState = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state stay at High\n")); } } } else if (levelNum == 3) { if (rssiThresh > rssiThresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI thresh error!!\n")); return pCoexSta->preWifiRssiState[index]; } @@ -153,10 +136,8 @@ static u8 halbtc8723b2ant_WifiRssiState( ) { if (wifiRssi >= (rssiThresh + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT)) { wifiRssiState = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state switch to Medium\n")); } else { wifiRssiState = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state stay at Low\n")); } } else if ( (pCoexSta->preWifiRssiState[index] == BTC_RSSI_STATE_MEDIUM) || @@ -164,21 +145,16 @@ static u8 halbtc8723b2ant_WifiRssiState( ) { if (wifiRssi >= (rssiThresh1 + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT)) { wifiRssiState = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state switch to High\n")); } else if (wifiRssi < rssiThresh) { wifiRssiState = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state switch to Low\n")); } else { wifiRssiState = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state stay at Medium\n")); } } else { if (wifiRssi < rssiThresh1) { wifiRssiState = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state switch to Medium\n")); } else { wifiRssiState = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state stay at High\n")); } } } @@ -233,31 +209,6 @@ static void halbtc8723b2ant_MonitorBtCtr(struct btc_coexist *pBtCoexist) pCoexSta->lowPriorityTx = regLPTx; pCoexSta->lowPriorityRx = regLPRx; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_BT_MONITOR, - ( - "[BTCoex], High Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n", - regHPTxRx, - regHPTx, - regHPTx, - regHPRx, - regHPRx - ) - ); - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_BT_MONITOR, - ( - "[BTCoex], Low Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n", - regLPTxRx, - regLPTx, - regLPTx, - regLPRx, - regLPRx - ) - ); - /* reset counter */ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0xc); } @@ -270,12 +221,6 @@ static void halbtc8723b2ant_QueryBtInfo(struct btc_coexist *pBtCoexist) H2C_Parameter[0] |= BIT0; /* trigger */ - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_EXEC, - ("[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", H2C_Parameter[0]) - ); - pBtCoexist->fBtcFillH2c(pBtCoexist, 0x61, 1, H2C_Parameter); } @@ -384,7 +329,6 @@ static u8 halbtc8723b2ant_ActionAlgorithm(struct btc_coexist *pBtCoexist) pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn); if (!pBtLinkInfo->bBtLinkExist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], No BT link exists!!!\n")); return algorithm; } @@ -402,21 +346,16 @@ static u8 halbtc8723b2ant_ActionAlgorithm(struct btc_coexist *pBtCoexist) if (numOfDiffProfile == 1) { if (pBtLinkInfo->bScoExist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], SCO only\n")); algorithm = BT_8723B_2ANT_COEX_ALGO_SCO; } else { if (pBtLinkInfo->bHidExist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], HID only\n")); algorithm = BT_8723B_2ANT_COEX_ALGO_HID; } else if (pBtLinkInfo->bA2dpExist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], A2DP only\n")); algorithm = BT_8723B_2ANT_COEX_ALGO_A2DP; } else if (pBtLinkInfo->bPanExist) { if (bBtHsOn) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], PAN(HS) only\n")); algorithm = BT_8723B_2ANT_COEX_ALGO_PANHS; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], PAN(EDR) only\n")); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR; } } @@ -424,17 +363,13 @@ static u8 halbtc8723b2ant_ActionAlgorithm(struct btc_coexist *pBtCoexist) } else if (numOfDiffProfile == 2) { if (pBtLinkInfo->bScoExist) { if (pBtLinkInfo->bHidExist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], SCO + HID\n")); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; } else if (pBtLinkInfo->bA2dpExist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], SCO + A2DP ==> SCO\n")); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; } else if (pBtLinkInfo->bPanExist) { if (bBtHsOn) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], SCO + PAN(HS)\n")); algorithm = BT_8723B_2ANT_COEX_ALGO_SCO; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], SCO + PAN(EDR)\n")); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; } } @@ -443,17 +378,14 @@ static u8 halbtc8723b2ant_ActionAlgorithm(struct btc_coexist *pBtCoexist) pBtLinkInfo->bHidExist && pBtLinkInfo->bA2dpExist ) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], HID + A2DP\n")); algorithm = BT_8723B_2ANT_COEX_ALGO_HID_A2DP; } else if ( pBtLinkInfo->bHidExist && pBtLinkInfo->bPanExist ) { if (bBtHsOn) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], HID + PAN(HS)\n")); algorithm = BT_8723B_2ANT_COEX_ALGO_HID; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], HID + PAN(EDR)\n")); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; } } else if ( @@ -461,10 +393,8 @@ static u8 halbtc8723b2ant_ActionAlgorithm(struct btc_coexist *pBtCoexist) pBtLinkInfo->bA2dpExist ) { if (bBtHsOn) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], A2DP + PAN(HS)\n")); algorithm = BT_8723B_2ANT_COEX_ALGO_A2DP_PANHS; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], A2DP + PAN(EDR)\n")); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_A2DP; } } @@ -475,42 +405,17 @@ static u8 halbtc8723b2ant_ActionAlgorithm(struct btc_coexist *pBtCoexist) pBtLinkInfo->bHidExist && pBtLinkInfo->bA2dpExist ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], SCO + HID + A2DP ==> HID\n") - ); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; } else if ( pBtLinkInfo->bHidExist && pBtLinkInfo->bPanExist ) { - if (bBtHsOn) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], SCO + HID + PAN(HS)\n") - ); - algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; - } else { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ("[BTCoex], SCO + HID + PAN(EDR)\n") - ); - algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; - } + algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; } else if ( pBtLinkInfo->bPanExist && pBtLinkInfo->bA2dpExist ) { - if (bBtHsOn) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], SCO + A2DP + PAN(HS)\n")); - algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], SCO + A2DP + PAN(EDR) ==> HID\n")); - algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; - } + algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; } } else { if ( @@ -519,10 +424,8 @@ static u8 halbtc8723b2ant_ActionAlgorithm(struct btc_coexist *pBtCoexist) pBtLinkInfo->bA2dpExist ) { if (bBtHsOn) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], HID + A2DP + PAN(HS)\n")); algorithm = BT_8723B_2ANT_COEX_ALGO_HID_A2DP; } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], HID + A2DP + PAN(EDR)\n")); algorithm = BT_8723B_2ANT_COEX_ALGO_HID_A2DP_PANEDR; } } @@ -535,10 +438,7 @@ static u8 halbtc8723b2ant_ActionAlgorithm(struct btc_coexist *pBtCoexist) pBtLinkInfo->bA2dpExist ) { if (bBtHsOn) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Error!!! SCO + HID + A2DP + PAN(HS)\n")); - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], SCO + HID + A2DP + PAN(EDR) ==>PAN(EDR)+HID\n")); algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; } } @@ -558,17 +458,6 @@ static void halbtc8723b2ant_SetFwDacSwingLevel( /* 0x18/ 0x10/ 0xc/ 0x8/ 0x4/ 0x6 */ H2C_Parameter[0] = dacSwingLvl; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_EXEC, - ("[BTCoex], Set Dac Swing Level = 0x%x\n", dacSwingLvl) - ); - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_EXEC, - ("[BTCoex], FW write 0x64 = 0x%x\n", H2C_Parameter[0]) - ); - pBtCoexist->fBtcFillH2c(pBtCoexist, 0x64, 1, H2C_Parameter); } @@ -580,16 +469,6 @@ static void halbtc8723b2ant_SetFwDecBtPwr( H2C_Parameter[0] = decBtPwrLvl; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_EXEC, - ( - "[BTCoex], decrease Bt Power level = %d, FW write 0x62 = 0x%x\n", - decBtPwrLvl, - H2C_Parameter[0] - ) - ); - pBtCoexist->fBtcFillH2c(pBtCoexist, 0x62, 1, H2C_Parameter); } @@ -597,28 +476,9 @@ static void halbtc8723b2ant_DecBtPwr( struct btc_coexist *pBtCoexist, bool bForceExec, u8 decBtPwrLvl ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW, - ( - "[BTCoex], %s Dec BT power level = %d\n", - (bForceExec ? "force to" : ""), - decBtPwrLvl - ) - ); pCoexDm->curBtDecPwrLvl = decBtPwrLvl; if (!bForceExec) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - ( - "[BTCoex], preBtDecPwrLvl =%d, curBtDecPwrLvl =%d\n", - pCoexDm->preBtDecPwrLvl, - pCoexDm->curBtDecPwrLvl - ) - ); - if (pCoexDm->preBtDecPwrLvl == pCoexDm->curBtDecPwrLvl) return; } @@ -631,28 +491,9 @@ static void halbtc8723b2ant_FwDacSwingLvl( struct btc_coexist *pBtCoexist, bool bForceExec, u8 fwDacSwingLvl ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW, - ( - "[BTCoex], %s set FW Dac Swing level = %d\n", - (bForceExec ? "force to" : ""), - fwDacSwingLvl - ) - ); pCoexDm->curFwDacSwingLvl = fwDacSwingLvl; if (!bForceExec) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - ( - "[BTCoex], preFwDacSwingLvl =%d, curFwDacSwingLvl =%d\n", - pCoexDm->preFwDacSwingLvl, - pCoexDm->curFwDacSwingLvl - ) - ); - if (pCoexDm->preFwDacSwingLvl == pCoexDm->curFwDacSwingLvl) return; } @@ -669,17 +510,11 @@ static void halbtc8723b2ant_SetSwRfRxLpfCorner( { if (bRxRfShrinkOn) { /* Shrink RF Rx LPF corner */ - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW_EXEC, - ("[BTCoex], Shrink RF Rx LPF corner!!\n") - ); pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1e, 0xfffff, 0xffffc); } else { /* Resume RF Rx LPF corner */ /* After initialized, we can use pCoexDm->btRf0x1eBackup */ if (pBtCoexist->bInitilized) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, ("[BTCoex], Resume RF Rx LPF corner!!\n")); pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1e, 0xfffff, pCoexDm->btRf0x1eBackup); } } @@ -689,28 +524,9 @@ static void halbtc8723b2ant_RfShrink( struct btc_coexist *pBtCoexist, bool bForceExec, bool bRxRfShrinkOn ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW, - ( - "[BTCoex], %s turn Rx RF Shrink = %s\n", - (bForceExec ? "force to" : ""), - (bRxRfShrinkOn ? "ON" : "OFF") - ) - ); pCoexDm->bCurRfRxLpfShrink = bRxRfShrinkOn; if (!bForceExec) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW_DETAIL, - ( - "[BTCoex], bPreRfRxLpfShrink =%d, bCurRfRxLpfShrink =%d\n", - pCoexDm->bPreRfRxLpfShrink, - pCoexDm->bCurRfRxLpfShrink - ) - ); - if (pCoexDm->bPreRfRxLpfShrink == pCoexDm->bCurRfRxLpfShrink) return; } @@ -735,15 +551,6 @@ static void halbtc8723b2ant_SetSwPenaltyTxRateAdaptive( H2C_Parameter[5] = 0xf9; /* MCS5 or OFDM36 */ } - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_EXEC, - ( - "[BTCoex], set WiFi Low-Penalty Retry: %s", - (bLowPenaltyRa ? "ON!!" : "OFF!!") - ) - ); - pBtCoexist->fBtcFillH2c(pBtCoexist, 0x69, 6, H2C_Parameter); } @@ -752,28 +559,9 @@ static void halbtc8723b2ant_LowPenaltyRa( ) { /* return; */ - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW, - ( - "[BTCoex], %s turn LowPenaltyRA = %s\n", - (bForceExec ? "force to" : ""), - (bLowPenaltyRa ? "ON" : "OFF") - ) - ); pCoexDm->bCurLowPenaltyRa = bLowPenaltyRa; if (!bForceExec) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW_DETAIL, - ( - "[BTCoex], bPreLowPenaltyRa =%d, bCurLowPenaltyRa =%d\n", - pCoexDm->bPreLowPenaltyRa, - pCoexDm->bCurLowPenaltyRa - ) - ); - if (pCoexDm->bPreLowPenaltyRa == pCoexDm->bCurLowPenaltyRa) return; } @@ -786,11 +574,6 @@ static void halbtc8723b2ant_SetDacSwingReg(struct btc_coexist *pBtCoexist, u32 l { u8 val = (u8)level; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW_EXEC, - ("[BTCoex], Write SwDacSwing = 0x%x\n", level) - ); pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x883, 0x3e, val); } @@ -812,32 +595,10 @@ static void halbtc8723b2ant_DacSwing( u32 dacSwingLvl ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW, - ( - "[BTCoex], %s turn DacSwing =%s, dacSwingLvl = 0x%x\n", - (bForceExec ? "force to" : ""), - (bDacSwingOn ? "ON" : "OFF"), - dacSwingLvl - ) - ); pCoexDm->bCurDacSwingOn = bDacSwingOn; pCoexDm->curDacSwingLvl = dacSwingLvl; if (!bForceExec) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW_DETAIL, - ( - "[BTCoex], bPreDacSwingOn =%d, preDacSwingLvl = 0x%x, bCurDacSwingOn =%d, curDacSwingLvl = 0x%x\n", - pCoexDm->bPreDacSwingOn, - pCoexDm->preDacSwingLvl, - pCoexDm->bCurDacSwingOn, - pCoexDm->curDacSwingLvl - ) - ); - if ((pCoexDm->bPreDacSwingOn == pCoexDm->bCurDacSwingOn) && (pCoexDm->preDacSwingLvl == pCoexDm->curDacSwingLvl)) return; @@ -857,7 +618,6 @@ static void halbtc8723b2ant_SetAgcTable( /* BB AGC Gain Table */ if (bAgcTableEn) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, ("[BTCoex], BB Agc Table On!\n")); pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0x6e1A0001); pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0x6d1B0001); pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0x6c1C0001); @@ -866,7 +626,6 @@ static void halbtc8723b2ant_SetAgcTable( pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0x691F0001); pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0x68200001); } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, ("[BTCoex], BB Agc Table Off!\n")); pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0xaa1A0001); pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0xa91B0001); pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0xa81C0001); @@ -880,11 +639,9 @@ static void halbtc8723b2ant_SetAgcTable( /* RF Gain */ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0xef, 0xfffff, 0x02000); if (bAgcTableEn) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, ("[BTCoex], Agc Table On!\n")); pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x3b, 0xfffff, 0x38fff); pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x3b, 0xfffff, 0x38ffe); } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, ("[BTCoex], Agc Table Off!\n")); pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x3b, 0xfffff, 0x380c3); pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x3b, 0xfffff, 0x28ce6); } @@ -892,11 +649,9 @@ static void halbtc8723b2ant_SetAgcTable( pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0xed, 0xfffff, 0x1); if (bAgcTableEn) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, ("[BTCoex], Agc Table On!\n")); pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x40, 0xfffff, 0x38fff); pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x40, 0xfffff, 0x38ffe); } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, ("[BTCoex], Agc Table Off!\n")); pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x40, 0xfffff, 0x380c3); pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x40, 0xfffff, 0x28ce6); } @@ -913,28 +668,9 @@ static void halbtc8723b2ant_AgcTable( struct btc_coexist *pBtCoexist, bool bForceExec, bool bAgcTableEn ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW, - ( - "[BTCoex], %s %s Agc Table\n", - (bForceExec ? "force to" : ""), - (bAgcTableEn ? "Enable" : "Disable") - ) - ); pCoexDm->bCurAgcTableEn = bAgcTableEn; if (!bForceExec) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW_DETAIL, - ( - "[BTCoex], bPreAgcTableEn =%d, bCurAgcTableEn =%d\n", - pCoexDm->bPreAgcTableEn, - pCoexDm->bCurAgcTableEn - ) - ); - if (pCoexDm->bPreAgcTableEn == pCoexDm->bCurAgcTableEn) return; } @@ -951,32 +687,12 @@ static void halbtc8723b2ant_SetCoexTable( u8 val0x6cc ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW_EXEC, - ("[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0) - ); pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x6c0, val0x6c0); - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW_EXEC, - ("[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4) - ); pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x6c4, val0x6c4); - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW_EXEC, - ("[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8) - ); pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x6c8, val0x6c8); - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW_EXEC, - ("[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc) - ); pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x6cc, val0x6cc); } @@ -989,47 +705,12 @@ static void halbtc8723b2ant_CoexTable( u8 val0x6cc ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW, - ( - "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, 0x6c4 = 0x%x, 0x6c8 = 0x%x, 0x6cc = 0x%x\n", - (bForceExec ? "force to" : ""), - val0x6c0, - val0x6c4, - val0x6c8, - val0x6cc - ) - ); pCoexDm->curVal0x6c0 = val0x6c0; pCoexDm->curVal0x6c4 = val0x6c4; pCoexDm->curVal0x6c8 = val0x6c8; pCoexDm->curVal0x6cc = val0x6cc; if (!bForceExec) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW_DETAIL, - ( - "[BTCoex], preVal0x6c0 = 0x%x, preVal0x6c4 = 0x%x, preVal0x6c8 = 0x%x, preVal0x6cc = 0x%x !!\n", - pCoexDm->preVal0x6c0, - pCoexDm->preVal0x6c4, - pCoexDm->preVal0x6c8, - pCoexDm->preVal0x6cc - ) - ); - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_SW_DETAIL, - ( - "[BTCoex], curVal0x6c0 = 0x%x, curVal0x6c4 = 0x%x, curVal0x6c8 = 0x%x, curVal0x6cc = 0x%x !!\n", - pCoexDm->curVal0x6c0, - pCoexDm->curVal0x6c4, - pCoexDm->curVal0x6c8, - pCoexDm->curVal0x6cc - ) - ); - if ( (pCoexDm->preVal0x6c0 == pCoexDm->curVal0x6c0) && (pCoexDm->preVal0x6c4 == pCoexDm->curVal0x6c4) && @@ -1104,15 +785,6 @@ static void halbtc8723b2ant_SetFwIgnoreWlanAct( if (bEnable) H2C_Parameter[0] |= BIT0; /* function enable */ - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_EXEC, - ( - "[BTCoex], set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n", - H2C_Parameter[0] - ) - ); - pBtCoexist->fBtcFillH2c(pBtCoexist, 0x63, 1, H2C_Parameter); } @@ -1120,22 +792,9 @@ static void halbtc8723b2ant_IgnoreWlanAct( struct btc_coexist *pBtCoexist, bool bForceExec, bool bEnable ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW, - ( - "[BTCoex], %s turn Ignore WlanAct %s\n", - (bForceExec ? "force to" : ""), - (bEnable ? "ON" : "OFF") - ) - ); - pCoexDm->bCurIgnoreWlanAct = bEnable; if (!bForceExec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], bPreIgnoreWlanAct = %d, bCurIgnoreWlanAct = %d!!\n", - pCoexDm->bPreIgnoreWlanAct, pCoexDm->bCurIgnoreWlanAct)); - if (pCoexDm->bPreIgnoreWlanAct == pCoexDm->bCurIgnoreWlanAct) return; } @@ -1167,19 +826,6 @@ static void halbtc8723b2ant_SetFwPstdma( pCoexDm->psTdmaPara[3] = byte4; pCoexDm->psTdmaPara[4] = byte5; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_EXEC, - ( - "[BTCoex], FW write 0x60(5bytes) = 0x%x%08x\n", - H2C_Parameter[0], - H2C_Parameter[1] << 24 | - H2C_Parameter[2] << 16 | - H2C_Parameter[3] << 8 | - H2C_Parameter[4] - ) - ); - pBtCoexist->fBtcFillH2c(pBtCoexist, 0x60, 5, H2C_Parameter); } @@ -1305,38 +951,10 @@ static void halbtc8723b2ant_PsTdma( struct btc_coexist *pBtCoexist, bool bForceExec, bool bTurnOn, u8 type ) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW, - ( - "[BTCoex], %s turn %s PS TDMA, type =%d\n", - (bForceExec ? "force to" : ""), - (bTurnOn ? "ON" : "OFF"), - type - ) - ); pCoexDm->bCurPsTdmaOn = bTurnOn; pCoexDm->curPsTdma = type; if (!bForceExec) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - ( - "[BTCoex], bPrePsTdmaOn = %d, bCurPsTdmaOn = %d!!\n", - pCoexDm->bPrePsTdmaOn, - pCoexDm->bCurPsTdmaOn - ) - ); - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - ( - "[BTCoex], prePsTdma = %d, curPsTdma = %d!!\n", - pCoexDm->prePsTdma, pCoexDm->curPsTdma - ) - ); - if ( (pCoexDm->bPrePsTdmaOn == pCoexDm->bCurPsTdmaOn) && (pCoexDm->prePsTdma == pCoexDm->curPsTdma) @@ -1505,8 +1123,6 @@ static bool halbtc8723b2ant_IsCommonAction(struct btc_coexist *pBtCoexist) pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &bLowPwrDisable); halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Wifi non-connected idle!!\n")); - pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0); halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 1); @@ -1523,8 +1139,6 @@ static bool halbtc8723b2ant_IsCommonAction(struct btc_coexist *pBtCoexist) pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &bLowPwrDisable); halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Wifi connected + BT non connected-idle!!\n")); - pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0); halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 1); @@ -1542,7 +1156,6 @@ static bool halbtc8723b2ant_IsCommonAction(struct btc_coexist *pBtCoexist) if (bBtHsOn) return false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Wifi connected + BT connected-idle!!\n")); halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8); pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); @@ -1560,13 +1173,11 @@ static bool halbtc8723b2ant_IsCommonAction(struct btc_coexist *pBtCoexist) pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &bLowPwrDisable); if (bWifiBusy) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Wifi Connected-Busy + BT Busy!!\n")); bCommon = false; } else { if (bBtHsOn) return false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Wifi Connected-Idle + BT Busy!!\n")); btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0); halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8); @@ -1598,11 +1209,8 @@ static void halbtc8723b2ant_TdmaDurationAdjust( s32 result; /* 0: no change, +1: increase WiFi duration, -1: decrease WiFi duration */ u8 retryCount = 0; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, ("[BTCoex], TdmaDurationAdjust()\n")); - if (!pCoexDm->bAutoTdmaAdjust) { pCoexDm->bAutoTdmaAdjust = true; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], first run TdmaDurationAdjust()!!\n")); { if (bScoHid) { if (bTxPause) { @@ -1648,15 +1256,6 @@ static void halbtc8723b2ant_TdmaDurationAdjust( } else { /* acquire the BT TRx retry count from BT_Info byte2 */ retryCount = pCoexSta->btRetryCnt; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], retryCount = %d\n", retryCount)); - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - ( - "[BTCoex], up =%d, dn =%d, m =%d, n =%d, WaitCount =%d\n", - up, dn, m, n, WaitCount - ) - ); result = 0; WaitCount++; @@ -1673,7 +1272,6 @@ static void halbtc8723b2ant_TdmaDurationAdjust( up = 0; dn = 0; result = 1; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], Increase wifi duration!!\n")); } } else if (retryCount <= 3) { /* <=3 retry in the last 2-second duration */ up--; @@ -1696,7 +1294,6 @@ static void halbtc8723b2ant_TdmaDurationAdjust( dn = 0; WaitCount = 0; result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], Decrease wifi duration for retryCounter<3!!\n")); } } else { /* retry count > 3, 只要1次 retry count > 3, 則調窄WiFi duration */ if (WaitCount == 1) @@ -1712,14 +1309,10 @@ static void halbtc8723b2ant_TdmaDurationAdjust( dn = 0; WaitCount = 0; result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], Decrease wifi duration for retryCounter>3!!\n")); } - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], max Interval = %d\n", maxInterval)); if (maxInterval == 1) { if (bTxPause) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], TxPause = 1\n")); - if (pCoexDm->curPsTdma == 71) HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(5); else if (pCoexDm->curPsTdma == 1) @@ -1768,7 +1361,6 @@ static void halbtc8723b2ant_TdmaDurationAdjust( HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(13); } } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], TxPause = 0\n")); if (pCoexDm->curPsTdma == 5) HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(71); else if (pCoexDm->curPsTdma == 6) @@ -1821,7 +1413,6 @@ static void halbtc8723b2ant_TdmaDurationAdjust( } } else if (maxInterval == 2) { if (bTxPause) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], TxPause = 1\n")); if (pCoexDm->curPsTdma == 1) HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(6); else if (pCoexDm->curPsTdma == 2) @@ -1868,7 +1459,6 @@ static void halbtc8723b2ant_TdmaDurationAdjust( HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(14); } } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], TxPause = 0\n")); if (pCoexDm->curPsTdma == 5) HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(2); else if (pCoexDm->curPsTdma == 6) @@ -1917,7 +1507,6 @@ static void halbtc8723b2ant_TdmaDurationAdjust( } } else if (maxInterval == 3) { if (bTxPause) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], TxPause = 1\n")); if (pCoexDm->curPsTdma == 1) HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(7); else if (pCoexDm->curPsTdma == 2) @@ -1964,7 +1553,6 @@ static void halbtc8723b2ant_TdmaDurationAdjust( HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(15); } } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], TxPause = 0\n")); if (pCoexDm->curPsTdma == 5) HAL_BTC8723B2ANT_DMA_DURATION_ADJUST(3); else if (pCoexDm->curPsTdma == 6) @@ -2018,15 +1606,6 @@ static void halbtc8723b2ant_TdmaDurationAdjust( /* then we have to adjust it back to the previous record one. */ if (pCoexDm->curPsTdma != pCoexDm->psTdmaDuAdjType) { bool bScan = false, bLink = false, bRoam = false; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - ( - "[BTCoex], PsTdma type mismatch!!!, curPsTdma =%d, recordPsTdma =%d\n", - pCoexDm->curPsTdma, - pCoexDm->psTdmaDuAdjType - ) - ); pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_SCAN, &bScan); pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_LINK, &bLink); @@ -2034,9 +1613,7 @@ static void halbtc8723b2ant_TdmaDurationAdjust( if (!bScan && !bLink && !bRoam) halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, pCoexDm->psTdmaDuAdjType); - else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], roaming/link/scan is under progress, will adjust next time!!!\n")); - } + } } @@ -2171,7 +1748,6 @@ static void halbtc8723b2ant_ActionA2dp(struct btc_coexist *pBtCoexist) /* define the office environment */ if (apNum >= 10 && BTC_RSSI_HIGH(wifiRssiState1)) { - /* DbgPrint(" AP#>10(%d)\n", apNum); */ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8); halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6); @@ -2660,21 +2236,16 @@ static void halbtc8723b2ant_RunCoexistMechanism(struct btc_coexist *pBtCoexist) { u8 algorithm = 0; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], RunCoexistMechanism() ===>\n")); - if (pBtCoexist->bManualControl) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], RunCoexistMechanism(), return for Manual CTRL <===\n")); return; } if (pCoexSta->bUnderIps) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], wifi is under IPS !!!\n")); return; } algorithm = halbtc8723b2ant_ActionAlgorithm(pBtCoexist); if (pCoexSta->bC2hBtInquiryPage && (BT_8723B_2ANT_COEX_ALGO_PANHS != algorithm)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BT is under inquiry/page scan !!\n")); halbtc8723b2ant_ActionBtInquiry(pBtCoexist); return; } else { @@ -2685,69 +2256,47 @@ static void halbtc8723b2ant_RunCoexistMechanism(struct btc_coexist *pBtCoexist) } pCoexDm->curAlgorithm = algorithm; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Algorithm = %d\n", pCoexDm->curAlgorithm)); if (halbtc8723b2ant_IsCommonAction(pBtCoexist)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant common.\n")); pCoexDm->bAutoTdmaAdjust = false; } else { if (pCoexDm->curAlgorithm != pCoexDm->preAlgorithm) { - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE, - ( - "[BTCoex], preAlgorithm =%d, curAlgorithm =%d\n", - pCoexDm->preAlgorithm, - pCoexDm->curAlgorithm - ) - ); pCoexDm->bAutoTdmaAdjust = false; } switch (pCoexDm->curAlgorithm) { case BT_8723B_2ANT_COEX_ALGO_SCO: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = SCO.\n")); halbtc8723b2ant_ActionSco(pBtCoexist); break; case BT_8723B_2ANT_COEX_ALGO_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = HID.\n")); halbtc8723b2ant_ActionHid(pBtCoexist); break; case BT_8723B_2ANT_COEX_ALGO_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = A2DP.\n")); halbtc8723b2ant_ActionA2dp(pBtCoexist); break; case BT_8723B_2ANT_COEX_ALGO_A2DP_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = A2DP+PAN(HS).\n")); halbtc8723b2ant_ActionA2dpPanHs(pBtCoexist); break; case BT_8723B_2ANT_COEX_ALGO_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = PAN(EDR).\n")); halbtc8723b2ant_ActionPanEdr(pBtCoexist); break; case BT_8723B_2ANT_COEX_ALGO_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = HS mode.\n")); halbtc8723b2ant_ActionPanHs(pBtCoexist); break; case BT_8723B_2ANT_COEX_ALGO_PANEDR_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = PAN+A2DP.\n")); halbtc8723b2ant_ActionPanEdrA2dp(pBtCoexist); break; case BT_8723B_2ANT_COEX_ALGO_PANEDR_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = PAN(EDR)+HID.\n")); halbtc8723b2ant_ActionPanEdrHid(pBtCoexist); break; case BT_8723B_2ANT_COEX_ALGO_HID_A2DP_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = HID+A2DP+PAN.\n")); halbtc8723b2ant_ActionHidA2dpPanEdr(pBtCoexist); break; case BT_8723B_2ANT_COEX_ALGO_HID_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = HID+A2DP.\n")); halbtc8723b2ant_ActionHidA2dp(pBtCoexist); break; default: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = coexist All Off!!\n")); halbtc8723b2ant_CoexAllOff(pBtCoexist); break; } @@ -2784,8 +2333,6 @@ static void halbtc8723b2ant_InitHwConfig(struct btc_coexist *pBtCoexist, bool bB { u8 u1Tmp = 0; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], 2Ant Init HW Config!!\n")); - /* backup rf 0x1e value */ pCoexDm->btRf0x1eBackup = pBtCoexist->fBtcGetRfReg(pBtCoexist, BTC_RF_A, 0x1e, 0xfffff); @@ -2873,8 +2420,6 @@ void EXhalbtc8723b2ant_InitHwConfig(struct btc_coexist *pBtCoexist, bool bWifiOn void EXhalbtc8723b2ant_InitCoexDm(struct btc_coexist *pBtCoexist) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], Coex Mechanism Init!!\n")); - halbtc8723b2ant_InitCoexDm(pBtCoexist); } @@ -2886,7 +2431,7 @@ void EXhalbtc8723b2ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) u8 *cliBuf = pBtCoexist->cliBuf; u8 u1Tmp[4], i, btInfoExt, psTdmaCase = 0; u32 u4Tmp[4]; - bool bRoam = false, bScan = false, bLink = false, bWifiUnder5G = false; + bool bRoam = false, bScan = false, bLink = false; bool bBtHsOn = false, bWifiBusy = false; s32 wifiRssi = 0, btHsRssi = 0; u32 wifiBw, wifiTrafficDir, faOfdm, faCck; @@ -2977,7 +2522,6 @@ void EXhalbtc8723b2ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) ); CL_PRINTF(cliBuf); - pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_UNDER_5G, &bWifiUnder5G); pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw); pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy); pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_TRAFFIC_DIRECTION, &wifiTrafficDir); @@ -2985,7 +2529,7 @@ void EXhalbtc8723b2ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s / %s/ %s ", "Wifi status", \ - (bWifiUnder5G ? "5G" : "2.4G"), + ("2.4G"), ((BTC_WIFI_BW_LEGACY == wifiBw) ? "Legacy" : (((BTC_WIFI_BW_HT40 == wifiBw) ? "HT40" : "HT20"))), ((!bWifiBusy) ? "idle" : ((BTC_WIFI_TRAFFIC_TX == wifiTrafficDir) ? "uplink" : "downlink")) ); @@ -3262,13 +2806,11 @@ void EXhalbtc8723b2ant_DisplayCoexInfo(struct btc_coexist *pBtCoexist) void EXhalbtc8723b2ant_IpsNotify(struct btc_coexist *pBtCoexist, u8 type) { if (BTC_IPS_ENTER == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], IPS ENTER notify\n")); pCoexSta->bUnderIps = true; halbtc8723b2ant_WifiOffHwCfg(pBtCoexist); halbtc8723b2ant_IgnoreWlanAct(pBtCoexist, FORCE_EXEC, true); halbtc8723b2ant_CoexAllOff(pBtCoexist); } else if (BTC_IPS_LEAVE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], IPS LEAVE notify\n")); pCoexSta->bUnderIps = false; halbtc8723b2ant_InitHwConfig(pBtCoexist, false); halbtc8723b2ant_InitCoexDm(pBtCoexist); @@ -3279,10 +2821,8 @@ void EXhalbtc8723b2ant_IpsNotify(struct btc_coexist *pBtCoexist, u8 type) void EXhalbtc8723b2ant_LpsNotify(struct btc_coexist *pBtCoexist, u8 type) { if (BTC_LPS_ENABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], LPS ENABLE notify\n")); pCoexSta->bUnderLps = true; } else if (BTC_LPS_DISABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], LPS DISABLE notify\n")); pCoexSta->bUnderLps = false; } } @@ -3290,18 +2830,14 @@ void EXhalbtc8723b2ant_LpsNotify(struct btc_coexist *pBtCoexist, u8 type) void EXhalbtc8723b2ant_ScanNotify(struct btc_coexist *pBtCoexist, u8 type) { if (BTC_SCAN_START == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], SCAN START notify\n")); } else if (BTC_SCAN_FINISH == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], SCAN FINISH notify\n")); } } void EXhalbtc8723b2ant_ConnectNotify(struct btc_coexist *pBtCoexist, u8 type) { if (BTC_ASSOCIATE_START == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], CONNECT START notify\n")); } else if (BTC_ASSOCIATE_FINISH == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], CONNECT FINISH notify\n")); } } @@ -3312,12 +2848,6 @@ void EXhalbtc8723b2ant_MediaStatusNotify(struct btc_coexist *pBtCoexist, u8 type u8 wifiCentralChnl; u8 apNum = 0; - if (BTC_MEDIA_CONNECT == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], MEDIA connect notify\n")); - } else { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], MEDIA disconnect notify\n")); - } - /* only 2.4G we need to inform bt the chnl mask */ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_WIFI_CENTRAL_CHNL, &wifiCentralChnl); if ((BTC_MEDIA_CONNECT == type) && (wifiCentralChnl <= 14)) { @@ -3339,23 +2869,11 @@ void EXhalbtc8723b2ant_MediaStatusNotify(struct btc_coexist *pBtCoexist, u8 type pCoexDm->wifiChnlInfo[1] = H2C_Parameter[1]; pCoexDm->wifiChnlInfo[2] = H2C_Parameter[2]; - BTC_PRINT( - BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_EXEC, - ( - "[BTCoex], FW write 0x66 = 0x%x\n", - H2C_Parameter[0] << 16 | H2C_Parameter[1] << 8 | H2C_Parameter[2] - ) - ); - pBtCoexist->fBtcFillH2c(pBtCoexist, 0x66, 3, H2C_Parameter); } void EXhalbtc8723b2ant_SpecialPacketNotify(struct btc_coexist *pBtCoexist, u8 type) { - if (type == BTC_PACKET_DHCP) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], DHCP Packet notify\n")); - } } void EXhalbtc8723b2ant_BtInfoNotify( @@ -3375,21 +2893,14 @@ void EXhalbtc8723b2ant_BtInfoNotify( pCoexSta->btInfoC2hCnt[rspSource]++; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Bt info[%d], length =%d, hex data =[", rspSource, length)); for (i = 0; i < length; i++) { pCoexSta->btInfoC2h[rspSource][i] = tmpBuf[i]; if (i == 1) btInfo = tmpBuf[i]; - if (i == length - 1) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("0x%02x]\n", tmpBuf[i])); - } else { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("0x%02x, ", tmpBuf[i])); - } } if (pBtCoexist->bManualControl) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), return for Manual CTRL<===\n")); return; } @@ -3404,14 +2915,12 @@ void EXhalbtc8723b2ant_BtInfoNotify( pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_BL_BT_TX_RX_MASK, &pCoexSta->bBtTxRxMask); if (pCoexSta->bBtTxRxMask) { /* BT into is responded by BT FW and BT RF REG 0x3C != 0x01 => Need to switch BT TRx Mask */ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Switch BT TRx Mask since BT RF REG 0x3C != 0x01\n")); pBtCoexist->fBtcSetBtReg(pBtCoexist, BTC_BT_REG_RF, 0x3c, 0x01); } /* Here we need to resend some wifi info to BT */ /* because bt is reset and loss of the info. */ if ((pCoexSta->btInfoExt & BIT1)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BT ext info bit1 check, send wifi BW&Chnl to BT!!\n")); pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected); if (bWifiConnected) @@ -3421,7 +2930,6 @@ void EXhalbtc8723b2ant_BtInfoNotify( } if ((pCoexSta->btInfoExt & BIT3)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n")); halbtc8723b2ant_IgnoreWlanAct(pBtCoexist, FORCE_EXEC, false); } else { /* BT already NOT ignore Wlan active, do nothing here. */ @@ -3465,22 +2973,17 @@ void EXhalbtc8723b2ant_BtInfoNotify( if (!(btInfo & BT_INFO_8723B_2ANT_B_CONNECTION)) { pCoexDm->btStatus = BT_8723B_2ANT_BT_STATUS_NON_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT Non-Connected idle!!!\n")); } else if (btInfo == BT_INFO_8723B_2ANT_B_CONNECTION) { /* connection exists but no busy */ pCoexDm->btStatus = BT_8723B_2ANT_BT_STATUS_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n")); } else if ( (btInfo & BT_INFO_8723B_2ANT_B_SCO_ESCO) || (btInfo & BT_INFO_8723B_2ANT_B_SCO_BUSY) ) { pCoexDm->btStatus = BT_8723B_2ANT_BT_STATUS_SCO_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT SCO busy!!!\n")); } else if (btInfo & BT_INFO_8723B_2ANT_B_ACL_BUSY) { pCoexDm->btStatus = BT_8723B_2ANT_BT_STATUS_ACL_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT ACL busy!!!\n")); } else { pCoexDm->btStatus = BT_8723B_2ANT_BT_STATUS_MAX; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT Non-Defined state!!!\n")); } if ( @@ -3505,8 +3008,6 @@ void EXhalbtc8723b2ant_BtInfoNotify( void EXhalbtc8723b2ant_HaltNotify(struct btc_coexist *pBtCoexist) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Halt notify\n")); - halbtc8723b2ant_WifiOffHwCfg(pBtCoexist); pBtCoexist->fBtcSetBtReg(pBtCoexist, BTC_BT_REG_RF, 0x3c, 0x15); /* BT goto standby while GNT_BT 1-->0 */ halbtc8723b2ant_IgnoreWlanAct(pBtCoexist, FORCE_EXEC, true); @@ -3516,12 +3017,8 @@ void EXhalbtc8723b2ant_HaltNotify(struct btc_coexist *pBtCoexist) void EXhalbtc8723b2ant_PnpNotify(struct btc_coexist *pBtCoexist, u8 pnpState) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Pnp notify\n")); - if (BTC_WIFI_PNP_SLEEP == pnpState) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Pnp notify to SLEEP\n")); } else if (BTC_WIFI_PNP_WAKE_UP == pnpState) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Pnp notify to WAKE UP\n")); halbtc8723b2ant_InitHwConfig(pBtCoexist, false); halbtc8723b2ant_InitCoexDm(pBtCoexist); halbtc8723b2ant_QueryBtInfo(pBtCoexist); @@ -3533,16 +3030,10 @@ void EXhalbtc8723b2ant_Periodical(struct btc_coexist *pBtCoexist) static u8 disVerInfoCnt; u32 fwVer = 0, btPatchVer = 0; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], ==========================Periodical ===========================\n")); - if (disVerInfoCnt <= 5) { disVerInfoCnt += 1; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], ****************************************************************\n")); pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_BT_PATCH_VER, &btPatchVer); pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_FW_VER, &fwVer); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", \ - GLCoexVerDate8723b2Ant, GLCoexVer8723b2Ant, fwVer, btPatchVer, btPatchVer)); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], ****************************************************************\n")); } if ( diff --git a/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h b/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h index 7b2d94a33d9c..deb57fa15eaf 100644 --- a/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h +++ b/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h @@ -78,29 +78,6 @@ enum { BTC_CHIP_MAX }; -enum { - BTC_MSG_INTERFACE = 0x0, - BTC_MSG_ALGORITHM = 0x1, - BTC_MSG_MAX -}; -extern u32 GLBtcDbgType[]; - -/* following is for BTC_MSG_INTERFACE */ -#define INTF_INIT BIT0 -#define INTF_NOTIFY BIT2 - -/* following is for BTC_ALGORITHM */ -#define ALGO_BT_RSSI_STATE BIT0 -#define ALGO_WIFI_RSSI_STATE BIT1 -#define ALGO_BT_MONITOR BIT2 -#define ALGO_TRACE BIT3 -#define ALGO_TRACE_FW BIT4 -#define ALGO_TRACE_FW_DETAIL BIT5 -#define ALGO_TRACE_FW_EXEC BIT6 -#define ALGO_TRACE_SW BIT7 -#define ALGO_TRACE_SW_DETAIL BIT8 -#define ALGO_TRACE_SW_EXEC BIT9 - /* following is for wifi link status */ #define WIFI_STA_CONNECTED BIT0 #define WIFI_AP_CONNECTED BIT1 @@ -112,50 +89,6 @@ extern u32 GLBtcDbgType[]; #define CL_SPRINTF snprintf #define CL_PRINTF DCMD_Printf -/* The following is for dbgview print */ -#if DBG -#define BTC_PRINT(dbgtype, dbgflag, printstr)\ -{\ - if (GLBtcDbgType[dbgtype] & dbgflag)\ - DbgPrint printstr;\ -} - -#define BTC_PRINT_ADDR(dbgtype, dbgflag, printstr, _Ptr)\ -{\ - if (GLBtcDbgType[dbgtype] & dbgflag) {\ - int __i;\ - u8 *ptr = (u8 *)_Ptr;\ - DbgPrint printstr;\ - DbgPrint(" ");\ - for (__i = 0; __i < 6; __i++)\ - DbgPrint("%02X%s", ptr[__i], (__i == 5) ? "" : "-");\ - DbgPrint("\n");\ - } \ -} - -#define BTC_PRINT_DATA(dbgtype, dbgflag, _TitleString, _HexData, _HexDataLen)\ -{\ - if (GLBtcDbgType[dbgtype] & dbgflag) {\ - int __i;\ - u8 *ptr = (u8 *)_HexData;\ - DbgPrint(_TitleString);\ - for (__i = 0; __i < (int)_HexDataLen; __i++) {\ - DbgPrint("%02X%s", ptr[__i], (((__i + 1) % 4) == 0) ? " " : " ");\ - if (((__i + 1) % 16) == 0)\ - DbgPrint("\n");\ - } \ - DbgPrint("\n");\ - } \ -} - -#else -#define BTC_PRINT(dbgtype, dbgflag, printstr) no_printk printstr -#define BTC_PRINT_F(dbgtype, dbgflag, printstr) no_printk printstr -#define BTC_PRINT_ADDR(dbgtype, dbgflag, printstr, _Ptr) no_printk printstr -#define BTC_PRINT_DATA(dbgtype, dbgflag, _TitleString, _HexData, _HexDataLen) \ - no_printk("%s %p %zu", _TitleString, _HexData, _HexDataLen) -#endif - struct btc_board_info { /* The following is some board information */ u8 btChipType; @@ -209,7 +142,6 @@ enum { BTC_GET_BL_WIFI_LINK, BTC_GET_BL_WIFI_ROAM, BTC_GET_BL_WIFI_4_WAY_PROGRESS, - BTC_GET_BL_WIFI_UNDER_5G, BTC_GET_BL_WIFI_AP_MODE_ENABLE, BTC_GET_BL_WIFI_ENABLE_ENCRYPTION, BTC_GET_BL_WIFI_UNDER_B_MODE, diff --git a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.c b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.c index 016d257b90a0..3de8dcb5ed7c 100644 --- a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.c +++ b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_BB.c @@ -33,47 +33,6 @@ static bool CheckPositive( pDM_Odm->TypeALNA << 16 | pDM_Odm->TypeAPA << 24; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_TRACE, - ( - "===> [8812A] CheckPositive (cond1, cond2) = (0x%X 0x%X)\n", - cond1, - cond2 - ) - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_TRACE, - ( - "===> [8812A] CheckPositive (driver1, driver2) = (0x%X 0x%X)\n", - driver1, - driver2 - ) - ); - - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_TRACE, - (" (Platform, Interface) = (0x%X, 0x%X)\n", - pDM_Odm->SupportPlatform, - pDM_Odm->SupportInterface - ) - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_TRACE, - ( - " (Board, Package) = (0x%X, 0x%X)\n", - pDM_Odm->BoardType, - pDM_Odm->PackageType - ) - ); - /* Value Defined Check =============== */ /* QFN Type [15:12] and Cut Version [27:24] need to do value check */ @@ -263,13 +222,6 @@ void ODM_ReadAndConfig_MP_8723B_AGC_TAB(struct dm_odm_t *pDM_Odm) u32 ArrayLen = ARRAY_SIZE(Array_MP_8723B_AGC_TAB); u32 *Array = Array_MP_8723B_AGC_TAB; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_LOUD, - ("===> ODM_ReadAndConfig_MP_8723B_AGC_TAB\n") - ); - for (i = 0; i < ArrayLen; i += 2) { u32 v1 = Array[i]; u32 v2 = Array[i+1]; @@ -532,13 +484,6 @@ void ODM_ReadAndConfig_MP_8723B_PHY_REG(struct dm_odm_t *pDM_Odm) u32 ArrayLen = ARRAY_SIZE(Array_MP_8723B_PHY_REG); u32 *Array = Array_MP_8723B_PHY_REG; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_LOUD, - ("===> ODM_ReadAndConfig_MP_8723B_PHY_REG\n") - ); - for (i = 0; i < ArrayLen; i += 2) { u32 v1 = Array[i]; u32 v2 = Array[i+1]; @@ -598,12 +543,12 @@ void ODM_ReadAndConfig_MP_8723B_PHY_REG(struct dm_odm_t *pDM_Odm) ******************************************************************************/ static u32 Array_MP_8723B_PHY_REG_PG[] = { - 0, 0, 0, 0x00000e08, 0x0000ff00, 0x00003800, - 0, 0, 0, 0x0000086c, 0xffffff00, 0x32343600, - 0, 0, 0, 0x00000e00, 0xffffffff, 0x40424444, - 0, 0, 0, 0x00000e04, 0xffffffff, 0x28323638, - 0, 0, 0, 0x00000e10, 0xffffffff, 0x38404244, - 0, 0, 0, 0x00000e14, 0xffffffff, 0x26303436 + 0, 0, 0x00000e08, 0x0000ff00, 0x00003800, + 0, 0, 0x0000086c, 0xffffff00, 0x32343600, + 0, 0, 0x00000e00, 0xffffffff, 0x40424444, + 0, 0, 0x00000e04, 0xffffffff, 0x28323638, + 0, 0, 0x00000e10, 0xffffffff, 0x38404244, + 0, 0, 0x00000e14, 0xffffffff, 0x26303436 }; void ODM_ReadAndConfig_MP_8723B_PHY_REG_PG(struct dm_odm_t *pDM_Odm) @@ -611,24 +556,16 @@ void ODM_ReadAndConfig_MP_8723B_PHY_REG_PG(struct dm_odm_t *pDM_Odm) u32 i = 0; u32 *Array = Array_MP_8723B_PHY_REG_PG; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_LOUD, - ("===> ODM_ReadAndConfig_MP_8723B_PHY_REG_PG\n") - ); - pDM_Odm->PhyRegPgVersion = 1; pDM_Odm->PhyRegPgValueType = PHY_REG_PG_EXACT_VALUE; - for (i = 0; i < ARRAY_SIZE(Array_MP_8723B_PHY_REG_PG); i += 6) { + for (i = 0; i < ARRAY_SIZE(Array_MP_8723B_PHY_REG_PG); i += 5) { u32 v1 = Array[i]; u32 v2 = Array[i+1]; u32 v3 = Array[i+2]; u32 v4 = Array[i+3]; u32 v5 = Array[i+4]; - u32 v6 = Array[i+5]; - odm_ConfigBB_PHY_REG_PG_8723B(pDM_Odm, v1, v2, v3, v4, v5, v6); + odm_ConfigBB_PHY_REG_PG_8723B(pDM_Odm, v1, v2, v3, v4, v5); } } diff --git a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_MAC.c b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_MAC.c index 677bcfa10b0d..47e66f4ad9d1 100644 --- a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_MAC.c +++ b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_MAC.c @@ -33,48 +33,6 @@ static bool CheckPositive( pDM_Odm->TypeALNA << 16 | pDM_Odm->TypeAPA << 24; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_TRACE, - ( - "===> [8812A] CheckPositive (cond1, cond2) = (0x%X 0x%X)\n", - cond1, - cond2 - ) - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_TRACE, - ( - "===> [8812A] CheckPositive (driver1, driver2) = (0x%X 0x%X)\n", - driver1, - driver2 - ) - ); - - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_TRACE, - ( - " (Platform, Interface) = (0x%X, 0x%X)\n", - pDM_Odm->SupportPlatform, - pDM_Odm->SupportInterface - ) - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_TRACE, - ( - " (Board, Package) = (0x%X, 0x%X)\n", - pDM_Odm->BoardType, - pDM_Odm->PackageType - ) - ); - /* Value Defined Check =============== */ /* QFN Type [15:12] and Cut Version [27:24] need to do value check */ @@ -234,13 +192,6 @@ void ODM_ReadAndConfig_MP_8723B_MAC_REG(struct dm_odm_t *pDM_Odm) u32 ArrayLen = ARRAY_SIZE(Array_MP_8723B_MAC_REG); u32 *Array = Array_MP_8723B_MAC_REG; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_LOUD, - ("===> ODM_ReadAndConfig_MP_8723B_MAC_REG\n") - ); - for (i = 0; i < ArrayLen; i += 2) { u32 v1 = Array[i]; u32 v2 = Array[i+1]; diff --git a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.c b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.c index 2c450c1ce7e7..00d429977ea9 100644 --- a/drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.c +++ b/drivers/staging/rtl8723bs/hal/HalHWImg8723B_RF.c @@ -33,48 +33,6 @@ static bool CheckPositive( pDM_Odm->TypeALNA << 16 | pDM_Odm->TypeAPA << 24; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_TRACE, - ( - "===> [8812A] CheckPositive (cond1, cond2) = (0x%X 0x%X)\n", - cond1, - cond2 - ) - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_TRACE, - ( - "===> [8812A] CheckPositive (driver1, driver2) = (0x%X 0x%X)\n", - driver1, - driver2 - ) - ); - - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_TRACE, - ( - " (Platform, Interface) = (0x%X, 0x%X)\n", - pDM_Odm->SupportPlatform, - pDM_Odm->SupportInterface - ) - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_TRACE, - ( - " (Board, Package) = (0x%X, 0x%X)\n", - pDM_Odm->BoardType, - pDM_Odm->PackageType - ) - ); - /* Value Defined Check =============== */ /* QFN Type [15:12] and Cut Version [27:24] need to do value check */ @@ -265,13 +223,6 @@ void ODM_ReadAndConfig_MP_8723B_RadioA(struct dm_odm_t *pDM_Odm) u32 ArrayLen = ARRAY_SIZE(Array_MP_8723B_RadioA); u32 *Array = Array_MP_8723B_RadioA; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_LOUD, - ("===> ODM_ReadAndConfig_MP_8723B_RadioA\n") - ); - for (i = 0; i < ArrayLen; i += 2) { u32 v1 = Array[i]; u32 v2 = Array[i+1]; @@ -331,62 +282,6 @@ void ODM_ReadAndConfig_MP_8723B_RadioA(struct dm_odm_t *pDM_Odm) * TxPowerTrack_SDIO.TXT ******************************************************************************/ -static u8 gDeltaSwingTableIdx_MP_5GB_N_TxPowerTrack_SDIO_8723B[][DELTA_SWINGIDX_SIZE] = { - { - 0, 1, 1, 2, 2, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, - 9, 10, 11, 12, 12, 13, 13, 14, 14, 14, 14, 14, 14, 14 - }, - { - 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, - 10, 11, 11, 12, 12, 13, 13, 14, 14, 14, 14, 14, 14, 14 - }, - { - 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, - 10, 11, 11, 12, 12, 13, 13, 14, 14, 14, 14, 14, 14, 14 - }, -}; -static u8 gDeltaSwingTableIdx_MP_5GB_P_TxPowerTrack_SDIO_8723B[][DELTA_SWINGIDX_SIZE] = { - { - 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, - 12, 13, 14, 15, 15, 16, 16, 17, 17, 18, 19, 20, 20, 20 - }, - { - 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, - 12, 13, 14, 15, 15, 16, 17, 18, 18, 19, 19, 20, 20, 20 - }, - { - 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, - 12, 13, 14, 15, 15, 16, 17, 18, 18, 19, 20, 21, 21, 21 - }, -}; -static u8 gDeltaSwingTableIdx_MP_5GA_N_TxPowerTrack_SDIO_8723B[][DELTA_SWINGIDX_SIZE] = { - { - 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 8, 9, 9, 10, - 10, 11, 11, 12, 12, 13, 13, 14, 14, 14, 14, 14, 14, 14 - }, - { - 0, 1, 2, 3, 3, 4, 5, 6, 6, 6, 7, 7, 8, 8, 9, 10, - 11, 11, 12, 13, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16 - }, - { - 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 10, 11, - 11, 12, 13, 14, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16 - }, -}; -static u8 gDeltaSwingTableIdx_MP_5GA_P_TxPowerTrack_SDIO_8723B[][DELTA_SWINGIDX_SIZE] = { - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }, - { - 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, - 12, 13, 14, 15, 15, 16, 17, 18, 18, 19, 20, 21, 21, 21 - }, - { - 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, - 12, 13, 14, 15, 15, 16, 17, 18, 18, 19, 20, 21, 21, 21 - }, -}; static u8 gDeltaSwingTableIdx_MP_2GB_N_TxPowerTrack_SDIO_8723B[] = { 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 13, 14, 15 @@ -424,13 +319,6 @@ void ODM_ReadAndConfig_MP_8723B_TxPowerTrack_SDIO(struct dm_odm_t *pDM_Odm) { struct odm_rf_cal_t *pRFCalibrateInfo = &pDM_Odm->RFCalibrateInfo; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_LOUD, - ("===> ODM_ReadAndConfig_MP_MP_8723B\n") - ); - memcpy( pRFCalibrateInfo->DeltaSwingTableIdx_2GA_P, @@ -473,27 +361,6 @@ void ODM_ReadAndConfig_MP_8723B_TxPowerTrack_SDIO(struct dm_odm_t *pDM_Odm) gDeltaSwingTableIdx_MP_2GCCKB_N_TxPowerTrack_SDIO_8723B, DELTA_SWINGIDX_SIZE ); - - memcpy( - pRFCalibrateInfo->DeltaSwingTableIdx_5GA_P, - gDeltaSwingTableIdx_MP_5GA_P_TxPowerTrack_SDIO_8723B, - DELTA_SWINGIDX_SIZE*3 - ); - memcpy( - pRFCalibrateInfo->DeltaSwingTableIdx_5GA_N, - gDeltaSwingTableIdx_MP_5GA_N_TxPowerTrack_SDIO_8723B, - DELTA_SWINGIDX_SIZE*3 - ); - memcpy( - pRFCalibrateInfo->DeltaSwingTableIdx_5GB_P, - gDeltaSwingTableIdx_MP_5GB_P_TxPowerTrack_SDIO_8723B, - DELTA_SWINGIDX_SIZE*3 - ); - memcpy( - pRFCalibrateInfo->DeltaSwingTableIdx_5GB_N, - gDeltaSwingTableIdx_MP_5GB_N_TxPowerTrack_SDIO_8723B, - DELTA_SWINGIDX_SIZE*3 - ); } /****************************************************************************** @@ -501,258 +368,258 @@ void ODM_ReadAndConfig_MP_8723B_TxPowerTrack_SDIO(struct dm_odm_t *pDM_Odm) ******************************************************************************/ static u8 *Array_MP_8723B_TXPWR_LMT[] = { - "FCC", "2.4G", "20M", "CCK", "1T", "01", "32", - "ETSI", "2.4G", "20M", "CCK", "1T", "01", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "01", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "02", "32", - "ETSI", "2.4G", "20M", "CCK", "1T", "02", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "02", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "03", "32", - "ETSI", "2.4G", "20M", "CCK", "1T", "03", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "03", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "04", "32", - "ETSI", "2.4G", "20M", "CCK", "1T", "04", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "04", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "05", "32", - "ETSI", "2.4G", "20M", "CCK", "1T", "05", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "05", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "06", "32", - "ETSI", "2.4G", "20M", "CCK", "1T", "06", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "06", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "07", "32", - "ETSI", "2.4G", "20M", "CCK", "1T", "07", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "07", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "08", "32", - "ETSI", "2.4G", "20M", "CCK", "1T", "08", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "08", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "09", "32", - "ETSI", "2.4G", "20M", "CCK", "1T", "09", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "09", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "10", "32", - "ETSI", "2.4G", "20M", "CCK", "1T", "10", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "10", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "11", "32", - "ETSI", "2.4G", "20M", "CCK", "1T", "11", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "11", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "12", "63", - "ETSI", "2.4G", "20M", "CCK", "1T", "12", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "12", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "13", "63", - "ETSI", "2.4G", "20M", "CCK", "1T", "13", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "13", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "14", "63", - "ETSI", "2.4G", "20M", "CCK", "1T", "14", "63", - "MKK", "2.4G", "20M", "CCK", "1T", "14", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "01", "28", - "ETSI", "2.4G", "20M", "OFDM", "1T", "01", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "01", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "02", "28", - "ETSI", "2.4G", "20M", "OFDM", "1T", "02", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "02", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "03", "32", - "ETSI", "2.4G", "20M", "OFDM", "1T", "03", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "03", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "04", "32", - "ETSI", "2.4G", "20M", "OFDM", "1T", "04", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "04", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "05", "32", - "ETSI", "2.4G", "20M", "OFDM", "1T", "05", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "05", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "06", "32", - "ETSI", "2.4G", "20M", "OFDM", "1T", "06", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "06", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "07", "32", - "ETSI", "2.4G", "20M", "OFDM", "1T", "07", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "07", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "08", "32", - "ETSI", "2.4G", "20M", "OFDM", "1T", "08", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "08", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "09", "32", - "ETSI", "2.4G", "20M", "OFDM", "1T", "09", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "09", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "10", "28", - "ETSI", "2.4G", "20M", "OFDM", "1T", "10", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "10", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "11", "28", - "ETSI", "2.4G", "20M", "OFDM", "1T", "11", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "11", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "12", "63", - "ETSI", "2.4G", "20M", "OFDM", "1T", "12", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "12", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "13", "63", - "ETSI", "2.4G", "20M", "OFDM", "1T", "13", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "13", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "14", "63", - "ETSI", "2.4G", "20M", "OFDM", "1T", "14", "63", - "MKK", "2.4G", "20M", "OFDM", "1T", "14", "63", - "FCC", "2.4G", "20M", "HT", "1T", "01", "26", - "ETSI", "2.4G", "20M", "HT", "1T", "01", "32", - "MKK", "2.4G", "20M", "HT", "1T", "01", "32", - "FCC", "2.4G", "20M", "HT", "1T", "02", "26", - "ETSI", "2.4G", "20M", "HT", "1T", "02", "32", - "MKK", "2.4G", "20M", "HT", "1T", "02", "32", - "FCC", "2.4G", "20M", "HT", "1T", "03", "32", - "ETSI", "2.4G", "20M", "HT", "1T", "03", "32", - "MKK", "2.4G", "20M", "HT", "1T", "03", "32", - "FCC", "2.4G", "20M", "HT", "1T", "04", "32", - "ETSI", "2.4G", "20M", "HT", "1T", "04", "32", - "MKK", "2.4G", "20M", "HT", "1T", "04", "32", - "FCC", "2.4G", "20M", "HT", "1T", "05", "32", - "ETSI", "2.4G", "20M", "HT", "1T", "05", "32", - "MKK", "2.4G", "20M", "HT", "1T", "05", "32", - "FCC", "2.4G", "20M", "HT", "1T", "06", "32", - "ETSI", "2.4G", "20M", "HT", "1T", "06", "32", - "MKK", "2.4G", "20M", "HT", "1T", "06", "32", - "FCC", "2.4G", "20M", "HT", "1T", "07", "32", - "ETSI", "2.4G", "20M", "HT", "1T", "07", "32", - "MKK", "2.4G", "20M", "HT", "1T", "07", "32", - "FCC", "2.4G", "20M", "HT", "1T", "08", "32", - "ETSI", "2.4G", "20M", "HT", "1T", "08", "32", - "MKK", "2.4G", "20M", "HT", "1T", "08", "32", - "FCC", "2.4G", "20M", "HT", "1T", "09", "32", - "ETSI", "2.4G", "20M", "HT", "1T", "09", "32", - "MKK", "2.4G", "20M", "HT", "1T", "09", "32", - "FCC", "2.4G", "20M", "HT", "1T", "10", "26", - "ETSI", "2.4G", "20M", "HT", "1T", "10", "32", - "MKK", "2.4G", "20M", "HT", "1T", "10", "32", - "FCC", "2.4G", "20M", "HT", "1T", "11", "26", - "ETSI", "2.4G", "20M", "HT", "1T", "11", "32", - "MKK", "2.4G", "20M", "HT", "1T", "11", "32", - "FCC", "2.4G", "20M", "HT", "1T", "12", "63", - "ETSI", "2.4G", "20M", "HT", "1T", "12", "32", - "MKK", "2.4G", "20M", "HT", "1T", "12", "32", - "FCC", "2.4G", "20M", "HT", "1T", "13", "63", - "ETSI", "2.4G", "20M", "HT", "1T", "13", "32", - "MKK", "2.4G", "20M", "HT", "1T", "13", "32", - "FCC", "2.4G", "20M", "HT", "1T", "14", "63", - "ETSI", "2.4G", "20M", "HT", "1T", "14", "63", - "MKK", "2.4G", "20M", "HT", "1T", "14", "63", - "FCC", "2.4G", "20M", "HT", "2T", "01", "30", - "ETSI", "2.4G", "20M", "HT", "2T", "01", "32", - "MKK", "2.4G", "20M", "HT", "2T", "01", "32", - "FCC", "2.4G", "20M", "HT", "2T", "02", "32", - "ETSI", "2.4G", "20M", "HT", "2T", "02", "32", - "MKK", "2.4G", "20M", "HT", "2T", "02", "32", - "FCC", "2.4G", "20M", "HT", "2T", "03", "32", - "ETSI", "2.4G", "20M", "HT", "2T", "03", "32", - "MKK", "2.4G", "20M", "HT", "2T", "03", "32", - "FCC", "2.4G", "20M", "HT", "2T", "04", "32", - "ETSI", "2.4G", "20M", "HT", "2T", "04", "32", - "MKK", "2.4G", "20M", "HT", "2T", "04", "32", - "FCC", "2.4G", "20M", "HT", "2T", "05", "32", - "ETSI", "2.4G", "20M", "HT", "2T", "05", "32", - "MKK", "2.4G", "20M", "HT", "2T", "05", "32", - "FCC", "2.4G", "20M", "HT", "2T", "06", "32", - "ETSI", "2.4G", "20M", "HT", "2T", "06", "32", - "MKK", "2.4G", "20M", "HT", "2T", "06", "32", - "FCC", "2.4G", "20M", "HT", "2T", "07", "32", - "ETSI", "2.4G", "20M", "HT", "2T", "07", "32", - "MKK", "2.4G", "20M", "HT", "2T", "07", "32", - "FCC", "2.4G", "20M", "HT", "2T", "08", "32", - "ETSI", "2.4G", "20M", "HT", "2T", "08", "32", - "MKK", "2.4G", "20M", "HT", "2T", "08", "32", - "FCC", "2.4G", "20M", "HT", "2T", "09", "32", - "ETSI", "2.4G", "20M", "HT", "2T", "09", "32", - "MKK", "2.4G", "20M", "HT", "2T", "09", "32", - "FCC", "2.4G", "20M", "HT", "2T", "10", "32", - "ETSI", "2.4G", "20M", "HT", "2T", "10", "32", - "MKK", "2.4G", "20M", "HT", "2T", "10", "32", - "FCC", "2.4G", "20M", "HT", "2T", "11", "30", - "ETSI", "2.4G", "20M", "HT", "2T", "11", "32", - "MKK", "2.4G", "20M", "HT", "2T", "11", "32", - "FCC", "2.4G", "20M", "HT", "2T", "12", "63", - "ETSI", "2.4G", "20M", "HT", "2T", "12", "32", - "MKK", "2.4G", "20M", "HT", "2T", "12", "32", - "FCC", "2.4G", "20M", "HT", "2T", "13", "63", - "ETSI", "2.4G", "20M", "HT", "2T", "13", "32", - "MKK", "2.4G", "20M", "HT", "2T", "13", "32", - "FCC", "2.4G", "20M", "HT", "2T", "14", "63", - "ETSI", "2.4G", "20M", "HT", "2T", "14", "63", - "MKK", "2.4G", "20M", "HT", "2T", "14", "63", - "FCC", "2.4G", "40M", "HT", "1T", "01", "63", - "ETSI", "2.4G", "40M", "HT", "1T", "01", "63", - "MKK", "2.4G", "40M", "HT", "1T", "01", "63", - "FCC", "2.4G", "40M", "HT", "1T", "02", "63", - "ETSI", "2.4G", "40M", "HT", "1T", "02", "63", - "MKK", "2.4G", "40M", "HT", "1T", "02", "63", - "FCC", "2.4G", "40M", "HT", "1T", "03", "26", - "ETSI", "2.4G", "40M", "HT", "1T", "03", "32", - "MKK", "2.4G", "40M", "HT", "1T", "03", "32", - "FCC", "2.4G", "40M", "HT", "1T", "04", "26", - "ETSI", "2.4G", "40M", "HT", "1T", "04", "32", - "MKK", "2.4G", "40M", "HT", "1T", "04", "32", - "FCC", "2.4G", "40M", "HT", "1T", "05", "32", - "ETSI", "2.4G", "40M", "HT", "1T", "05", "32", - "MKK", "2.4G", "40M", "HT", "1T", "05", "32", - "FCC", "2.4G", "40M", "HT", "1T", "06", "32", - "ETSI", "2.4G", "40M", "HT", "1T", "06", "32", - "MKK", "2.4G", "40M", "HT", "1T", "06", "32", - "FCC", "2.4G", "40M", "HT", "1T", "07", "32", - "ETSI", "2.4G", "40M", "HT", "1T", "07", "32", - "MKK", "2.4G", "40M", "HT", "1T", "07", "32", - "FCC", "2.4G", "40M", "HT", "1T", "08", "26", - "ETSI", "2.4G", "40M", "HT", "1T", "08", "32", - "MKK", "2.4G", "40M", "HT", "1T", "08", "32", - "FCC", "2.4G", "40M", "HT", "1T", "09", "26", - "ETSI", "2.4G", "40M", "HT", "1T", "09", "32", - "MKK", "2.4G", "40M", "HT", "1T", "09", "32", - "FCC", "2.4G", "40M", "HT", "1T", "10", "26", - "ETSI", "2.4G", "40M", "HT", "1T", "10", "32", - "MKK", "2.4G", "40M", "HT", "1T", "10", "32", - "FCC", "2.4G", "40M", "HT", "1T", "11", "26", - "ETSI", "2.4G", "40M", "HT", "1T", "11", "32", - "MKK", "2.4G", "40M", "HT", "1T", "11", "32", - "FCC", "2.4G", "40M", "HT", "1T", "12", "63", - "ETSI", "2.4G", "40M", "HT", "1T", "12", "32", - "MKK", "2.4G", "40M", "HT", "1T", "12", "32", - "FCC", "2.4G", "40M", "HT", "1T", "13", "63", - "ETSI", "2.4G", "40M", "HT", "1T", "13", "32", - "MKK", "2.4G", "40M", "HT", "1T", "13", "32", - "FCC", "2.4G", "40M", "HT", "1T", "14", "63", - "ETSI", "2.4G", "40M", "HT", "1T", "14", "63", - "MKK", "2.4G", "40M", "HT", "1T", "14", "63", - "FCC", "2.4G", "40M", "HT", "2T", "01", "63", - "ETSI", "2.4G", "40M", "HT", "2T", "01", "63", - "MKK", "2.4G", "40M", "HT", "2T", "01", "63", - "FCC", "2.4G", "40M", "HT", "2T", "02", "63", - "ETSI", "2.4G", "40M", "HT", "2T", "02", "63", - "MKK", "2.4G", "40M", "HT", "2T", "02", "63", - "FCC", "2.4G", "40M", "HT", "2T", "03", "30", - "ETSI", "2.4G", "40M", "HT", "2T", "03", "30", - "MKK", "2.4G", "40M", "HT", "2T", "03", "30", - "FCC", "2.4G", "40M", "HT", "2T", "04", "32", - "ETSI", "2.4G", "40M", "HT", "2T", "04", "30", - "MKK", "2.4G", "40M", "HT", "2T", "04", "30", - "FCC", "2.4G", "40M", "HT", "2T", "05", "32", - "ETSI", "2.4G", "40M", "HT", "2T", "05", "30", - "MKK", "2.4G", "40M", "HT", "2T", "05", "30", - "FCC", "2.4G", "40M", "HT", "2T", "06", "32", - "ETSI", "2.4G", "40M", "HT", "2T", "06", "30", - "MKK", "2.4G", "40M", "HT", "2T", "06", "30", - "FCC", "2.4G", "40M", "HT", "2T", "07", "32", - "ETSI", "2.4G", "40M", "HT", "2T", "07", "30", - "MKK", "2.4G", "40M", "HT", "2T", "07", "30", - "FCC", "2.4G", "40M", "HT", "2T", "08", "32", - "ETSI", "2.4G", "40M", "HT", "2T", "08", "30", - "MKK", "2.4G", "40M", "HT", "2T", "08", "30", - "FCC", "2.4G", "40M", "HT", "2T", "09", "32", - "ETSI", "2.4G", "40M", "HT", "2T", "09", "30", - "MKK", "2.4G", "40M", "HT", "2T", "09", "30", - "FCC", "2.4G", "40M", "HT", "2T", "10", "32", - "ETSI", "2.4G", "40M", "HT", "2T", "10", "30", - "MKK", "2.4G", "40M", "HT", "2T", "10", "30", - "FCC", "2.4G", "40M", "HT", "2T", "11", "30", - "ETSI", "2.4G", "40M", "HT", "2T", "11", "30", - "MKK", "2.4G", "40M", "HT", "2T", "11", "30", - "FCC", "2.4G", "40M", "HT", "2T", "12", "63", - "ETSI", "2.4G", "40M", "HT", "2T", "12", "32", - "MKK", "2.4G", "40M", "HT", "2T", "12", "32", - "FCC", "2.4G", "40M", "HT", "2T", "13", "63", - "ETSI", "2.4G", "40M", "HT", "2T", "13", "32", - "MKK", "2.4G", "40M", "HT", "2T", "13", "32", - "FCC", "2.4G", "40M", "HT", "2T", "14", "63", - "ETSI", "2.4G", "40M", "HT", "2T", "14", "63", - "MKK", "2.4G", "40M", "HT", "2T", "14", "63" + "FCC", "20M", "CCK", "1T", "01", "32", + "ETSI", "20M", "CCK", "1T", "01", "32", + "MKK", "20M", "CCK", "1T", "01", "32", + "FCC", "20M", "CCK", "1T", "02", "32", + "ETSI", "20M", "CCK", "1T", "02", "32", + "MKK", "20M", "CCK", "1T", "02", "32", + "FCC", "20M", "CCK", "1T", "03", "32", + "ETSI", "20M", "CCK", "1T", "03", "32", + "MKK", "20M", "CCK", "1T", "03", "32", + "FCC", "20M", "CCK", "1T", "04", "32", + "ETSI", "20M", "CCK", "1T", "04", "32", + "MKK", "20M", "CCK", "1T", "04", "32", + "FCC", "20M", "CCK", "1T", "05", "32", + "ETSI", "20M", "CCK", "1T", "05", "32", + "MKK", "20M", "CCK", "1T", "05", "32", + "FCC", "20M", "CCK", "1T", "06", "32", + "ETSI", "20M", "CCK", "1T", "06", "32", + "MKK", "20M", "CCK", "1T", "06", "32", + "FCC", "20M", "CCK", "1T", "07", "32", + "ETSI", "20M", "CCK", "1T", "07", "32", + "MKK", "20M", "CCK", "1T", "07", "32", + "FCC", "20M", "CCK", "1T", "08", "32", + "ETSI", "20M", "CCK", "1T", "08", "32", + "MKK", "20M", "CCK", "1T", "08", "32", + "FCC", "20M", "CCK", "1T", "09", "32", + "ETSI", "20M", "CCK", "1T", "09", "32", + "MKK", "20M", "CCK", "1T", "09", "32", + "FCC", "20M", "CCK", "1T", "10", "32", + "ETSI", "20M", "CCK", "1T", "10", "32", + "MKK", "20M", "CCK", "1T", "10", "32", + "FCC", "20M", "CCK", "1T", "11", "32", + "ETSI", "20M", "CCK", "1T", "11", "32", + "MKK", "20M", "CCK", "1T", "11", "32", + "FCC", "20M", "CCK", "1T", "12", "63", + "ETSI", "20M", "CCK", "1T", "12", "32", + "MKK", "20M", "CCK", "1T", "12", "32", + "FCC", "20M", "CCK", "1T", "13", "63", + "ETSI", "20M", "CCK", "1T", "13", "32", + "MKK", "20M", "CCK", "1T", "13", "32", + "FCC", "20M", "CCK", "1T", "14", "63", + "ETSI", "20M", "CCK", "1T", "14", "63", + "MKK", "20M", "CCK", "1T", "14", "32", + "FCC", "20M", "OFDM", "1T", "01", "28", + "ETSI", "20M", "OFDM", "1T", "01", "32", + "MKK", "20M", "OFDM", "1T", "01", "32", + "FCC", "20M", "OFDM", "1T", "02", "28", + "ETSI", "20M", "OFDM", "1T", "02", "32", + "MKK", "20M", "OFDM", "1T", "02", "32", + "FCC", "20M", "OFDM", "1T", "03", "32", + "ETSI", "20M", "OFDM", "1T", "03", "32", + "MKK", "20M", "OFDM", "1T", "03", "32", + "FCC", "20M", "OFDM", "1T", "04", "32", + "ETSI", "20M", "OFDM", "1T", "04", "32", + "MKK", "20M", "OFDM", "1T", "04", "32", + "FCC", "20M", "OFDM", "1T", "05", "32", + "ETSI", "20M", "OFDM", "1T", "05", "32", + "MKK", "20M", "OFDM", "1T", "05", "32", + "FCC", "20M", "OFDM", "1T", "06", "32", + "ETSI", "20M", "OFDM", "1T", "06", "32", + "MKK", "20M", "OFDM", "1T", "06", "32", + "FCC", "20M", "OFDM", "1T", "07", "32", + "ETSI", "20M", "OFDM", "1T", "07", "32", + "MKK", "20M", "OFDM", "1T", "07", "32", + "FCC", "20M", "OFDM", "1T", "08", "32", + "ETSI", "20M", "OFDM", "1T", "08", "32", + "MKK", "20M", "OFDM", "1T", "08", "32", + "FCC", "20M", "OFDM", "1T", "09", "32", + "ETSI", "20M", "OFDM", "1T", "09", "32", + "MKK", "20M", "OFDM", "1T", "09", "32", + "FCC", "20M", "OFDM", "1T", "10", "28", + "ETSI", "20M", "OFDM", "1T", "10", "32", + "MKK", "20M", "OFDM", "1T", "10", "32", + "FCC", "20M", "OFDM", "1T", "11", "28", + "ETSI", "20M", "OFDM", "1T", "11", "32", + "MKK", "20M", "OFDM", "1T", "11", "32", + "FCC", "20M", "OFDM", "1T", "12", "63", + "ETSI", "20M", "OFDM", "1T", "12", "32", + "MKK", "20M", "OFDM", "1T", "12", "32", + "FCC", "20M", "OFDM", "1T", "13", "63", + "ETSI", "20M", "OFDM", "1T", "13", "32", + "MKK", "20M", "OFDM", "1T", "13", "32", + "FCC", "20M", "OFDM", "1T", "14", "63", + "ETSI", "20M", "OFDM", "1T", "14", "63", + "MKK", "20M", "OFDM", "1T", "14", "63", + "FCC", "20M", "HT", "1T", "01", "26", + "ETSI", "20M", "HT", "1T", "01", "32", + "MKK", "20M", "HT", "1T", "01", "32", + "FCC", "20M", "HT", "1T", "02", "26", + "ETSI", "20M", "HT", "1T", "02", "32", + "MKK", "20M", "HT", "1T", "02", "32", + "FCC", "20M", "HT", "1T", "03", "32", + "ETSI", "20M", "HT", "1T", "03", "32", + "MKK", "20M", "HT", "1T", "03", "32", + "FCC", "20M", "HT", "1T", "04", "32", + "ETSI", "20M", "HT", "1T", "04", "32", + "MKK", "20M", "HT", "1T", "04", "32", + "FCC", "20M", "HT", "1T", "05", "32", + "ETSI", "20M", "HT", "1T", "05", "32", + "MKK", "20M", "HT", "1T", "05", "32", + "FCC", "20M", "HT", "1T", "06", "32", + "ETSI", "20M", "HT", "1T", "06", "32", + "MKK", "20M", "HT", "1T", "06", "32", + "FCC", "20M", "HT", "1T", "07", "32", + "ETSI", "20M", "HT", "1T", "07", "32", + "MKK", "20M", "HT", "1T", "07", "32", + "FCC", "20M", "HT", "1T", "08", "32", + "ETSI", "20M", "HT", "1T", "08", "32", + "MKK", "20M", "HT", "1T", "08", "32", + "FCC", "20M", "HT", "1T", "09", "32", + "ETSI", "20M", "HT", "1T", "09", "32", + "MKK", "20M", "HT", "1T", "09", "32", + "FCC", "20M", "HT", "1T", "10", "26", + "ETSI", "20M", "HT", "1T", "10", "32", + "MKK", "20M", "HT", "1T", "10", "32", + "FCC", "20M", "HT", "1T", "11", "26", + "ETSI", "20M", "HT", "1T", "11", "32", + "MKK", "20M", "HT", "1T", "11", "32", + "FCC", "20M", "HT", "1T", "12", "63", + "ETSI", "20M", "HT", "1T", "12", "32", + "MKK", "20M", "HT", "1T", "12", "32", + "FCC", "20M", "HT", "1T", "13", "63", + "ETSI", "20M", "HT", "1T", "13", "32", + "MKK", "20M", "HT", "1T", "13", "32", + "FCC", "20M", "HT", "1T", "14", "63", + "ETSI", "20M", "HT", "1T", "14", "63", + "MKK", "20M", "HT", "1T", "14", "63", + "FCC", "20M", "HT", "2T", "01", "30", + "ETSI", "20M", "HT", "2T", "01", "32", + "MKK", "20M", "HT", "2T", "01", "32", + "FCC", "20M", "HT", "2T", "02", "32", + "ETSI", "20M", "HT", "2T", "02", "32", + "MKK", "20M", "HT", "2T", "02", "32", + "FCC", "20M", "HT", "2T", "03", "32", + "ETSI", "20M", "HT", "2T", "03", "32", + "MKK", "20M", "HT", "2T", "03", "32", + "FCC", "20M", "HT", "2T", "04", "32", + "ETSI", "20M", "HT", "2T", "04", "32", + "MKK", "20M", "HT", "2T", "04", "32", + "FCC", "20M", "HT", "2T", "05", "32", + "ETSI", "20M", "HT", "2T", "05", "32", + "MKK", "20M", "HT", "2T", "05", "32", + "FCC", "20M", "HT", "2T", "06", "32", + "ETSI", "20M", "HT", "2T", "06", "32", + "MKK", "20M", "HT", "2T", "06", "32", + "FCC", "20M", "HT", "2T", "07", "32", + "ETSI", "20M", "HT", "2T", "07", "32", + "MKK", "20M", "HT", "2T", "07", "32", + "FCC", "20M", "HT", "2T", "08", "32", + "ETSI", "20M", "HT", "2T", "08", "32", + "MKK", "20M", "HT", "2T", "08", "32", + "FCC", "20M", "HT", "2T", "09", "32", + "ETSI", "20M", "HT", "2T", "09", "32", + "MKK", "20M", "HT", "2T", "09", "32", + "FCC", "20M", "HT", "2T", "10", "32", + "ETSI", "20M", "HT", "2T", "10", "32", + "MKK", "20M", "HT", "2T", "10", "32", + "FCC", "20M", "HT", "2T", "11", "30", + "ETSI", "20M", "HT", "2T", "11", "32", + "MKK", "20M", "HT", "2T", "11", "32", + "FCC", "20M", "HT", "2T", "12", "63", + "ETSI", "20M", "HT", "2T", "12", "32", + "MKK", "20M", "HT", "2T", "12", "32", + "FCC", "20M", "HT", "2T", "13", "63", + "ETSI", "20M", "HT", "2T", "13", "32", + "MKK", "20M", "HT", "2T", "13", "32", + "FCC", "20M", "HT", "2T", "14", "63", + "ETSI", "20M", "HT", "2T", "14", "63", + "MKK", "20M", "HT", "2T", "14", "63", + "FCC", "40M", "HT", "1T", "01", "63", + "ETSI", "40M", "HT", "1T", "01", "63", + "MKK", "40M", "HT", "1T", "01", "63", + "FCC", "40M", "HT", "1T", "02", "63", + "ETSI", "40M", "HT", "1T", "02", "63", + "MKK", "40M", "HT", "1T", "02", "63", + "FCC", "40M", "HT", "1T", "03", "26", + "ETSI", "40M", "HT", "1T", "03", "32", + "MKK", "40M", "HT", "1T", "03", "32", + "FCC", "40M", "HT", "1T", "04", "26", + "ETSI", "40M", "HT", "1T", "04", "32", + "MKK", "40M", "HT", "1T", "04", "32", + "FCC", "40M", "HT", "1T", "05", "32", + "ETSI", "40M", "HT", "1T", "05", "32", + "MKK", "40M", "HT", "1T", "05", "32", + "FCC", "40M", "HT", "1T", "06", "32", + "ETSI", "40M", "HT", "1T", "06", "32", + "MKK", "40M", "HT", "1T", "06", "32", + "FCC", "40M", "HT", "1T", "07", "32", + "ETSI", "40M", "HT", "1T", "07", "32", + "MKK", "40M", "HT", "1T", "07", "32", + "FCC", "40M", "HT", "1T", "08", "26", + "ETSI", "40M", "HT", "1T", "08", "32", + "MKK", "40M", "HT", "1T", "08", "32", + "FCC", "40M", "HT", "1T", "09", "26", + "ETSI", "40M", "HT", "1T", "09", "32", + "MKK", "40M", "HT", "1T", "09", "32", + "FCC", "40M", "HT", "1T", "10", "26", + "ETSI", "40M", "HT", "1T", "10", "32", + "MKK", "40M", "HT", "1T", "10", "32", + "FCC", "40M", "HT", "1T", "11", "26", + "ETSI", "40M", "HT", "1T", "11", "32", + "MKK", "40M", "HT", "1T", "11", "32", + "FCC", "40M", "HT", "1T", "12", "63", + "ETSI", "40M", "HT", "1T", "12", "32", + "MKK", "40M", "HT", "1T", "12", "32", + "FCC", "40M", "HT", "1T", "13", "63", + "ETSI", "40M", "HT", "1T", "13", "32", + "MKK", "40M", "HT", "1T", "13", "32", + "FCC", "40M", "HT", "1T", "14", "63", + "ETSI", "40M", "HT", "1T", "14", "63", + "MKK", "40M", "HT", "1T", "14", "63", + "FCC", "40M", "HT", "2T", "01", "63", + "ETSI", "40M", "HT", "2T", "01", "63", + "MKK", "40M", "HT", "2T", "01", "63", + "FCC", "40M", "HT", "2T", "02", "63", + "ETSI", "40M", "HT", "2T", "02", "63", + "MKK", "40M", "HT", "2T", "02", "63", + "FCC", "40M", "HT", "2T", "03", "30", + "ETSI", "40M", "HT", "2T", "03", "30", + "MKK", "40M", "HT", "2T", "03", "30", + "FCC", "40M", "HT", "2T", "04", "32", + "ETSI", "40M", "HT", "2T", "04", "30", + "MKK", "40M", "HT", "2T", "04", "30", + "FCC", "40M", "HT", "2T", "05", "32", + "ETSI", "40M", "HT", "2T", "05", "30", + "MKK", "40M", "HT", "2T", "05", "30", + "FCC", "40M", "HT", "2T", "06", "32", + "ETSI", "40M", "HT", "2T", "06", "30", + "MKK", "40M", "HT", "2T", "06", "30", + "FCC", "40M", "HT", "2T", "07", "32", + "ETSI", "40M", "HT", "2T", "07", "30", + "MKK", "40M", "HT", "2T", "07", "30", + "FCC", "40M", "HT", "2T", "08", "32", + "ETSI", "40M", "HT", "2T", "08", "30", + "MKK", "40M", "HT", "2T", "08", "30", + "FCC", "40M", "HT", "2T", "09", "32", + "ETSI", "40M", "HT", "2T", "09", "30", + "MKK", "40M", "HT", "2T", "09", "30", + "FCC", "40M", "HT", "2T", "10", "32", + "ETSI", "40M", "HT", "2T", "10", "30", + "MKK", "40M", "HT", "2T", "10", "30", + "FCC", "40M", "HT", "2T", "11", "30", + "ETSI", "40M", "HT", "2T", "11", "30", + "MKK", "40M", "HT", "2T", "11", "30", + "FCC", "40M", "HT", "2T", "12", "63", + "ETSI", "40M", "HT", "2T", "12", "32", + "MKK", "40M", "HT", "2T", "12", "32", + "FCC", "40M", "HT", "2T", "13", "63", + "ETSI", "40M", "HT", "2T", "13", "32", + "MKK", "40M", "HT", "2T", "13", "32", + "FCC", "40M", "HT", "2T", "14", "63", + "ETSI", "40M", "HT", "2T", "14", "63", + "MKK", "40M", "HT", "2T", "14", "63" }; void ODM_ReadAndConfig_MP_8723B_TXPWR_LMT(struct dm_odm_t *pDM_Odm) @@ -760,26 +627,17 @@ void ODM_ReadAndConfig_MP_8723B_TXPWR_LMT(struct dm_odm_t *pDM_Odm) u32 i = 0; u8 **Array = Array_MP_8723B_TXPWR_LMT; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_LOUD, - ("===> ODM_ReadAndConfig_MP_8723B_TXPWR_LMT\n") - ); - - for (i = 0; i < ARRAY_SIZE(Array_MP_8723B_TXPWR_LMT); i += 7) { + for (i = 0; i < ARRAY_SIZE(Array_MP_8723B_TXPWR_LMT); i += 6) { u8 *regulation = Array[i]; - u8 *band = Array[i+1]; - u8 *bandwidth = Array[i+2]; - u8 *rate = Array[i+3]; - u8 *rfPath = Array[i+4]; - u8 *chnl = Array[i+5]; - u8 *val = Array[i+6]; + u8 *bandwidth = Array[i+1]; + u8 *rate = Array[i+2]; + u8 *rfPath = Array[i+3]; + u8 *chnl = Array[i+4]; + u8 *val = Array[i+5]; odm_ConfigBB_TXPWR_LMT_8723B( pDM_Odm, regulation, - band, bandwidth, rate, rfPath, diff --git a/drivers/staging/rtl8723bs/hal/HalPhyRf.c b/drivers/staging/rtl8723bs/hal/HalPhyRf.c index 14426151faae..365e1195b5e5 100644 --- a/drivers/staging/rtl8723bs/hal/HalPhyRf.c +++ b/drivers/staging/rtl8723bs/hal/HalPhyRf.c @@ -76,7 +76,7 @@ void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter) struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - u8 ThermalValue = 0, delta, delta_LCK, delta_IQK, p = 0, i = 0; + u8 ThermalValue = 0, delta, delta_LCK, p = 0, i = 0; u8 ThermalValue_AVG_count = 0; u32 ThermalValue_AVG = 0; @@ -108,18 +108,6 @@ void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter) pDM_Odm->RFCalibrateInfo.TXPowerTrackingCallbackCnt++; pDM_Odm->RFCalibrateInfo.bTXPowerTrackingInit = true; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "===>ODM_TXPowerTrackingCallback_ThermalMeter,\npDM_Odm->BbSwingIdxCckBase: %d, pDM_Odm->BbSwingIdxOfdmBase[A]: %d, pDM_Odm->DefaultOfdmIndex: %d\n", - pDM_Odm->BbSwingIdxCckBase, - pDM_Odm->BbSwingIdxOfdmBase[ODM_RF_PATH_A], - pDM_Odm->DefaultOfdmIndex - ) - ); - ThermalValue = (u8)PHY_QueryRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, c.ThermalRegAddr, 0xfc00); /* 0x42: RF Reg[15:10] 88E */ if ( !pDM_Odm->RFCalibrateInfo.TxPowerTrackControl || @@ -130,13 +118,6 @@ void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter) /* 4 3. Initialize ThermalValues of RFCalibrateInfo */ - if (pDM_Odm->RFCalibrateInfo.bReloadtxpowerindex) - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, - ("reload ofdm index for band switch\n") - ); - /* 4 4. Calculate average thermal meter */ pDM_Odm->RFCalibrateInfo.ThermalValue_AVG[pDM_Odm->RFCalibrateInfo.ThermalValue_AVG_index] = ThermalValue; @@ -154,19 +135,9 @@ void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter) /* Calculate Average ThermalValue after average enough times */ if (ThermalValue_AVG_count) { ThermalValue = (u8)(ThermalValue_AVG / ThermalValue_AVG_count); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n", - ThermalValue, - pHalData->EEPROMThermalMeter - ) - ); } - /* 4 5. Calculate delta, delta_LCK, delta_IQK. */ + /* 4 5. Calculate delta, delta_LCK */ /* delta" here is used to determine whether thermal value changes or not. */ delta = (ThermalValue > pDM_Odm->RFCalibrateInfo.ThermalValue) ? @@ -176,36 +147,10 @@ void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter) (ThermalValue > pDM_Odm->RFCalibrateInfo.ThermalValue_LCK) ? (ThermalValue - pDM_Odm->RFCalibrateInfo.ThermalValue_LCK) : (pDM_Odm->RFCalibrateInfo.ThermalValue_LCK - ThermalValue); - delta_IQK = - (ThermalValue > pDM_Odm->RFCalibrateInfo.ThermalValue_IQK) ? - (ThermalValue - pDM_Odm->RFCalibrateInfo.ThermalValue_IQK) : - (pDM_Odm->RFCalibrateInfo.ThermalValue_IQK - ThermalValue); - - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n", - delta, - delta_LCK, - delta_IQK - ) - ); /* 4 6. If necessary, do LCK. */ /* Delta temperature is equal to or larger than 20 centigrade. */ if (delta_LCK >= c.Threshold_IQK) { - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "delta_LCK(%d) >= Threshold_IQK(%d)\n", - delta_LCK, - c.Threshold_IQK - ) - ); pDM_Odm->RFCalibrateInfo.ThermalValue_LCK = ThermalValue; if (c.PHY_LCCalibrate) (*c.PHY_LCCalibrate)(pDM_Odm); @@ -224,16 +169,6 @@ void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter) /* 4 7.1 The Final Power Index = BaseIndex + PowerIndexOffset */ if (ThermalValue > pHalData->EEPROMThermalMeter) { - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "deltaSwingTableIdx_TUP_A[%d] = %d\n", - delta, - deltaSwingTableIdx_TUP_A[delta] - ) - ); pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[ODM_RF_PATH_A] = pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_A]; pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_A] = @@ -243,27 +178,7 @@ void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter) pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = deltaSwingTableIdx_TUP_A[delta]; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", - pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] - ) - ); - if (c.RfPathCount > 1) { - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "deltaSwingTableIdx_TUP_B[%d] = %d\n", - delta, - deltaSwingTableIdx_TUP_B[delta] - ) - ); pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[ODM_RF_PATH_B] = pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_B]; pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_B] = @@ -272,29 +187,9 @@ void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter) /* Record delta swing for mix mode power tracking */ pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = deltaSwingTableIdx_TUP_B[delta]; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n", - pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] - ) - ); } } else { - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "deltaSwingTableIdx_TDOWN_A[%d] = %d\n", - delta, - deltaSwingTableIdx_TDOWN_A[delta] - ) - ); - pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[ODM_RF_PATH_A] = pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_A]; pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_A] = @@ -304,28 +199,7 @@ void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter) pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = -1 * deltaSwingTableIdx_TDOWN_A[delta]; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", - pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] - ) - ); - if (c.RfPathCount > 1) { - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "deltaSwingTableIdx_TDOWN_B[%d] = %d\n", - delta, - deltaSwingTableIdx_TDOWN_B[delta] - ) - ); - pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[ODM_RF_PATH_B] = pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_B]; pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[ODM_RF_PATH_B] = @@ -334,30 +208,10 @@ void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter) /* Record delta swing for mix mode power tracking */ pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = -1 * deltaSwingTableIdx_TDOWN_B[delta]; - - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n", - pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] - ) - ); } } for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) { - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "\n\n ================================ [Path-%c] Calculating PowerIndexOffset ================================\n", - (p == ODM_RF_PATH_A ? 'A' : 'B') - ) - ); - if ( pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[p] == pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[p] @@ -366,20 +220,6 @@ void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter) else pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] = pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[p] - pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[p]; /* Power Index Diff between 2 times Power Tracking */ - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "[Path-%c] PowerIndexOffset(%d) = DeltaPowerIndex(%d) - DeltaPowerIndexLast(%d)\n", - ( - p == ODM_RF_PATH_A ? 'A' : 'B'), - pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p], - pDM_Odm->RFCalibrateInfo.DeltaPowerIndex[p], - pDM_Odm->RFCalibrateInfo.DeltaPowerIndexLast[p] - ) - ); - pDM_Odm->RFCalibrateInfo.OFDM_index[p] = pDM_Odm->BbSwingIdxOfdmBase[p] + pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p]; @@ -394,87 +234,23 @@ void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter) pDM_Odm->BbSwingIdxOfdm[p] = pDM_Odm->RFCalibrateInfo.OFDM_index[p]; - /* *************Print BB Swing Base and Index Offset************* */ - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n", - pDM_Odm->BbSwingIdxCck, - pDM_Odm->BbSwingIdxCckBase, - pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] - ) - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n", - pDM_Odm->BbSwingIdxOfdm[p], - (p == ODM_RF_PATH_A ? 'A' : 'B'), - pDM_Odm->BbSwingIdxOfdmBase[p], - pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] - ) - ); - /* 4 7.1 Handle boundary conditions of index. */ if (pDM_Odm->RFCalibrateInfo.OFDM_index[p] > c.SwingTableSize_OFDM-1) pDM_Odm->RFCalibrateInfo.OFDM_index[p] = c.SwingTableSize_OFDM-1; else if (pDM_Odm->RFCalibrateInfo.OFDM_index[p] < OFDM_min_index) pDM_Odm->RFCalibrateInfo.OFDM_index[p] = OFDM_min_index; } - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ("\n\n ========================================================================================================\n") - ); if (pDM_Odm->RFCalibrateInfo.CCK_index > c.SwingTableSize_CCK-1) pDM_Odm->RFCalibrateInfo.CCK_index = c.SwingTableSize_CCK-1; /* else if (pDM_Odm->RFCalibrateInfo.CCK_index < 0) */ /* pDM_Odm->RFCalibrateInfo.CCK_index = 0; */ } else { - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "The thermal meter is unchanged or TxPowerTracking OFF(%d): ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n", - pDM_Odm->RFCalibrateInfo.TxPowerTrackControl, - ThermalValue, - pDM_Odm->RFCalibrateInfo.ThermalValue - ) - ); - for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) pDM_Odm->RFCalibrateInfo.PowerIndexOffset[p] = 0; } - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "TxPowerTracking: [CCK] Swing Current Index: %d, Swing Base Index: %d\n", - pDM_Odm->RFCalibrateInfo.CCK_index, - pDM_Odm->BbSwingIdxCckBase - ) - ); /* Print Swing base & current */ for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) { - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "TxPowerTracking: [OFDM] Swing Current Index: %d, Swing Base Index[%c]: %d\n", - pDM_Odm->RFCalibrateInfo.OFDM_index[p], - (p == ODM_RF_PATH_A ? 'A' : 'B'), - pDM_Odm->BbSwingIdxOfdmBase[p] - ) - ); } if ( @@ -490,106 +266,11 @@ void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter) /* to increase TX power. Otherwise, EVM will be bad. */ /* */ /* 2012/04/25 MH Add for tx power tracking to set tx power in tx agc for 88E. */ - if (ThermalValue > pDM_Odm->RFCalibrateInfo.ThermalValue) { - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "Temperature Increasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", - pDM_Odm->RFCalibrateInfo.PowerIndexOffset[ODM_RF_PATH_A], - delta, - ThermalValue, - pHalData->EEPROMThermalMeter, - pDM_Odm->RFCalibrateInfo.ThermalValue - ) - ); - - if (c.RfPathCount > 1) - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "Temperature Increasing(B): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", - pDM_Odm->RFCalibrateInfo.PowerIndexOffset[ODM_RF_PATH_B], - delta, - ThermalValue, - pHalData->EEPROMThermalMeter, - pDM_Odm->RFCalibrateInfo.ThermalValue - ) - ); - - } else if (ThermalValue < pDM_Odm->RFCalibrateInfo.ThermalValue) { /* Low temperature */ - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", - pDM_Odm->RFCalibrateInfo.PowerIndexOffset[ODM_RF_PATH_A], - delta, - ThermalValue, - pHalData->EEPROMThermalMeter, - pDM_Odm->RFCalibrateInfo.ThermalValue - ) - ); - - if (c.RfPathCount > 1) - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "Temperature Decreasing(B): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", - pDM_Odm->RFCalibrateInfo.PowerIndexOffset[ODM_RF_PATH_B], - delta, - ThermalValue, - pHalData->EEPROMThermalMeter, - pDM_Odm->RFCalibrateInfo.ThermalValue - ) - ); - - } if (ThermalValue > pHalData->EEPROMThermalMeter) { - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "Temperature(%d) higher than PG value(%d)\n", - ThermalValue, - pHalData->EEPROMThermalMeter - ) - ); - - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ("**********Enter POWER Tracking MIX_MODE**********\n") - ); for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) (*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, MIX_MODE, p, 0); } else { - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ( - "Temperature(%d) lower than PG value(%d)\n", - ThermalValue, - pHalData->EEPROMThermalMeter - ) - ); - - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ("**********Enter POWER Tracking MIX_MODE**********\n") - ); for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) (*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, MIX_MODE, p, Indexforchannel); } @@ -599,26 +280,9 @@ void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter) for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) pDM_Odm->BbSwingIdxOfdmBase[p] = pDM_Odm->BbSwingIdxOfdm[p]; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, - ( - "pDM_Odm->RFCalibrateInfo.ThermalValue = %d ThermalValue = %d\n", - pDM_Odm->RFCalibrateInfo.ThermalValue, - ThermalValue - ) - ); - /* Record last Power Tracking Thermal Value */ pDM_Odm->RFCalibrateInfo.ThermalValue = ThermalValue; } - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_TX_PWR_TRACK, - ODM_DBG_LOUD, - ("<===ODM_TXPowerTrackingCallback_ThermalMeter\n") - ); - pDM_Odm->RFCalibrateInfo.TXPowercount = 0; } diff --git a/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c b/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c index c70b9cf2da32..8121b8eb45b6 100644 --- a/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c +++ b/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c @@ -69,7 +69,7 @@ static void setIqkMatrix_8723B( ele_D = (OFDMSwingTable_New[OFDM_index] & 0xFFC00000)>>22; /* new element A = element D x X */ - if ((IqkResult_X != 0) && (*(pDM_Odm->pBandType) == ODM_BAND_2_4G)) { + if (IqkResult_X != 0) { if ((IqkResult_X & 0x00000200) != 0) /* consider minus */ IqkResult_X = IqkResult_X | 0xFFFFFC00; ele_A = ((IqkResult_X * ele_D)>>8)&0x000003FF; @@ -129,9 +129,6 @@ static void setIqkMatrix_8723B( break; } } - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("TxPwrTracking path B: X = 0x%x, Y = 0x%x ele_A = 0x%x ele_C = 0x%x ele_D = 0x%x 0xeb4 = 0x%x 0xebc = 0x%x\n", - (u32)IqkResult_X, (u32)IqkResult_Y, (u32)ele_A, (u32)ele_C, (u32)ele_D, (u32)IqkResult_X, (u32)IqkResult_Y)); } @@ -210,8 +207,6 @@ void ODM_TxPwrTrackSetPwr_8723B( } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("===>ODM_TxPwrTrackSetPwr8723B\n")); - if (TxRate != 0xFF) { /* 2 CCK */ if ((TxRate >= MGN_1M) && (TxRate <= MGN_11M)) @@ -233,13 +228,10 @@ void ODM_TxPwrTrackSetPwr_8723B( else PwrTrackingLimit_OFDM = pDM_Odm->DefaultOfdmIndex; /* Default OFDM index = 30 */ } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("TxRate = 0x%x, PwrTrackingLimit =%d\n", TxRate, PwrTrackingLimit_OFDM)); if (Method == TXAGC) { struct adapter *Adapter = pDM_Odm->Adapter; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("odm_TxPwrTrackSetPwr8723B CH =%d\n", *(pDM_Odm->pChannel))); - pDM_Odm->Remnant_OFDMSwingIdx[RFPath] = pDM_Odm->Absolute_OFDMSwingIdx[RFPath]; pDM_Odm->Modify_TxAGC_Flag_PathA = true; @@ -270,10 +262,6 @@ void ODM_TxPwrTrackSetPwr_8723B( setCCKFilterCoefficient(pDM_Odm, Final_CCK_Swing_Index); } else if (Method == MIX_MODE) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, - ("pDM_Odm->DefaultOfdmIndex =%d, pDM_Odm->DefaultCCKIndex =%d, pDM_Odm->Absolute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n", - pDM_Odm->DefaultOfdmIndex, pDM_Odm->DefaultCckIndex, pDM_Odm->Absolute_OFDMSwingIdx[RFPath], RFPath)); - Final_OFDM_Swing_Index = pDM_Odm->DefaultOfdmIndex + pDM_Odm->Absolute_OFDMSwingIdx[RFPath]; Final_CCK_Swing_Index = pDM_Odm->DefaultCckIndex + pDM_Odm->Absolute_OFDMSwingIdx[RFPath]; @@ -287,10 +275,6 @@ void ODM_TxPwrTrackSetPwr_8723B( pDM_Odm->Modify_TxAGC_Flag_PathA = true; PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, OFDM); PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, HT_MCS0_MCS7); - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, - ("******Path_A Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n", - PwrTrackingLimit_OFDM, pDM_Odm->Remnant_OFDMSwingIdx[RFPath])); } else if (Final_OFDM_Swing_Index <= 0) { pDM_Odm->Remnant_OFDMSwingIdx[RFPath] = Final_OFDM_Swing_Index; @@ -301,26 +285,16 @@ void ODM_TxPwrTrackSetPwr_8723B( pDM_Odm->Modify_TxAGC_Flag_PathA = true; PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, OFDM); PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, HT_MCS0_MCS7); - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, - ("******Path_A Lower then BBSwing lower bound 0 , Remnant TxAGC Value = %d\n", - pDM_Odm->Remnant_OFDMSwingIdx[RFPath])); } else { setIqkMatrix_8723B(pDM_Odm, Final_OFDM_Swing_Index, RFPath, pDM_Odm->RFCalibrateInfo.IQKMatrixRegSetting[ChannelMappedIndex].Value[0][0], pDM_Odm->RFCalibrateInfo.IQKMatrixRegSetting[ChannelMappedIndex].Value[0][1]); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, - ("******Path_A Compensate with BBSwing , Final_OFDM_Swing_Index = %d\n", Final_OFDM_Swing_Index)); - if (pDM_Odm->Modify_TxAGC_Flag_PathA) { /* If TxAGC has changed, reset TxAGC again */ pDM_Odm->Remnant_OFDMSwingIdx[RFPath] = 0; PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, OFDM); PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, HT_MCS0_MCS7); pDM_Odm->Modify_TxAGC_Flag_PathA = false; - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, - ("******Path_A pDM_Odm->Modify_TxAGC_Flag = false\n")); } } @@ -329,30 +303,18 @@ void ODM_TxPwrTrackSetPwr_8723B( setCCKFilterCoefficient(pDM_Odm, PwrTrackingLimit_CCK); pDM_Odm->Modify_TxAGC_Flag_PathA_CCK = true; PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, CCK); - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, - ("******Path_A CCK Over Limit , PwrTrackingLimit_CCK = %d , pDM_Odm->Remnant_CCKSwingIdx = %d\n", PwrTrackingLimit_CCK, pDM_Odm->Remnant_CCKSwingIdx)); } else if (Final_CCK_Swing_Index <= 0) { /* Lowest CCK Index = 0 */ pDM_Odm->Remnant_CCKSwingIdx = Final_CCK_Swing_Index; setCCKFilterCoefficient(pDM_Odm, 0); pDM_Odm->Modify_TxAGC_Flag_PathA_CCK = true; PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, CCK); - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, - ("******Path_A CCK Under Limit , PwrTrackingLimit_CCK = %d , pDM_Odm->Remnant_CCKSwingIdx = %d\n", 0, pDM_Odm->Remnant_CCKSwingIdx)); } else { setCCKFilterCoefficient(pDM_Odm, Final_CCK_Swing_Index); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, - ("******Path_A CCK Compensate with BBSwing , Final_CCK_Swing_Index = %d\n", Final_CCK_Swing_Index)); - if (pDM_Odm->Modify_TxAGC_Flag_PathA_CCK) { /* If TxAGC has changed, reset TxAGC again */ pDM_Odm->Remnant_CCKSwingIdx = 0; PHY_SetTxPowerIndexByRateSection(Adapter, RFPath, pHalData->CurrentChannel, CCK); pDM_Odm->Modify_TxAGC_Flag_PathA_CCK = false; - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, - ("******Path_A pDM_Odm->Modify_TxAGC_Flag_CCK = false\n")); } } } else @@ -385,22 +347,7 @@ static void GetDeltaSwingTable_8723B( *TemperatureUP_B = pRFCalibrateInfo->DeltaSwingTableIdx_2GB_P; *TemperatureDOWN_B = pRFCalibrateInfo->DeltaSwingTableIdx_2GB_N; } - } /*else if (36 <= channel && channel <= 64) { - *TemperatureUP_A = pRFCalibrateInfo->DeltaSwingTableIdx_5GA_P[0]; - *TemperatureDOWN_A = pRFCalibrateInfo->DeltaSwingTableIdx_5GA_N[0]; - *TemperatureUP_B = pRFCalibrateInfo->DeltaSwingTableIdx_5GB_P[0]; - *TemperatureDOWN_B = pRFCalibrateInfo->DeltaSwingTableIdx_5GB_N[0]; - } else if (100 <= channel && channel <= 140) { - *TemperatureUP_A = pRFCalibrateInfo->DeltaSwingTableIdx_5GA_P[1]; - *TemperatureDOWN_A = pRFCalibrateInfo->DeltaSwingTableIdx_5GA_N[1]; - *TemperatureUP_B = pRFCalibrateInfo->DeltaSwingTableIdx_5GB_P[1]; - *TemperatureDOWN_B = pRFCalibrateInfo->DeltaSwingTableIdx_5GB_N[1]; - } else if (149 <= channel && channel <= 173) { - *TemperatureUP_A = pRFCalibrateInfo->DeltaSwingTableIdx_5GA_P[2]; - *TemperatureDOWN_A = pRFCalibrateInfo->DeltaSwingTableIdx_5GA_N[2]; - *TemperatureUP_B = pRFCalibrateInfo->DeltaSwingTableIdx_5GB_P[2]; - *TemperatureDOWN_B = pRFCalibrateInfo->DeltaSwingTableIdx_5GB_N[2]; - }*/else { + } else { *TemperatureUP_A = (u8 *)DeltaSwingTableIdx_2GA_P_8188E; *TemperatureDOWN_A = (u8 *)DeltaSwingTableIdx_2GA_N_8188E; *TemperatureUP_B = (u8 *)DeltaSwingTableIdx_2GA_P_8188E; @@ -442,8 +389,6 @@ static u8 phy_PathA_IQK_8723B( /* Save RF Path */ Path_SEL_BB = PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path A IQK!\n")); - /* leave IQK mode */ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000); @@ -461,7 +406,6 @@ static u8 phy_PathA_IQK_8723B( PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord, 0x01007c00); PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK, bMaskDWord, 0x01004800); /* path-A IQK setting */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path-A IQK setting!\n")); */ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_A, bMaskDWord, 0x18008c1c); PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_A, bMaskDWord, 0x38008c1c); PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c); @@ -473,7 +417,6 @@ static u8 phy_PathA_IQK_8723B( PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_B, bMaskDWord, 0x28110000); /* LO calibration setting */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LO calibration setting!\n")); */ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Rsp, bMaskDWord, 0x00462911); /* enter IQK mode */ @@ -491,12 +434,10 @@ static u8 phy_PathA_IQK_8723B( PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800); /* One shot, path A LOK & IQK */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("One shot, path A LOK & IQK!\n")); */ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000); PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000); /* delay x ms */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Delay %d ms for One shot, path A LOK & IQK.\n", IQK_DELAY_TIME_8723B)); */ /* PlatformStallExecution(IQK_DELAY_TIME_8723B*1000); */ mdelay(IQK_DELAY_TIME_8723B); @@ -513,11 +454,6 @@ static u8 phy_PathA_IQK_8723B( regEAC = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord); regE94 = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord); regE9C = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xeac = 0x%x\n", regEAC)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe94 = 0x%x, 0xe9c = 0x%x\n", regE94, regE9C)); - /* monitor image power before & after IQK */ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe90(before IQK) = 0x%x, 0xe98(afer IQK) = 0x%x\n", - PHY_QueryBBReg(pDM_Odm->Adapter, 0xe90, bMaskDWord), PHY_QueryBBReg(pDM_Odm->Adapter, 0xe98, bMaskDWord))); /* Allen 20131125 */ @@ -550,18 +486,13 @@ static u8 phy_PathA_RxIQK8723B( struct hal_com_data *pHalData = GET_HAL_DATA(padapter); struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path A Rx IQK!\n")); */ - /* Save RF Path */ Path_SEL_BB = PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord); /* leave IQK mode */ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000); - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path A RX IQK:Get TXIMR setting\n")); /* 1 Get TXIMR setting */ /* modify RXIQK mode table */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path-A Rx IQK modify RXIQK mode table!\n")); */ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1); PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000); PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f); @@ -587,7 +518,6 @@ static u8 phy_PathA_RxIQK8723B( PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_B, bMaskDWord, 0x28110000); /* LO calibration setting */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LO calibration setting!\n")); */ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911); /* enter IQK mode */ @@ -605,12 +535,10 @@ static u8 phy_PathA_RxIQK8723B( PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800); /* One shot, path A LOK & IQK */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("One shot, path A LOK & IQK!\n")); */ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000); PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000); /* delay x ms */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Delay %d ms for One shot, path A LOK & IQK.\n", IQK_DELAY_TIME_8723B)); */ /* PlatformStallExecution(IQK_DELAY_TIME_8723B*1000); */ mdelay(IQK_DELAY_TIME_8723B); @@ -626,11 +554,6 @@ static u8 phy_PathA_RxIQK8723B( regEAC = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord); regE94 = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord); regE9C = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xeac = 0x%x\n", regEAC)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe94 = 0x%x, 0xe9c = 0x%x\n", regE94, regE9C)); - /* monitor image power before & after IQK */ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe90(before IQK) = 0x%x, 0xe98(afer IQK) = 0x%x\n", - PHY_QueryBBReg(pDM_Odm->Adapter, 0xe90, bMaskDWord), PHY_QueryBBReg(pDM_Odm->Adapter, 0xe98, bMaskDWord))); /* Allen 20131125 */ tmp = (regE9C & 0x03FF0000)>>16; @@ -651,14 +574,8 @@ static u8 phy_PathA_RxIQK8723B( u4tmp = 0x80007C00 | (regE94&0x3FF0000) | ((regE9C&0x3FF0000) >> 16); PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord, u4tmp); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe40 = 0x%x u4tmp = 0x%x\n", PHY_QueryBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord), u4tmp)); - - - /* 1 RX IQK */ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path A RX IQK\n")); /* modify RXIQK mode table */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path-A Rx IQK modify RXIQK mode table 2!\n")); */ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000); PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1); PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000); @@ -688,7 +605,6 @@ static u8 phy_PathA_RxIQK8723B( PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_B, bMaskDWord, 0x28110000); /* LO calibration setting */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LO calibration setting!\n")); */ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Rsp, bMaskDWord, 0x0046a8d1); /* enter IQK mode */ @@ -706,12 +622,10 @@ static u8 phy_PathA_RxIQK8723B( PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800); /* One shot, path A LOK & IQK */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("One shot, path A LOK & IQK!\n")); */ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000); PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000); /* delay x ms */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Delay %d ms for One shot, path A LOK & IQK.\n", IQK_DELAY_TIME_88E)); */ /* PlatformStallExecution(IQK_DELAY_TIME_8723B*1000); */ mdelay(IQK_DELAY_TIME_8723B); @@ -726,11 +640,6 @@ static u8 phy_PathA_RxIQK8723B( /* Check failed */ regEAC = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord); regEA4 = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_Before_IQK_A_2, bMaskDWord); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xeac = 0x%x\n", regEAC)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xea4 = 0x%x, 0xeac = 0x%x\n", regEA4, regEAC)); - /* monitor image power before & after IQK */ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xea0(before IQK) = 0x%x, 0xea8(afer IQK) = 0x%x\n", - PHY_QueryBBReg(pDM_Odm->Adapter, 0xea0, bMaskDWord), PHY_QueryBBReg(pDM_Odm->Adapter, 0xea8, bMaskDWord))); /* PA/PAD controlled by 0x0 */ /* leave IQK mode */ @@ -751,8 +660,7 @@ static u8 phy_PathA_RxIQK8723B( (tmp < 0xf) ) result |= 0x02; - else /* if Tx not OK, ignore Rx */ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path A Rx IQK fail!!\n")); + return result; } @@ -764,8 +672,6 @@ static u8 phy_PathB_IQK_8723B(struct adapter *padapter) struct hal_com_data *pHalData = GET_HAL_DATA(padapter); struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path B IQK!\n")); - /* Save RF Path */ Path_SEL_BB = PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord); @@ -788,7 +694,6 @@ static u8 phy_PathB_IQK_8723B(struct adapter *padapter) PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord, 0x01007c00); PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK, bMaskDWord, 0x01004800); /* path-A IQK setting */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path-B IQK setting!\n")); */ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_A, bMaskDWord, 0x18008c1c); PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_A, bMaskDWord, 0x38008c1c); PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c); @@ -801,7 +706,6 @@ static u8 phy_PathB_IQK_8723B(struct adapter *padapter) PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_B, bMaskDWord, 0x28110000); /* LO calibration setting */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LO calibration setting!\n")); */ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Rsp, bMaskDWord, 0x00462911); /* enter IQK mode */ @@ -815,12 +719,10 @@ static u8 phy_PathB_IQK_8723B(struct adapter *padapter) PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800); /* One shot, path B LOK & IQK */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("One shot, path B LOK & IQK!\n")); */ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000); PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000); /* delay x ms */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Delay %d ms for One shot, path B LOK & IQK.\n", IQK_DELAY_TIME_88E)); */ /* PlatformStallExecution(IQK_DELAY_TIME_88E*1000); */ mdelay(IQK_DELAY_TIME_8723B); @@ -832,18 +734,10 @@ static u8 phy_PathB_IQK_8723B(struct adapter *padapter) /* leave IQK mode */ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000); -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0x948 = 0x%x\n", PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord))); */ - - /* Check failed */ regEAC = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord); regE94 = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord); regE9C = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xeac = 0x%x\n", regEAC)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe94 = 0x%x, 0xe9c = 0x%x\n", regE94, regE9C)); - /* monitor image power before & after IQK */ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe90(before IQK) = 0x%x, 0xe98(afer IQK) = 0x%x\n", - PHY_QueryBBReg(pDM_Odm->Adapter, 0xe90, bMaskDWord), PHY_QueryBBReg(pDM_Odm->Adapter, 0xe98, bMaskDWord))); /* Allen 20131125 */ tmp = (regE9C & 0x03FF0000)>>16; @@ -871,8 +765,6 @@ static u8 phy_PathB_RxIQK8723B(struct adapter *padapter, bool configPathB) struct hal_com_data *pHalData = GET_HAL_DATA(padapter); struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path B Rx IQK!\n")); */ - /* Save RF Path */ Path_SEL_BB = PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord); /* leave IQK mode */ @@ -880,11 +772,7 @@ static u8 phy_PathB_RxIQK8723B(struct adapter *padapter, bool configPathB) /* switch to path B */ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000280); - - /* 1 Get TXIMR setting */ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path B RX IQK:Get TXIMR setting!\n")); /* modify RXIQK mode table */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path-A Rx IQK modify RXIQK mode table!\n")); */ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1); PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000); PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f); @@ -912,7 +800,6 @@ static u8 phy_PathB_RxIQK8723B(struct adapter *padapter, bool configPathB) PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_B, bMaskDWord, 0x28110000); /* LO calibration setting */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LO calibration setting!\n")); */ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911); /* enter IQK mode */ @@ -926,13 +813,11 @@ static u8 phy_PathB_RxIQK8723B(struct adapter *padapter, bool configPathB) PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800); /* One shot, path B TXIQK @ RXIQK */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("One shot, path B LOK & IQK!\n")); */ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000); PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000); /* delay x ms */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Delay %d ms for One shot, path A LOK & IQK.\n", IQK_DELAY_TIME_88E)); */ /* PlatformStallExecution(IQK_DELAY_TIME_88E*1000); */ mdelay(IQK_DELAY_TIME_8723B); @@ -948,18 +833,11 @@ static u8 phy_PathB_RxIQK8723B(struct adapter *padapter, bool configPathB) regEAC = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord); regE94 = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord); regE9C = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xeac = 0x%x\n", regEAC)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe94 = 0x%x, 0xe9c = 0x%x\n", regE94, regE9C)); - /* monitor image power before & after IQK */ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe90(before IQK) = 0x%x, 0xe98(afer IQK) = 0x%x\n", - PHY_QueryBBReg(pDM_Odm->Adapter, 0xe90, bMaskDWord), PHY_QueryBBReg(pDM_Odm->Adapter, 0xe98, bMaskDWord))); /* Allen 20131125 */ tmp = (regE9C & 0x03FF0000)>>16; -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("tmp1 = 0x%x\n", tmp)); */ if ((tmp & 0x200) > 0) tmp = 0x400 - tmp; -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("tmp2 = 0x%x\n", tmp)); */ if ( !(regEAC & BIT28) && @@ -975,10 +853,6 @@ static u8 phy_PathB_RxIQK8723B(struct adapter *padapter, bool configPathB) u4tmp = 0x80007C00 | (regE94&0x3FF0000) | ((regE9C&0x3FF0000) >> 16); PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord, u4tmp); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe40 = 0x%x u4tmp = 0x%x\n", PHY_QueryBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord), u4tmp)); - - /* 1 RX IQK */ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path B RX IQK\n")); /* modify RXIQK mode table */ /* 20121009, Kordan> RF Mode = 3 */ @@ -1013,7 +887,6 @@ static u8 phy_PathB_RxIQK8723B(struct adapter *padapter, bool configPathB) PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_B, bMaskDWord, 0x28110000); /* LO calibration setting */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LO calibration setting!\n")); */ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Rsp, bMaskDWord, 0x0046a8d1); /* enter IQK mode */ @@ -1027,12 +900,10 @@ static u8 phy_PathB_RxIQK8723B(struct adapter *padapter, bool configPathB) PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800); /* One shot, path B LOK & IQK */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("One shot, path B LOK & IQK!\n")); */ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000); PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000); /* delay x ms */ -/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Delay %d ms for One shot, path A LOK & IQK.\n", IQK_DELAY_TIME_88E)); */ /* PlatformStallExecution(IQK_DELAY_TIME_88E*1000); */ mdelay(IQK_DELAY_TIME_8723B); @@ -1048,12 +919,6 @@ static u8 phy_PathB_RxIQK8723B(struct adapter *padapter, bool configPathB) regEAC = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord); regEA4 = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_Before_IQK_A_2, bMaskDWord); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xeac = 0x%x\n", regEAC)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xea4 = 0x%x, 0xeac = 0x%x\n", regEA4, regEAC)); - /* monitor image power before & after IQK */ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xea0(before IQK) = 0x%x, 0xea8(afer IQK) = 0x%x\n", - PHY_QueryBBReg(pDM_Odm->Adapter, 0xea0, bMaskDWord), PHY_QueryBBReg(pDM_Odm->Adapter, 0xea8, bMaskDWord))); - /* PA/PAD controlled by 0x0 */ /* leave IQK mode */ /* PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, 0xffffff00, 0x00000000); */ @@ -1075,8 +940,6 @@ static u8 phy_PathB_RxIQK8723B(struct adapter *padapter, bool configPathB) (tmp < 0xf) ) result |= 0x02; - else - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path B Rx IQK fail!!\n")); return result; } @@ -1096,8 +959,6 @@ static void _PHY_PathAFillIQKMatrix8723B( struct odm_rf_cal_t *pRFCalibrateInfo = &pDM_Odm->RFCalibrateInfo; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path A IQ Calibration %s !\n", (bIQKOK)?"Success":"Failed")); - if (final_candidate == 0xFF) return; @@ -1108,7 +969,6 @@ static void _PHY_PathAFillIQKMatrix8723B( if ((X & 0x00000200) != 0) X = X | 0xFFFFFC00; TX0_A = (X * Oldval_0) >> 8; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("X = 0x%x, TX0_A = 0x%x, Oldval_0 0x%x\n", X, TX0_A, Oldval_0)); PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XATxIQImbalance, 0x3FF, TX0_A); PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT(31), ((X*Oldval_0>>7) & 0x1)); @@ -1119,7 +979,6 @@ static void _PHY_PathAFillIQKMatrix8723B( /* 2 Tx IQC */ TX0_C = (Y * Oldval_0) >> 8; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Y = 0x%x, TX = 0x%x\n", Y, TX0_C)); PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XCTxAFE, 0xF0000000, ((TX0_C&0x3C0)>>6)); pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC94][KEY] = rOFDM0_XCTxAFE; pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC94][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XCTxAFE, bMaskDWord); @@ -1133,8 +992,6 @@ static void _PHY_PathAFillIQKMatrix8723B( pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC4C][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskDWord); if (bTxOnly) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_PHY_PathAFillIQKMatrix8723B only Tx OK\n")); - /* <20130226, Kordan> Saving RxIQC, otherwise not initialized. */ pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xCA0][KEY] = rOFDM0_RxIQExtAnta; pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xCA0][VAL] = 0xfffffff & PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_RxIQExtAnta, bMaskDWord); @@ -1176,8 +1033,6 @@ static void _PHY_PathBFillIQKMatrix8723B( struct odm_rf_cal_t *pRFCalibrateInfo = &pDM_Odm->RFCalibrateInfo; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path B IQ Calibration %s !\n", (bIQKOK)?"Success":"Failed")); - if (final_candidate == 0xFF) return; @@ -1188,7 +1043,6 @@ static void _PHY_PathBFillIQKMatrix8723B( if ((X & 0x00000200) != 0) X = X | 0xFFFFFC00; TX1_A = (X * Oldval_1) >> 8; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("X = 0x%x, TX1_A = 0x%x\n", X, TX1_A)); PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XBTxIQImbalance, 0x3FF, TX1_A); @@ -1199,7 +1053,6 @@ static void _PHY_PathBFillIQKMatrix8723B( Y = Y | 0xFFFFFC00; TX1_C = (Y * Oldval_1) >> 8; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Y = 0x%x, TX1_C = 0x%x\n", Y, TX1_C)); /* 2 Tx IQC */ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XDTxAFE, 0xF0000000, ((TX1_C&0x3C0)>>6)); @@ -1217,8 +1070,6 @@ static void _PHY_PathBFillIQKMatrix8723B( pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC4C][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskDWord); if (bTxOnly) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_PHY_PathBFillIQKMatrix8723B only Tx OK\n")); - pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][KEY] = rOFDM0_XARxIQImbalance; /* pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XARxIQImbalance, bMaskDWord); */ pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][VAL] = 0x40000100; @@ -1297,7 +1148,6 @@ static void _PHY_SaveADDARegisters8723B( if (!ODM_CheckPowerStatus(padapter)) return; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Save ADDA parameters.\n")); for (i = 0 ; i < RegisterNum ; i++) { ADDABackup[i] = PHY_QueryBBReg(pDM_Odm->Adapter, ADDAReg[i], bMaskDWord); } @@ -1312,7 +1162,6 @@ static void _PHY_SaveMACRegisters8723B( struct hal_com_data *pHalData = GET_HAL_DATA(padapter); struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Save MAC parameters.\n")); for (i = 0 ; i < (IQK_MAC_REG_NUM - 1); i++) { MACBackup[i] = rtw_read8(pDM_Odm->Adapter, MACReg[i]); } @@ -1332,7 +1181,6 @@ static void _PHY_ReloadADDARegisters8723B( struct hal_com_data *pHalData = GET_HAL_DATA(padapter); struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Reload ADDA power saving parameters !\n")); for (i = 0 ; i < RegiesterNum; i++) { PHY_SetBBReg(pDM_Odm->Adapter, ADDAReg[i], bMaskDWord, ADDABackup[i]); } @@ -1362,8 +1210,6 @@ static void _PHY_PathADDAOn8723B( struct hal_com_data *pHalData = GET_HAL_DATA(padapter); struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("ADDA ON.\n")); - pathOn = 0x01c00014; if (!is2T) { pathOn = 0x01c00014; @@ -1386,8 +1232,6 @@ static void _PHY_MACSettingCalibration8723B( struct hal_com_data *pHalData = GET_HAL_DATA(padapter); struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("MAC settings for Calibration.\n")); - rtw_write8(pDM_Odm->Adapter, MACReg[i], 0x3F); for (i = 1 ; i < (IQK_MAC_REG_NUM - 1); i++) { @@ -1540,17 +1384,12 @@ static void phy_IQCalibrate_8723B( /* u32 bbvalue; */ if (t == 0) { -/* bbvalue = PHY_QueryBBReg(pDM_Odm->Adapter, rFPGA0_RFMOD, bMaskDWord); */ -/* RT_DISP(FINIT, INIT_IQK, ("phy_IQCalibrate_8188E() ==>0x%08x\n", bbvalue)); */ - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQ Calibration for %s for %d times\n", (is2T ? "2T2R" : "1T1R"), t)); /* Save ADDA parameters, turn Path A ADDA on */ _PHY_SaveADDARegisters8723B(padapter, ADDA_REG, pDM_Odm->RFCalibrateInfo.ADDA_backup, IQK_ADDA_REG_NUM); _PHY_SaveMACRegisters8723B(padapter, IQK_MAC_REG, pDM_Odm->RFCalibrateInfo.IQK_MAC_backup); _PHY_SaveADDARegisters8723B(padapter, IQK_BB_REG_92C, pDM_Odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM); } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQ Calibration for %s for %d times\n", (is2T ? "2T2R" : "1T1R"), t)); _PHY_PathADDAOn8723B(padapter, ADDA_REG, is2T); @@ -1596,7 +1435,6 @@ static void phy_IQCalibrate_8723B( PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000); pDM_Odm->RFCalibrateInfo.TxLOK[ODM_RF_PATH_A] = PHY_QueryRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x8, bRFRegOffsetMask); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path A Tx IQK Success!!\n")); result[t][0] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16; result[t][1] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16; break; @@ -1607,19 +1445,15 @@ static void phy_IQCalibrate_8723B( for (i = 0 ; i < retryCount ; i++) { PathAOK = phy_PathA_RxIQK8723B(padapter, is2T, RF_Path); if (PathAOK == 0x03) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path A Rx IQK Success!!\n")); /* result[t][0] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16; */ /* result[t][1] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16; */ result[t][2] = (PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_Before_IQK_A_2, bMaskDWord)&0x3FF0000)>>16; result[t][3] = (PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord)&0x3FF0000)>>16; break; - } else { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path A Rx IQK Fail!!\n")); } } if (0x00 == PathAOK) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path A IQK failed!!\n")); } /* path B IQK */ @@ -1633,7 +1467,6 @@ static void phy_IQCalibrate_8723B( PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000); pDM_Odm->RFCalibrateInfo.TxLOK[ODM_RF_PATH_B] = PHY_QueryRFReg(pDM_Odm->Adapter, ODM_RF_PATH_B, 0x8, bRFRegOffsetMask); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path B Tx IQK Success!!\n")); result[t][4] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16; result[t][5] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16; break; @@ -1644,25 +1477,18 @@ static void phy_IQCalibrate_8723B( for (i = 0 ; i < retryCount ; i++) { PathBOK = phy_PathB_RxIQK8723B(padapter, is2T); if (PathBOK == 0x03) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path B Rx IQK Success!!\n")); /* result[t][0] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16; */ /* result[t][1] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16; */ result[t][6] = (PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_Before_IQK_A_2, bMaskDWord)&0x3FF0000)>>16; result[t][7] = (PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord)&0x3FF0000)>>16; break; - } else { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path B Rx IQK Fail!!\n")); } } /* Allen end */ - if (0x00 == PathBOK) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path B IQK failed!!\n")); - } } /* Back to BB mode, load original value */ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK:Back to BB mode, load original value!\n")); PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0); if (t != 0) { @@ -1692,7 +1518,6 @@ static void phy_IQCalibrate_8723B( PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00); } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("phy_IQCalibrate_8723B() <==\n")); } @@ -1789,7 +1614,7 @@ void PHY_IQCalibrate_8723B( s32 result[4][8]; /* last is final result */ u8 i, final_candidate; bool bPathAOK, bPathBOK; - s32 RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4, RegECC, RegTmp = 0; + s32 RegE94, RegE9C, RegEA4, RegEB4, RegEBC, RegEC4, RegTmp = 0; bool is12simular, is13simular, is23simular; bool bSingleTone = false, bCarrierSuppression = false; u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = { @@ -1805,8 +1630,6 @@ void PHY_IQCalibrate_8723B( }; /* u32 Path_SEL_BB = 0; */ u32 GNT_BT_default; - u32 StartTime; - s32 ProgressingTime; if (!ODM_CheckPowerStatus(padapter)) return; @@ -1818,9 +1641,6 @@ void PHY_IQCalibrate_8723B( if (bSingleTone || bCarrierSuppression) return; -#if DISABLE_BB_RF - return; -#endif if (pDM_Odm->RFCalibrateInfo.bIQKInProgress) return; @@ -1868,12 +1688,9 @@ void PHY_IQCalibrate_8723B( } if (bReCovery) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("PHY_IQCalibrate_8723B: Return due to bReCovery!\n")); _PHY_ReloadADDARegisters8723B(padapter, IQK_BB_REG_92C, pDM_Odm->RFCalibrateInfo.IQK_BB_backup_recover, 9); return; } - StartTime = jiffies; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK:Start!!!\n")); /* save default GNT_BT */ GNT_BT_default = PHY_QueryBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord); @@ -1908,7 +1725,6 @@ void PHY_IQCalibrate_8723B( is12simular = phy_SimularityCompare_8723B(padapter, result, 0, 1); if (is12simular) { final_candidate = 0; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK: is12simular final_candidate is %x\n", final_candidate)); break; } } @@ -1917,7 +1733,6 @@ void PHY_IQCalibrate_8723B( is13simular = phy_SimularityCompare_8723B(padapter, result, 0, 2); if (is13simular) { final_candidate = 0; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK: is13simular final_candidate is %x\n", final_candidate)); break; } @@ -1925,7 +1740,6 @@ void PHY_IQCalibrate_8723B( is23simular = phy_SimularityCompare_8723B(padapter, result, 1, 2); if (is23simular) { final_candidate = 1; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK: is23simular final_candidate is %x\n", final_candidate)); } else { for (i = 0; i < 8; i++) RegTmp += result[3][i]; @@ -1942,29 +1756,20 @@ void PHY_IQCalibrate_8723B( RegE94 = result[i][0]; RegE9C = result[i][1]; RegEA4 = result[i][2]; - RegEAC = result[i][3]; RegEB4 = result[i][4]; RegEBC = result[i][5]; RegEC4 = result[i][6]; - RegECC = result[i][7]; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK: RegE94 =%x RegE9C =%x RegEA4 =%x RegEAC =%x RegEB4 =%x RegEBC =%x RegEC4 =%x RegECC =%x\n ", RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4, RegECC)); } if (final_candidate != 0xff) { pDM_Odm->RFCalibrateInfo.RegE94 = RegE94 = result[final_candidate][0]; pDM_Odm->RFCalibrateInfo.RegE9C = RegE9C = result[final_candidate][1]; RegEA4 = result[final_candidate][2]; - RegEAC = result[final_candidate][3]; pDM_Odm->RFCalibrateInfo.RegEB4 = RegEB4 = result[final_candidate][4]; pDM_Odm->RFCalibrateInfo.RegEBC = RegEBC = result[final_candidate][5]; RegEC4 = result[final_candidate][6]; - RegECC = result[final_candidate][7]; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK: final_candidate is %x\n", final_candidate)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK: RegE94 =%x RegE9C =%x RegEA4 =%x RegEAC =%x RegEB4 =%x RegEBC =%x RegEC4 =%x RegECC =%x\n ", RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4, RegECC)); bPathAOK = bPathBOK = true; } else { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK: FAIL use default value\n")); - pDM_Odm->RFCalibrateInfo.RegE94 = pDM_Odm->RFCalibrateInfo.RegEB4 = 0x100; /* X default value */ pDM_Odm->RFCalibrateInfo.RegE9C = pDM_Odm->RFCalibrateInfo.RegEBC = 0x0; /* Y default value */ } @@ -1985,7 +1790,6 @@ void PHY_IQCalibrate_8723B( pDM_Odm->RFCalibrateInfo.IQKMatrixRegSetting[0].Value[0][i] = result[final_candidate][i]; pDM_Odm->RFCalibrateInfo.IQKMatrixRegSetting[0].bIQKDone = true; } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("\nIQK OK Indexforchannel %d.\n", 0)); _PHY_SaveADDARegisters8723B(padapter, IQK_BB_REG_92C, pDM_Odm->RFCalibrateInfo.IQK_BB_backup_recover, 9); @@ -2015,12 +1819,6 @@ void PHY_IQCalibrate_8723B( } pDM_Odm->RFCalibrateInfo.bIQKInProgress = false; - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK finished\n")); - ProgressingTime = jiffies_to_msecs(jiffies - StartTime); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK ProgressingTime = %d\n", ProgressingTime)); - - } @@ -2028,12 +1826,6 @@ void PHY_LCCalibrate_8723B(struct dm_odm_t *pDM_Odm) { bool bSingleTone = false, bCarrierSuppression = false; u32 timeout = 2000, timecount = 0; - u32 StartTime; - s32 ProgressingTime; - -#if DISABLE_BB_RF - return; -#endif if (!(pDM_Odm->SupportAbility & ODM_RF_CALIBRATION)) return; @@ -2042,7 +1834,6 @@ void PHY_LCCalibrate_8723B(struct dm_odm_t *pDM_Odm) if (bSingleTone || bCarrierSuppression) return; - StartTime = jiffies; while (*(pDM_Odm->pbScanInProcess) && timecount < timeout) { mdelay(50); timecount += 50; @@ -2055,8 +1846,4 @@ void PHY_LCCalibrate_8723B(struct dm_odm_t *pDM_Odm) pDM_Odm->RFCalibrateInfo.bLCKInProgress = false; - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LCK:Finish!!!interface %d\n", pDM_Odm->InterfaceIndex)); - ProgressingTime = jiffies_to_msecs(jiffies - StartTime); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LCK ProgressingTime = %d\n", ProgressingTime)); } diff --git a/drivers/staging/rtl8723bs/hal/hal_btcoex.c b/drivers/staging/rtl8723bs/hal/hal_btcoex.c index 5802ed4c6f82..3b0573885dce 100644 --- a/drivers/staging/rtl8723bs/hal/hal_btcoex.c +++ b/drivers/staging/rtl8723bs/hal/hal_btcoex.c @@ -17,7 +17,6 @@ struct btc_coexist GLBtCoexist; static u8 GLBtcWiFiInScanState; static u8 GLBtcWiFiInIQKState; -u32 GLBtcDbgType[BTC_MSG_MAX]; static u8 GLBtcDbgBuf[BT_TMP_BUF_SIZE]; struct btcdbginfo { /* _btcoexdbginfo */ @@ -75,32 +74,6 @@ static u8 halbtcoutsrc_IsBtCoexistAvailable(struct btc_coexist *pBtCoexist) return true; } -static void halbtcoutsrc_DbgInit(void) -{ - u8 i; - - for (i = 0; i < BTC_MSG_MAX; i++) - GLBtcDbgType[i] = 0; - - GLBtcDbgType[BTC_MSG_INTERFACE] = \ -/* INTF_INIT | */ -/* INTF_NOTIFY | */ - 0; - - GLBtcDbgType[BTC_MSG_ALGORITHM] = \ -/* ALGO_BT_RSSI_STATE | */ -/* ALGO_WIFI_RSSI_STATE | */ -/* ALGO_BT_MONITOR | */ -/* ALGO_TRACE | */ -/* ALGO_TRACE_FW | */ -/* ALGO_TRACE_FW_DETAIL | */ -/* ALGO_TRACE_FW_EXEC | */ -/* ALGO_TRACE_SW | */ -/* ALGO_TRACE_SW_DETAIL | */ -/* ALGO_TRACE_SW_EXEC | */ - 0; -} - static void halbtcoutsrc_LeaveLps(struct btc_coexist *pBtCoexist) { struct adapter *padapter; @@ -131,9 +104,6 @@ static void halbtcoutsrc_NormalLps(struct btc_coexist *pBtCoexist) { struct adapter *padapter; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Normal LPS behavior!!!\n")); - padapter = pBtCoexist->Adapter; if (pBtCoexist->btInfo.bBtCtrlLps) { @@ -398,10 +368,6 @@ static u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf) *pu8 = false; break; - case BTC_GET_BL_WIFI_UNDER_5G: - *pu8 = pHalData->CurrentBandType == 1; - break; - case BTC_GET_BL_WIFI_AP_MODE_ENABLE: *pu8 = check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE); break; @@ -922,8 +888,6 @@ void hal_btcoex_Initialize(void *padapter) /* pBtCoexist->statistics.cntBind++; */ - halbtcoutsrc_DbgInit(); - pBtCoexist->chipInterface = BTC_INTF_SDIO; EXhalbtcoutsrc_BindBtCoexWithAdapter(padapter); @@ -1481,10 +1445,6 @@ u32 hal_btcoex_GetRaMask(struct adapter *padapter) void hal_btcoex_RecordPwrMode(struct adapter *padapter, u8 *pCmdBuf, u8 cmdLen) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, ("[BTCoex], FW write pwrModeCmd = 0x%04x%08x\n", - pCmdBuf[0] << 8 | pCmdBuf[1], - pCmdBuf[2] << 24 | pCmdBuf[3] << 16 | pCmdBuf[4] << 8 | pCmdBuf[5])); - memcpy(GLBtCoexist.pwrModeVal, pCmdBuf, cmdLen); } @@ -1499,138 +1459,3 @@ void hal_btcoex_DisplayBtCoexInfo(struct adapter *padapter, u8 *pbuf, u32 bufsiz DBG_BT_INFO_INIT(pinfo, NULL, 0); } -void hal_btcoex_SetDBG(struct adapter *padapter, u32 *pDbgModule) -{ - u32 i; - - - if (!pDbgModule) - return; - - for (i = 0; i < BTC_MSG_MAX; i++) - GLBtcDbgType[i] = pDbgModule[i]; -} - -u32 hal_btcoex_GetDBG(struct adapter *padapter, u8 *pStrBuf, u32 bufSize) -{ - s32 count; - u8 *pstr; - u32 leftSize; - - - if (!pStrBuf || bufSize == 0) - return 0; - - pstr = pStrBuf; - leftSize = bufSize; - - count = rtw_sprintf(pstr, leftSize, "#define DBG\t%d\n", DBG); - if ((count < 0) || (count >= leftSize)) - goto exit; - pstr += count; - leftSize -= count; - - count = rtw_sprintf(pstr, leftSize, "BTCOEX Debug Setting:\n"); - if ((count < 0) || (count >= leftSize)) - goto exit; - pstr += count; - leftSize -= count; - - count = rtw_sprintf(pstr, leftSize, - "INTERFACE / ALGORITHM: 0x%08X / 0x%08X\n\n", - GLBtcDbgType[BTC_MSG_INTERFACE], - GLBtcDbgType[BTC_MSG_ALGORITHM]); - if ((count < 0) || (count >= leftSize)) - goto exit; - pstr += count; - leftSize -= count; - - count = rtw_sprintf(pstr, leftSize, "INTERFACE Debug Setting Definition:\n"); - if ((count < 0) || (count >= leftSize)) - goto exit; - pstr += count; - leftSize -= count; - count = rtw_sprintf(pstr, leftSize, "\tbit[0]=%d for INTF_INIT\n", - (GLBtcDbgType[BTC_MSG_INTERFACE] & INTF_INIT) ? 1 : 0); - if ((count < 0) || (count >= leftSize)) - goto exit; - pstr += count; - leftSize -= count; - count = rtw_sprintf(pstr, leftSize, "\tbit[2]=%d for INTF_NOTIFY\n\n", - (GLBtcDbgType[BTC_MSG_INTERFACE] & INTF_NOTIFY) ? 1 : 0); - if ((count < 0) || (count >= leftSize)) - goto exit; - pstr += count; - leftSize -= count; - - count = rtw_sprintf(pstr, leftSize, "ALGORITHM Debug Setting Definition:\n"); - if ((count < 0) || (count >= leftSize)) - goto exit; - pstr += count; - leftSize -= count; - count = rtw_sprintf(pstr, leftSize, "\tbit[0]=%d for BT_RSSI_STATE\n", - (GLBtcDbgType[BTC_MSG_ALGORITHM] & ALGO_BT_RSSI_STATE) ? 1 : 0); - if ((count < 0) || (count >= leftSize)) - goto exit; - pstr += count; - leftSize -= count; - count = rtw_sprintf(pstr, leftSize, "\tbit[1]=%d for WIFI_RSSI_STATE\n", - (GLBtcDbgType[BTC_MSG_ALGORITHM] & ALGO_WIFI_RSSI_STATE) ? 1 : 0); - if ((count < 0) || (count >= leftSize)) - goto exit; - pstr += count; - leftSize -= count; - count = rtw_sprintf(pstr, leftSize, "\tbit[2]=%d for BT_MONITOR\n", - (GLBtcDbgType[BTC_MSG_ALGORITHM] & ALGO_BT_MONITOR) ? 1 : 0); - if ((count < 0) || (count >= leftSize)) - goto exit; - pstr += count; - leftSize -= count; - count = rtw_sprintf(pstr, leftSize, "\tbit[3]=%d for TRACE\n", - (GLBtcDbgType[BTC_MSG_ALGORITHM] & ALGO_TRACE) ? 1 : 0); - if ((count < 0) || (count >= leftSize)) - goto exit; - pstr += count; - leftSize -= count; - count = rtw_sprintf(pstr, leftSize, "\tbit[4]=%d for TRACE_FW\n", - (GLBtcDbgType[BTC_MSG_ALGORITHM] & ALGO_TRACE_FW) ? 1 : 0); - if ((count < 0) || (count >= leftSize)) - goto exit; - pstr += count; - leftSize -= count; - count = rtw_sprintf(pstr, leftSize, "\tbit[5]=%d for TRACE_FW_DETAIL\n", - (GLBtcDbgType[BTC_MSG_ALGORITHM] & ALGO_TRACE_FW_DETAIL) ? 1 : 0); - if ((count < 0) || (count >= leftSize)) - goto exit; - pstr += count; - leftSize -= count; - count = rtw_sprintf(pstr, leftSize, "\tbit[6]=%d for TRACE_FW_EXEC\n", - (GLBtcDbgType[BTC_MSG_ALGORITHM] & ALGO_TRACE_FW_EXEC) ? 1 : 0); - if ((count < 0) || (count >= leftSize)) - goto exit; - pstr += count; - leftSize -= count; - count = rtw_sprintf(pstr, leftSize, "\tbit[7]=%d for TRACE_SW\n", - (GLBtcDbgType[BTC_MSG_ALGORITHM] & ALGO_TRACE_SW) ? 1 : 0); - if ((count < 0) || (count >= leftSize)) - goto exit; - pstr += count; - leftSize -= count; - count = rtw_sprintf(pstr, leftSize, "\tbit[8]=%d for TRACE_SW_DETAIL\n", - (GLBtcDbgType[BTC_MSG_ALGORITHM] & ALGO_TRACE_SW_DETAIL) ? 1 : 0); - if ((count < 0) || (count >= leftSize)) - goto exit; - pstr += count; - leftSize -= count; - count = rtw_sprintf(pstr, leftSize, "\tbit[9]=%d for TRACE_SW_EXEC\n", - (GLBtcDbgType[BTC_MSG_ALGORITHM] & ALGO_TRACE_SW_EXEC) ? 1 : 0); - if ((count < 0) || (count >= leftSize)) - goto exit; - pstr += count; - leftSize -= count; - -exit: - count = pstr - pStrBuf; - - return count; -} diff --git a/drivers/staging/rtl8723bs/hal/hal_com.c b/drivers/staging/rtl8723bs/hal/hal_com.c index e82f59fc5e9b..eebd48438733 100644 --- a/drivers/staging/rtl8723bs/hal/hal_com.c +++ b/drivers/staging/rtl8723bs/hal/hal_com.c @@ -295,126 +295,6 @@ u8 MRateToHwRate(u8 rate) case MGN_MCS31: ret = DESC_RATEMCS31; break; - case MGN_VHT1SS_MCS0: - ret = DESC_RATEVHTSS1MCS0; - break; - case MGN_VHT1SS_MCS1: - ret = DESC_RATEVHTSS1MCS1; - break; - case MGN_VHT1SS_MCS2: - ret = DESC_RATEVHTSS1MCS2; - break; - case MGN_VHT1SS_MCS3: - ret = DESC_RATEVHTSS1MCS3; - break; - case MGN_VHT1SS_MCS4: - ret = DESC_RATEVHTSS1MCS4; - break; - case MGN_VHT1SS_MCS5: - ret = DESC_RATEVHTSS1MCS5; - break; - case MGN_VHT1SS_MCS6: - ret = DESC_RATEVHTSS1MCS6; - break; - case MGN_VHT1SS_MCS7: - ret = DESC_RATEVHTSS1MCS7; - break; - case MGN_VHT1SS_MCS8: - ret = DESC_RATEVHTSS1MCS8; - break; - case MGN_VHT1SS_MCS9: - ret = DESC_RATEVHTSS1MCS9; - break; - case MGN_VHT2SS_MCS0: - ret = DESC_RATEVHTSS2MCS0; - break; - case MGN_VHT2SS_MCS1: - ret = DESC_RATEVHTSS2MCS1; - break; - case MGN_VHT2SS_MCS2: - ret = DESC_RATEVHTSS2MCS2; - break; - case MGN_VHT2SS_MCS3: - ret = DESC_RATEVHTSS2MCS3; - break; - case MGN_VHT2SS_MCS4: - ret = DESC_RATEVHTSS2MCS4; - break; - case MGN_VHT2SS_MCS5: - ret = DESC_RATEVHTSS2MCS5; - break; - case MGN_VHT2SS_MCS6: - ret = DESC_RATEVHTSS2MCS6; - break; - case MGN_VHT2SS_MCS7: - ret = DESC_RATEVHTSS2MCS7; - break; - case MGN_VHT2SS_MCS8: - ret = DESC_RATEVHTSS2MCS8; - break; - case MGN_VHT2SS_MCS9: - ret = DESC_RATEVHTSS2MCS9; - break; - case MGN_VHT3SS_MCS0: - ret = DESC_RATEVHTSS3MCS0; - break; - case MGN_VHT3SS_MCS1: - ret = DESC_RATEVHTSS3MCS1; - break; - case MGN_VHT3SS_MCS2: - ret = DESC_RATEVHTSS3MCS2; - break; - case MGN_VHT3SS_MCS3: - ret = DESC_RATEVHTSS3MCS3; - break; - case MGN_VHT3SS_MCS4: - ret = DESC_RATEVHTSS3MCS4; - break; - case MGN_VHT3SS_MCS5: - ret = DESC_RATEVHTSS3MCS5; - break; - case MGN_VHT3SS_MCS6: - ret = DESC_RATEVHTSS3MCS6; - break; - case MGN_VHT3SS_MCS7: - ret = DESC_RATEVHTSS3MCS7; - break; - case MGN_VHT3SS_MCS8: - ret = DESC_RATEVHTSS3MCS8; - break; - case MGN_VHT3SS_MCS9: - ret = DESC_RATEVHTSS3MCS9; - break; - case MGN_VHT4SS_MCS0: - ret = DESC_RATEVHTSS4MCS0; - break; - case MGN_VHT4SS_MCS1: - ret = DESC_RATEVHTSS4MCS1; - break; - case MGN_VHT4SS_MCS2: - ret = DESC_RATEVHTSS4MCS2; - break; - case MGN_VHT4SS_MCS3: - ret = DESC_RATEVHTSS4MCS3; - break; - case MGN_VHT4SS_MCS4: - ret = DESC_RATEVHTSS4MCS4; - break; - case MGN_VHT4SS_MCS5: - ret = DESC_RATEVHTSS4MCS5; - break; - case MGN_VHT4SS_MCS6: - ret = DESC_RATEVHTSS4MCS6; - break; - case MGN_VHT4SS_MCS7: - ret = DESC_RATEVHTSS4MCS7; - break; - case MGN_VHT4SS_MCS8: - ret = DESC_RATEVHTSS4MCS8; - break; - case MGN_VHT4SS_MCS9: - ret = DESC_RATEVHTSS4MCS9; - break; default: break; } @@ -559,127 +439,6 @@ u8 HwRateToMRate(u8 rate) case DESC_RATEMCS31: ret_rate = MGN_MCS31; break; - case DESC_RATEVHTSS1MCS0: - ret_rate = MGN_VHT1SS_MCS0; - break; - case DESC_RATEVHTSS1MCS1: - ret_rate = MGN_VHT1SS_MCS1; - break; - case DESC_RATEVHTSS1MCS2: - ret_rate = MGN_VHT1SS_MCS2; - break; - case DESC_RATEVHTSS1MCS3: - ret_rate = MGN_VHT1SS_MCS3; - break; - case DESC_RATEVHTSS1MCS4: - ret_rate = MGN_VHT1SS_MCS4; - break; - case DESC_RATEVHTSS1MCS5: - ret_rate = MGN_VHT1SS_MCS5; - break; - case DESC_RATEVHTSS1MCS6: - ret_rate = MGN_VHT1SS_MCS6; - break; - case DESC_RATEVHTSS1MCS7: - ret_rate = MGN_VHT1SS_MCS7; - break; - case DESC_RATEVHTSS1MCS8: - ret_rate = MGN_VHT1SS_MCS8; - break; - case DESC_RATEVHTSS1MCS9: - ret_rate = MGN_VHT1SS_MCS9; - break; - case DESC_RATEVHTSS2MCS0: - ret_rate = MGN_VHT2SS_MCS0; - break; - case DESC_RATEVHTSS2MCS1: - ret_rate = MGN_VHT2SS_MCS1; - break; - case DESC_RATEVHTSS2MCS2: - ret_rate = MGN_VHT2SS_MCS2; - break; - case DESC_RATEVHTSS2MCS3: - ret_rate = MGN_VHT2SS_MCS3; - break; - case DESC_RATEVHTSS2MCS4: - ret_rate = MGN_VHT2SS_MCS4; - break; - case DESC_RATEVHTSS2MCS5: - ret_rate = MGN_VHT2SS_MCS5; - break; - case DESC_RATEVHTSS2MCS6: - ret_rate = MGN_VHT2SS_MCS6; - break; - case DESC_RATEVHTSS2MCS7: - ret_rate = MGN_VHT2SS_MCS7; - break; - case DESC_RATEVHTSS2MCS8: - ret_rate = MGN_VHT2SS_MCS8; - break; - case DESC_RATEVHTSS2MCS9: - ret_rate = MGN_VHT2SS_MCS9; - break; - case DESC_RATEVHTSS3MCS0: - ret_rate = MGN_VHT3SS_MCS0; - break; - case DESC_RATEVHTSS3MCS1: - ret_rate = MGN_VHT3SS_MCS1; - break; - case DESC_RATEVHTSS3MCS2: - ret_rate = MGN_VHT3SS_MCS2; - break; - case DESC_RATEVHTSS3MCS3: - ret_rate = MGN_VHT3SS_MCS3; - break; - case DESC_RATEVHTSS3MCS4: - ret_rate = MGN_VHT3SS_MCS4; - break; - case DESC_RATEVHTSS3MCS5: - ret_rate = MGN_VHT3SS_MCS5; - break; - case DESC_RATEVHTSS3MCS6: - ret_rate = MGN_VHT3SS_MCS6; - break; - case DESC_RATEVHTSS3MCS7: - ret_rate = MGN_VHT3SS_MCS7; - break; - case DESC_RATEVHTSS3MCS8: - ret_rate = MGN_VHT3SS_MCS8; - break; - case DESC_RATEVHTSS3MCS9: - ret_rate = MGN_VHT3SS_MCS9; - break; - case DESC_RATEVHTSS4MCS0: - ret_rate = MGN_VHT4SS_MCS0; - break; - case DESC_RATEVHTSS4MCS1: - ret_rate = MGN_VHT4SS_MCS1; - break; - case DESC_RATEVHTSS4MCS2: - ret_rate = MGN_VHT4SS_MCS2; - break; - case DESC_RATEVHTSS4MCS3: - ret_rate = MGN_VHT4SS_MCS3; - break; - case DESC_RATEVHTSS4MCS4: - ret_rate = MGN_VHT4SS_MCS4; - break; - case DESC_RATEVHTSS4MCS5: - ret_rate = MGN_VHT4SS_MCS5; - break; - case DESC_RATEVHTSS4MCS6: - ret_rate = MGN_VHT4SS_MCS6; - break; - case DESC_RATEVHTSS4MCS7: - ret_rate = MGN_VHT4SS_MCS7; - break; - case DESC_RATEVHTSS4MCS8: - ret_rate = MGN_VHT4SS_MCS8; - break; - case DESC_RATEVHTSS4MCS9: - ret_rate = MGN_VHT4SS_MCS9; - break; - default: break; } @@ -916,16 +675,10 @@ s32 c2h_evt_read_88xx(struct adapter *adapter, u8 *buf) c2h_evt->seq = rtw_read8(adapter, REG_C2HEVT_CMD_SEQ_88XX); c2h_evt->plen = rtw_read8(adapter, REG_C2HEVT_CMD_LEN_88XX); - print_hex_dump_debug(DRIVER_PREFIX ": c2h_evt_read(): ", DUMP_PREFIX_NONE, - 16, 1, &c2h_evt, sizeof(c2h_evt), false); - /* Read the content */ for (i = 0; i < c2h_evt->plen; i++) c2h_evt->payload[i] = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 2 + i); - print_hex_dump_debug(DRIVER_PREFIX ": c2h_evt_read(): Command Content:\n", - DUMP_PREFIX_NONE, 16, 1, c2h_evt->payload, c2h_evt->plen, false); - ret = _SUCCESS; clear_evt: @@ -1093,13 +846,6 @@ u8 SetHalDefVar( u8 bResult = _SUCCESS; switch (variable) { - case HW_DEF_FA_CNT_DUMP: - /* ODM_COMP_COMMON */ - if (*((u8 *)value)) - odm->DebugComponents |= (ODM_COMP_DIG | ODM_COMP_FA_CNT); - else - odm->DebugComponents &= ~(ODM_COMP_DIG | ODM_COMP_FA_CNT); - break; case HAL_DEF_DBG_RX_INFO_DUMP: if (odm->bLinked) { @@ -1166,7 +912,6 @@ u8 GetHalDefVar( ) { struct hal_com_data *hal_data = GET_HAL_DATA(adapter); - struct dm_odm_t *odm = &(hal_data->odmpriv); u8 bResult = _SUCCESS; switch (variable) { @@ -1183,12 +928,6 @@ u8 GetHalDefVar( *((int *)value) = psta->rssi_stat.UndecoratedSmoothedPWDB; } break; - case HW_DEF_ODM_DBG_FLAG: - *((u64 *)value) = odm->DebugComponents; - break; - case HW_DEF_ODM_DBG_LEVEL: - *((u32 *)value) = odm->DebugLevel; - break; case HAL_DEF_DBG_DM_FUNC: *((u32 *)value) = hal_data->odmpriv.SupportAbility; break; diff --git a/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c b/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c index 94d11689b4ac..bb7941aee0c4 100644 --- a/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c +++ b/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c @@ -11,7 +11,7 @@ #include <hal_data.h> #include <linux/kernel.h> -u8 PHY_GetTxPowerByRateBase(struct adapter *Adapter, u8 Band, u8 RfPath, +u8 PHY_GetTxPowerByRateBase(struct adapter *Adapter, u8 RfPath, u8 TxNum, enum rate_section RateSection) { struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); @@ -20,73 +20,27 @@ u8 PHY_GetTxPowerByRateBase(struct adapter *Adapter, u8 Band, u8 RfPath, if (RfPath > ODM_RF_PATH_D) return 0; - if (Band == BAND_ON_2_4G) { - switch (RateSection) { - case CCK: - value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][0]; - break; - case OFDM: - value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][1]; - break; - case HT_MCS0_MCS7: - value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][2]; - break; - case HT_MCS8_MCS15: - value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][3]; - break; - case HT_MCS16_MCS23: - value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][4]; - break; - case HT_MCS24_MCS31: - value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][5]; - break; - case VHT_1SSMCS0_1SSMCS9: - value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][6]; - break; - case VHT_2SSMCS0_2SSMCS9: - value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][7]; - break; - case VHT_3SSMCS0_3SSMCS9: - value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][8]; - break; - case VHT_4SSMCS0_4SSMCS9: - value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][9]; - break; - default: - break; - } - } else if (Band == BAND_ON_5G) { - switch (RateSection) { - case OFDM: - value = pHalData->TxPwrByRateBase5G[RfPath][TxNum][0]; - break; - case HT_MCS0_MCS7: - value = pHalData->TxPwrByRateBase5G[RfPath][TxNum][1]; - break; - case HT_MCS8_MCS15: - value = pHalData->TxPwrByRateBase5G[RfPath][TxNum][2]; - break; - case HT_MCS16_MCS23: - value = pHalData->TxPwrByRateBase5G[RfPath][TxNum][3]; - break; - case HT_MCS24_MCS31: - value = pHalData->TxPwrByRateBase5G[RfPath][TxNum][4]; - break; - case VHT_1SSMCS0_1SSMCS9: - value = pHalData->TxPwrByRateBase5G[RfPath][TxNum][5]; - break; - case VHT_2SSMCS0_2SSMCS9: - value = pHalData->TxPwrByRateBase5G[RfPath][TxNum][6]; - break; - case VHT_3SSMCS0_3SSMCS9: - value = pHalData->TxPwrByRateBase5G[RfPath][TxNum][7]; - break; - case VHT_4SSMCS0_4SSMCS9: - value = pHalData->TxPwrByRateBase5G[RfPath][TxNum][8]; - break; - default: - break; - } + switch (RateSection) { + case CCK: + value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][0]; + break; + case OFDM: + value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][1]; + break; + case HT_MCS0_MCS7: + value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][2]; + break; + case HT_MCS8_MCS15: + value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][3]; + break; + case HT_MCS16_MCS23: + value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][4]; + break; + case HT_MCS24_MCS31: + value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][5]; + break; + default: + break; } return value; @@ -95,7 +49,6 @@ u8 PHY_GetTxPowerByRateBase(struct adapter *Adapter, u8 Band, u8 RfPath, static void phy_SetTxPowerByRateBase( struct adapter *Adapter, - u8 Band, u8 RfPath, enum rate_section RateSection, u8 TxNum, @@ -107,73 +60,27 @@ phy_SetTxPowerByRateBase( if (RfPath > ODM_RF_PATH_D) return; - if (Band == BAND_ON_2_4G) { - switch (RateSection) { - case CCK: - pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][0] = Value; - break; - case OFDM: - pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][1] = Value; - break; - case HT_MCS0_MCS7: - pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][2] = Value; - break; - case HT_MCS8_MCS15: - pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][3] = Value; - break; - case HT_MCS16_MCS23: - pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][4] = Value; - break; - case HT_MCS24_MCS31: - pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][5] = Value; - break; - case VHT_1SSMCS0_1SSMCS9: - pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][6] = Value; - break; - case VHT_2SSMCS0_2SSMCS9: - pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][7] = Value; - break; - case VHT_3SSMCS0_3SSMCS9: - pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][8] = Value; - break; - case VHT_4SSMCS0_4SSMCS9: - pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][9] = Value; - break; - default: - break; - } - } else if (Band == BAND_ON_5G) { - switch (RateSection) { - case OFDM: - pHalData->TxPwrByRateBase5G[RfPath][TxNum][0] = Value; - break; - case HT_MCS0_MCS7: - pHalData->TxPwrByRateBase5G[RfPath][TxNum][1] = Value; - break; - case HT_MCS8_MCS15: - pHalData->TxPwrByRateBase5G[RfPath][TxNum][2] = Value; - break; - case HT_MCS16_MCS23: - pHalData->TxPwrByRateBase5G[RfPath][TxNum][3] = Value; - break; - case HT_MCS24_MCS31: - pHalData->TxPwrByRateBase5G[RfPath][TxNum][4] = Value; - break; - case VHT_1SSMCS0_1SSMCS9: - pHalData->TxPwrByRateBase5G[RfPath][TxNum][5] = Value; - break; - case VHT_2SSMCS0_2SSMCS9: - pHalData->TxPwrByRateBase5G[RfPath][TxNum][6] = Value; - break; - case VHT_3SSMCS0_3SSMCS9: - pHalData->TxPwrByRateBase5G[RfPath][TxNum][7] = Value; - break; - case VHT_4SSMCS0_4SSMCS9: - pHalData->TxPwrByRateBase5G[RfPath][TxNum][8] = Value; - break; - default: - break; - } + switch (RateSection) { + case CCK: + pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][0] = Value; + break; + case OFDM: + pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][1] = Value; + break; + case HT_MCS0_MCS7: + pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][2] = Value; + break; + case HT_MCS8_MCS15: + pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][3] = Value; + break; + case HT_MCS16_MCS23: + pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][4] = Value; + break; + case HT_MCS24_MCS31: + pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][5] = Value; + break; + default: + break; } } @@ -185,50 +92,21 @@ struct adapter *padapter u8 path, base; for (path = ODM_RF_PATH_A; path <= ODM_RF_PATH_B; ++path) { - base = PHY_GetTxPowerByRate(padapter, BAND_ON_2_4G, path, RF_1TX, MGN_11M); - phy_SetTxPowerByRateBase(padapter, BAND_ON_2_4G, path, CCK, RF_1TX, base); - - base = PHY_GetTxPowerByRate(padapter, BAND_ON_2_4G, path, RF_1TX, MGN_54M); - phy_SetTxPowerByRateBase(padapter, BAND_ON_2_4G, path, OFDM, RF_1TX, base); - - base = PHY_GetTxPowerByRate(padapter, BAND_ON_2_4G, path, RF_1TX, MGN_MCS7); - phy_SetTxPowerByRateBase(padapter, BAND_ON_2_4G, path, HT_MCS0_MCS7, RF_1TX, base); - - base = PHY_GetTxPowerByRate(padapter, BAND_ON_2_4G, path, RF_2TX, MGN_MCS15); - phy_SetTxPowerByRateBase(padapter, BAND_ON_2_4G, path, HT_MCS8_MCS15, RF_2TX, base); - - base = PHY_GetTxPowerByRate(padapter, BAND_ON_2_4G, path, RF_3TX, MGN_MCS23); - phy_SetTxPowerByRateBase(padapter, BAND_ON_2_4G, path, HT_MCS16_MCS23, RF_3TX, base); - - base = PHY_GetTxPowerByRate(padapter, BAND_ON_2_4G, path, RF_1TX, MGN_VHT1SS_MCS7); - phy_SetTxPowerByRateBase(padapter, BAND_ON_2_4G, path, VHT_1SSMCS0_1SSMCS9, RF_1TX, base); - - base = PHY_GetTxPowerByRate(padapter, BAND_ON_2_4G, path, RF_2TX, MGN_VHT2SS_MCS7); - phy_SetTxPowerByRateBase(padapter, BAND_ON_2_4G, path, VHT_2SSMCS0_2SSMCS9, RF_2TX, base); - - base = PHY_GetTxPowerByRate(padapter, BAND_ON_2_4G, path, RF_3TX, MGN_VHT3SS_MCS7); - phy_SetTxPowerByRateBase(padapter, BAND_ON_2_4G, path, VHT_3SSMCS0_3SSMCS9, RF_3TX, base); + base = PHY_GetTxPowerByRate(padapter, path, RF_1TX, MGN_11M); + phy_SetTxPowerByRateBase(padapter, path, CCK, RF_1TX, base); - base = PHY_GetTxPowerByRate(padapter, BAND_ON_5G, path, RF_1TX, MGN_54M); - phy_SetTxPowerByRateBase(padapter, BAND_ON_5G, path, OFDM, RF_1TX, base); + base = PHY_GetTxPowerByRate(padapter, path, RF_1TX, MGN_54M); + phy_SetTxPowerByRateBase(padapter, path, OFDM, RF_1TX, base); - base = PHY_GetTxPowerByRate(padapter, BAND_ON_5G, path, RF_1TX, MGN_MCS7); - phy_SetTxPowerByRateBase(padapter, BAND_ON_5G, path, HT_MCS0_MCS7, RF_1TX, base); + base = PHY_GetTxPowerByRate(padapter, path, RF_1TX, MGN_MCS7); + phy_SetTxPowerByRateBase(padapter, path, HT_MCS0_MCS7, RF_1TX, base); - base = PHY_GetTxPowerByRate(padapter, BAND_ON_5G, path, RF_2TX, MGN_MCS15); - phy_SetTxPowerByRateBase(padapter, BAND_ON_5G, path, HT_MCS8_MCS15, RF_2TX, base); + base = PHY_GetTxPowerByRate(padapter, path, RF_2TX, MGN_MCS15); + phy_SetTxPowerByRateBase(padapter, path, HT_MCS8_MCS15, RF_2TX, base); - base = PHY_GetTxPowerByRate(padapter, BAND_ON_5G, path, RF_3TX, MGN_MCS23); - phy_SetTxPowerByRateBase(padapter, BAND_ON_5G, path, HT_MCS16_MCS23, RF_3TX, base); + base = PHY_GetTxPowerByRate(padapter, path, RF_3TX, MGN_MCS23); + phy_SetTxPowerByRateBase(padapter, path, HT_MCS16_MCS23, RF_3TX, base); - base = PHY_GetTxPowerByRate(padapter, BAND_ON_5G, path, RF_1TX, MGN_VHT1SS_MCS7); - phy_SetTxPowerByRateBase(padapter, BAND_ON_5G, path, VHT_1SSMCS0_1SSMCS9, RF_1TX, base); - - base = PHY_GetTxPowerByRate(padapter, BAND_ON_5G, path, RF_2TX, MGN_VHT2SS_MCS7); - phy_SetTxPowerByRateBase(padapter, BAND_ON_5G, path, VHT_2SSMCS0_2SSMCS9, RF_2TX, base); - - base = PHY_GetTxPowerByRate(padapter, BAND_ON_5G, path, RF_3TX, MGN_VHT2SS_MCS7); - phy_SetTxPowerByRateBase(padapter, BAND_ON_5G, path, VHT_3SSMCS0_3SSMCS9, RF_3TX, base); } } @@ -532,81 +410,6 @@ PHY_GetRateValuesOfTxPowerByRate( *RateNum = 4; break; - case 0xC3C: - case 0xE3C: - case 0x183C: - case 0x1a3C: - RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT1SS_MCS0); - RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT1SS_MCS1); - RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT1SS_MCS2); - RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT1SS_MCS3); - for (i = 0; i < 4; ++i) { - PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 + - ((Value >> (i * 8)) & 0xF)); - } - *RateNum = 4; - break; - - case 0xC40: - case 0xE40: - case 0x1840: - case 0x1a40: - RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT1SS_MCS4); - RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT1SS_MCS5); - RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT1SS_MCS6); - RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT1SS_MCS7); - for (i = 0; i < 4; ++i) { - PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 + - ((Value >> (i * 8)) & 0xF)); - } - *RateNum = 4; - break; - - case 0xC44: - case 0xE44: - case 0x1844: - case 0x1a44: - RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT1SS_MCS8); - RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT1SS_MCS9); - RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT2SS_MCS0); - RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT2SS_MCS1); - for (i = 0; i < 4; ++i) { - PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 + - ((Value >> (i * 8)) & 0xF)); - } - *RateNum = 4; - break; - - case 0xC48: - case 0xE48: - case 0x1848: - case 0x1a48: - RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT2SS_MCS2); - RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT2SS_MCS3); - RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT2SS_MCS4); - RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT2SS_MCS5); - for (i = 0; i < 4; ++i) { - PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 + - ((Value >> (i * 8)) & 0xF)); - } - *RateNum = 4; - break; - - case 0xC4C: - case 0xE4C: - case 0x184C: - case 0x1a4C: - RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT2SS_MCS6); - RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT2SS_MCS7); - RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT2SS_MCS8); - RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT2SS_MCS9); - for (i = 0; i < 4; ++i) { - PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 + - ((Value >> (i * 8)) & 0xF)); - } - *RateNum = 4; - break; - case 0xCD8: case 0xED8: case 0x18D8: @@ -637,49 +440,6 @@ PHY_GetRateValuesOfTxPowerByRate( *RateNum = 4; break; - case 0xCE0: - case 0xEE0: - case 0x18E0: - case 0x1aE0: - RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT3SS_MCS0); - RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT3SS_MCS1); - RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT3SS_MCS2); - RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT3SS_MCS3); - for (i = 0; i < 4; ++i) { - PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 + - ((Value >> (i * 8)) & 0xF)); - } - *RateNum = 4; - break; - - case 0xCE4: - case 0xEE4: - case 0x18E4: - case 0x1aE4: - RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT3SS_MCS4); - RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT3SS_MCS5); - RateIndex[2] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT3SS_MCS6); - RateIndex[3] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT3SS_MCS7); - for (i = 0; i < 4; ++i) { - PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 + - ((Value >> (i * 8)) & 0xF)); - } - *RateNum = 4; - break; - - case 0xCE8: - case 0xEE8: - case 0x18E8: - case 0x1aE8: - RateIndex[0] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT3SS_MCS8); - RateIndex[1] = PHY_GetRateIndexOfTxPowerByRate(MGN_VHT3SS_MCS9); - for (i = 0; i < 2; ++i) { - PwrByRateVal[i] = (s8) ((((Value >> (i * 8 + 4)) & 0xF)) * 10 + - ((Value >> (i * 8)) & 0xF)); - } - *RateNum = 4; - break; - default: break; } @@ -687,7 +447,6 @@ PHY_GetRateValuesOfTxPowerByRate( static void PHY_StoreTxPowerByRateNew( struct adapter *padapter, - u32 Band, u32 RfPath, u32 TxNum, u32 RegAddr, @@ -701,9 +460,6 @@ static void PHY_StoreTxPowerByRateNew( PHY_GetRateValuesOfTxPowerByRate(padapter, RegAddr, BitMask, Data, rateIndex, PwrByRateVal, &rateNum); - if (Band != BAND_ON_2_4G && Band != BAND_ON_5G) - return; - if (RfPath > ODM_RF_PATH_D) return; @@ -711,11 +467,7 @@ static void PHY_StoreTxPowerByRateNew( return; for (i = 0; i < rateNum; ++i) { - if (rateIndex[i] == PHY_GetRateIndexOfTxPowerByRate(MGN_VHT2SS_MCS0) || - rateIndex[i] == PHY_GetRateIndexOfTxPowerByRate(MGN_VHT2SS_MCS1)) - TxNum = RF_2TX; - - pHalData->TxPwrByRateOffset[Band][RfPath][TxNum][rateIndex[i]] = PwrByRateVal[i]; + pHalData->TxPwrByRateOffset[RfPath][TxNum][rateIndex[i]] = PwrByRateVal[i]; } } @@ -732,18 +484,16 @@ static void PHY_StoreTxPowerByRateOld( void PHY_InitTxPowerByRate(struct adapter *padapter) { struct hal_com_data *pHalData = GET_HAL_DATA(padapter); - u8 band, rfPath, TxNum, rate; + u8 rfPath, TxNum, rate; - for (band = BAND_ON_2_4G; band <= BAND_ON_5G; ++band) - for (rfPath = 0; rfPath < TX_PWR_BY_RATE_NUM_RF; ++rfPath) - for (TxNum = 0; TxNum < TX_PWR_BY_RATE_NUM_RF; ++TxNum) - for (rate = 0; rate < TX_PWR_BY_RATE_NUM_RATE; ++rate) - pHalData->TxPwrByRateOffset[band][rfPath][TxNum][rate] = 0; + for (rfPath = 0; rfPath < TX_PWR_BY_RATE_NUM_RF; ++rfPath) + for (TxNum = 0; TxNum < TX_PWR_BY_RATE_NUM_RF; ++TxNum) + for (rate = 0; rate < TX_PWR_BY_RATE_NUM_RATE; ++rate) + pHalData->TxPwrByRateOffset[rfPath][TxNum][rate] = 0; } void PHY_StoreTxPowerByRate( struct adapter *padapter, - u32 Band, u32 RfPath, u32 TxNum, u32 RegAddr, @@ -755,7 +505,7 @@ void PHY_StoreTxPowerByRate( struct dm_odm_t *pDM_Odm = &pHalData->odmpriv; if (pDM_Odm->PhyRegPgVersion > 0) - PHY_StoreTxPowerByRateNew(padapter, Band, RfPath, TxNum, RegAddr, BitMask, Data); + PHY_StoreTxPowerByRateNew(padapter, RfPath, TxNum, RegAddr, BitMask, Data); else if (pDM_Odm->PhyRegPgVersion == 0) { PHY_StoreTxPowerByRateOld(padapter, RegAddr, BitMask, Data); @@ -771,7 +521,7 @@ phy_ConvertTxPowerByRateInDbmToRelativeValues( struct adapter *padapter ) { - u8 base = 0, i = 0, value = 0, band = 0, path = 0, txNum = 0; + u8 base = 0, i = 0, value = 0, path = 0, txNum = 0; u8 cckRates[4] = { MGN_1M, MGN_2M, MGN_5_5M, MGN_11M }; @@ -787,77 +537,42 @@ struct adapter *padapter u8 mcs16_23Rates[8] = { MGN_MCS16, MGN_MCS17, MGN_MCS18, MGN_MCS19, MGN_MCS20, MGN_MCS21, MGN_MCS22, MGN_MCS23 }; - u8 vht1ssRates[10] = { - MGN_VHT1SS_MCS0, MGN_VHT1SS_MCS1, MGN_VHT1SS_MCS2, MGN_VHT1SS_MCS3, MGN_VHT1SS_MCS4, - MGN_VHT1SS_MCS5, MGN_VHT1SS_MCS6, MGN_VHT1SS_MCS7, MGN_VHT1SS_MCS8, MGN_VHT1SS_MCS9 - }; - u8 vht2ssRates[10] = { - MGN_VHT2SS_MCS0, MGN_VHT2SS_MCS1, MGN_VHT2SS_MCS2, MGN_VHT2SS_MCS3, MGN_VHT2SS_MCS4, - MGN_VHT2SS_MCS5, MGN_VHT2SS_MCS6, MGN_VHT2SS_MCS7, MGN_VHT2SS_MCS8, MGN_VHT2SS_MCS9 - }; - u8 vht3ssRates[10] = { - MGN_VHT3SS_MCS0, MGN_VHT3SS_MCS1, MGN_VHT3SS_MCS2, MGN_VHT3SS_MCS3, MGN_VHT3SS_MCS4, - MGN_VHT3SS_MCS5, MGN_VHT3SS_MCS6, MGN_VHT3SS_MCS7, MGN_VHT3SS_MCS8, MGN_VHT3SS_MCS9 - }; - - for (band = BAND_ON_2_4G; band <= BAND_ON_5G; ++band) { - for (path = ODM_RF_PATH_A; path <= ODM_RF_PATH_D; ++path) { - for (txNum = RF_1TX; txNum < RF_MAX_TX_NUM; ++txNum) { - /* CCK */ - base = PHY_GetTxPowerByRate(padapter, band, path, txNum, MGN_11M); - for (i = 0; i < ARRAY_SIZE(cckRates); ++i) { - value = PHY_GetTxPowerByRate(padapter, band, path, txNum, cckRates[i]); - PHY_SetTxPowerByRate(padapter, band, path, txNum, cckRates[i], value - base); - } - /* OFDM */ - base = PHY_GetTxPowerByRate(padapter, band, path, txNum, MGN_54M); - for (i = 0; i < sizeof(ofdmRates); ++i) { - value = PHY_GetTxPowerByRate(padapter, band, path, txNum, ofdmRates[i]); - PHY_SetTxPowerByRate(padapter, band, path, txNum, ofdmRates[i], value - base); - } - - /* HT MCS0~7 */ - base = PHY_GetTxPowerByRate(padapter, band, path, txNum, MGN_MCS7); - for (i = 0; i < sizeof(mcs0_7Rates); ++i) { - value = PHY_GetTxPowerByRate(padapter, band, path, txNum, mcs0_7Rates[i]); - PHY_SetTxPowerByRate(padapter, band, path, txNum, mcs0_7Rates[i], value - base); - } - - /* HT MCS8~15 */ - base = PHY_GetTxPowerByRate(padapter, band, path, txNum, MGN_MCS15); - for (i = 0; i < sizeof(mcs8_15Rates); ++i) { - value = PHY_GetTxPowerByRate(padapter, band, path, txNum, mcs8_15Rates[i]); - PHY_SetTxPowerByRate(padapter, band, path, txNum, mcs8_15Rates[i], value - base); - } + for (path = ODM_RF_PATH_A; path <= ODM_RF_PATH_D; ++path) { + for (txNum = RF_1TX; txNum < RF_MAX_TX_NUM; ++txNum) { + /* CCK */ + base = PHY_GetTxPowerByRate(padapter, path, txNum, MGN_11M); + for (i = 0; i < ARRAY_SIZE(cckRates); ++i) { + value = PHY_GetTxPowerByRate(padapter, path, txNum, cckRates[i]); + PHY_SetTxPowerByRate(padapter, path, txNum, cckRates[i], value - base); + } - /* HT MCS16~23 */ - base = PHY_GetTxPowerByRate(padapter, band, path, txNum, MGN_MCS23); - for (i = 0; i < sizeof(mcs16_23Rates); ++i) { - value = PHY_GetTxPowerByRate(padapter, band, path, txNum, mcs16_23Rates[i]); - PHY_SetTxPowerByRate(padapter, band, path, txNum, mcs16_23Rates[i], value - base); - } + /* OFDM */ + base = PHY_GetTxPowerByRate(padapter, path, txNum, MGN_54M); + for (i = 0; i < sizeof(ofdmRates); ++i) { + value = PHY_GetTxPowerByRate(padapter, path, txNum, ofdmRates[i]); + PHY_SetTxPowerByRate(padapter, path, txNum, ofdmRates[i], value - base); + } - /* VHT 1SS */ - base = PHY_GetTxPowerByRate(padapter, band, path, txNum, MGN_VHT1SS_MCS7); - for (i = 0; i < sizeof(vht1ssRates); ++i) { - value = PHY_GetTxPowerByRate(padapter, band, path, txNum, vht1ssRates[i]); - PHY_SetTxPowerByRate(padapter, band, path, txNum, vht1ssRates[i], value - base); - } + /* HT MCS0~7 */ + base = PHY_GetTxPowerByRate(padapter, path, txNum, MGN_MCS7); + for (i = 0; i < sizeof(mcs0_7Rates); ++i) { + value = PHY_GetTxPowerByRate(padapter, path, txNum, mcs0_7Rates[i]); + PHY_SetTxPowerByRate(padapter, path, txNum, mcs0_7Rates[i], value - base); + } - /* VHT 2SS */ - base = PHY_GetTxPowerByRate(padapter, band, path, txNum, MGN_VHT2SS_MCS7); - for (i = 0; i < sizeof(vht2ssRates); ++i) { - value = PHY_GetTxPowerByRate(padapter, band, path, txNum, vht2ssRates[i]); - PHY_SetTxPowerByRate(padapter, band, path, txNum, vht2ssRates[i], value - base); - } + /* HT MCS8~15 */ + base = PHY_GetTxPowerByRate(padapter, path, txNum, MGN_MCS15); + for (i = 0; i < sizeof(mcs8_15Rates); ++i) { + value = PHY_GetTxPowerByRate(padapter, path, txNum, mcs8_15Rates[i]); + PHY_SetTxPowerByRate(padapter, path, txNum, mcs8_15Rates[i], value - base); + } - /* VHT 3SS */ - base = PHY_GetTxPowerByRate(padapter, band, path, txNum, MGN_VHT3SS_MCS7); - for (i = 0; i < sizeof(vht3ssRates); ++i) { - value = PHY_GetTxPowerByRate(padapter, band, path, txNum, vht3ssRates[i]); - PHY_SetTxPowerByRate(padapter, band, path, txNum, vht3ssRates[i], value - base); - } + /* HT MCS16~23 */ + base = PHY_GetTxPowerByRate(padapter, path, txNum, MGN_MCS23); + for (i = 0; i < sizeof(mcs16_23Rates); ++i) { + value = PHY_GetTxPowerByRate(padapter, path, txNum, mcs16_23Rates[i]); + PHY_SetTxPowerByRate(padapter, path, txNum, mcs16_23Rates[i], value - base); } } } @@ -881,11 +596,10 @@ void PHY_SetTxPowerIndexByRateSection( if (RateSection == CCK) { u8 cckRates[] = {MGN_1M, MGN_2M, MGN_5_5M, MGN_11M}; - if (pHalData->CurrentBandType == BAND_ON_2_4G) - PHY_SetTxPowerIndexByRateArray(padapter, RFPath, - pHalData->CurrentChannelBW, - Channel, cckRates, - ARRAY_SIZE(cckRates)); + PHY_SetTxPowerIndexByRateArray(padapter, RFPath, + pHalData->CurrentChannelBW, + Channel, cckRates, + ARRAY_SIZE(cckRates)); } else if (RateSection == OFDM) { u8 ofdmRates[] = {MGN_6M, MGN_9M, MGN_12M, MGN_18M, MGN_24M, MGN_36M, MGN_48M, MGN_54M}; @@ -922,67 +636,7 @@ void PHY_SetTxPowerIndexByRateSection( Channel, htRates4T, ARRAY_SIZE(htRates4T)); - } else if (RateSection == VHT_1SSMCS0_1SSMCS9) { - u8 vhtRates1T[] = {MGN_VHT1SS_MCS0, MGN_VHT1SS_MCS1, MGN_VHT1SS_MCS2, MGN_VHT1SS_MCS3, MGN_VHT1SS_MCS4, - MGN_VHT1SS_MCS5, MGN_VHT1SS_MCS6, MGN_VHT1SS_MCS7, MGN_VHT1SS_MCS8, MGN_VHT1SS_MCS9}; - PHY_SetTxPowerIndexByRateArray(padapter, RFPath, - pHalData->CurrentChannelBW, - Channel, vhtRates1T, - ARRAY_SIZE(vhtRates1T)); - - } else if (RateSection == VHT_2SSMCS0_2SSMCS9) { - u8 vhtRates2T[] = {MGN_VHT2SS_MCS0, MGN_VHT2SS_MCS1, MGN_VHT2SS_MCS2, MGN_VHT2SS_MCS3, MGN_VHT2SS_MCS4, - MGN_VHT2SS_MCS5, MGN_VHT2SS_MCS6, MGN_VHT2SS_MCS7, MGN_VHT2SS_MCS8, MGN_VHT2SS_MCS9}; - - PHY_SetTxPowerIndexByRateArray(padapter, RFPath, - pHalData->CurrentChannelBW, - Channel, vhtRates2T, - ARRAY_SIZE(vhtRates2T)); - } else if (RateSection == VHT_3SSMCS0_3SSMCS9) { - u8 vhtRates3T[] = {MGN_VHT3SS_MCS0, MGN_VHT3SS_MCS1, MGN_VHT3SS_MCS2, MGN_VHT3SS_MCS3, MGN_VHT3SS_MCS4, - MGN_VHT3SS_MCS5, MGN_VHT3SS_MCS6, MGN_VHT3SS_MCS7, MGN_VHT3SS_MCS8, MGN_VHT3SS_MCS9}; - - PHY_SetTxPowerIndexByRateArray(padapter, RFPath, - pHalData->CurrentChannelBW, - Channel, vhtRates3T, - ARRAY_SIZE(vhtRates3T)); - } else if (RateSection == VHT_4SSMCS0_4SSMCS9) { - u8 vhtRates4T[] = {MGN_VHT4SS_MCS0, MGN_VHT4SS_MCS1, MGN_VHT4SS_MCS2, MGN_VHT4SS_MCS3, MGN_VHT4SS_MCS4, - MGN_VHT4SS_MCS5, MGN_VHT4SS_MCS6, MGN_VHT4SS_MCS7, MGN_VHT4SS_MCS8, MGN_VHT4SS_MCS9}; - - PHY_SetTxPowerIndexByRateArray(padapter, RFPath, - pHalData->CurrentChannelBW, - Channel, vhtRates4T, - ARRAY_SIZE(vhtRates4T)); - } -} - -static bool phy_GetChnlIndex(u8 Channel, u8 *ChannelIdx) -{ - u8 channel5G[CHANNEL_MAX_NUMBER_5G] = { - 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 100, 102, - 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, - 132, 134, 136, 138, 140, 142, 144, 149, 151, 153, 155, 157, 159, 161, - 163, 165, 167, 168, 169, 171, 173, 175, 177 - }; - u8 i = 0; - bool bIn24G = true; - - if (Channel <= 14) { - bIn24G = true; - *ChannelIdx = Channel-1; - } else { - bIn24G = false; - - for (i = 0; i < ARRAY_SIZE(channel5G); ++i) { - if (channel5G[i] == Channel) { - *ChannelIdx = i; - return bIn24G; - } - } } - - return bIn24G; } u8 PHY_GetTxPowerIndexBase( @@ -990,110 +644,45 @@ u8 PHY_GetTxPowerIndexBase( u8 RFPath, u8 Rate, enum channel_width BandWidth, - u8 Channel, - bool *bIn24G + u8 Channel ) { struct hal_com_data *pHalData = GET_HAL_DATA(padapter); - u8 i = 0; /* default set to 1S */ u8 txPower = 0; u8 chnlIdx = (Channel-1); if (HAL_IsLegalChannel(padapter, Channel) == false) chnlIdx = 0; - *bIn24G = phy_GetChnlIndex(Channel, &chnlIdx); - - if (*bIn24G) { /* 3 ============================== 2.4 G ============================== */ - if (IS_CCK_RATE(Rate)) - txPower = pHalData->Index24G_CCK_Base[RFPath][chnlIdx]; - else if (MGN_6M <= Rate) - txPower = pHalData->Index24G_BW40_Base[RFPath][chnlIdx]; - - /* OFDM-1T */ - if ((MGN_6M <= Rate && Rate <= MGN_54M) && !IS_CCK_RATE(Rate)) - txPower += pHalData->OFDM_24G_Diff[RFPath][TX_1S]; - - if (BandWidth == CHANNEL_WIDTH_20) { /* BW20-1S, BW20-2S */ - if ((MGN_MCS0 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT1SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW20_24G_Diff[RFPath][TX_1S]; - if ((MGN_MCS8 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT2SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW20_24G_Diff[RFPath][TX_2S]; - if ((MGN_MCS16 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT3SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW20_24G_Diff[RFPath][TX_3S]; - if ((MGN_MCS24 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT4SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW20_24G_Diff[RFPath][TX_4S]; - - } else if (BandWidth == CHANNEL_WIDTH_40) { /* BW40-1S, BW40-2S */ - if ((MGN_MCS0 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT1SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW40_24G_Diff[RFPath][TX_1S]; - if ((MGN_MCS8 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT2SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW40_24G_Diff[RFPath][TX_2S]; - if ((MGN_MCS16 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT3SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW40_24G_Diff[RFPath][TX_3S]; - if ((MGN_MCS24 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT4SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW40_24G_Diff[RFPath][TX_4S]; - - } - /* Willis suggest adopt BW 40M power index while in BW 80 mode */ - else if (BandWidth == CHANNEL_WIDTH_80) { - if ((MGN_MCS0 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT1SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW40_24G_Diff[RFPath][TX_1S]; - if ((MGN_MCS8 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT2SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW40_24G_Diff[RFPath][TX_2S]; - if ((MGN_MCS16 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT3SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW40_24G_Diff[RFPath][TX_3S]; - if ((MGN_MCS24 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT4SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW40_24G_Diff[RFPath][TX_4S]; + if (IS_CCK_RATE(Rate)) + txPower = pHalData->Index24G_CCK_Base[RFPath][chnlIdx]; + else if (MGN_6M <= Rate) + txPower = pHalData->Index24G_BW40_Base[RFPath][chnlIdx]; + + /* OFDM-1T */ + if ((MGN_6M <= Rate && Rate <= MGN_54M) && !IS_CCK_RATE(Rate)) + txPower += pHalData->OFDM_24G_Diff[RFPath][TX_1S]; + + if (BandWidth == CHANNEL_WIDTH_20) { /* BW20-1S, BW20-2S */ + if (MGN_MCS0 <= Rate && Rate <= MGN_MCS31) + txPower += pHalData->BW20_24G_Diff[RFPath][TX_1S]; + if (MGN_MCS8 <= Rate && Rate <= MGN_MCS31) + txPower += pHalData->BW20_24G_Diff[RFPath][TX_2S]; + if (MGN_MCS16 <= Rate && Rate <= MGN_MCS31) + txPower += pHalData->BW20_24G_Diff[RFPath][TX_3S]; + if (MGN_MCS24 <= Rate && Rate <= MGN_MCS31) + txPower += pHalData->BW20_24G_Diff[RFPath][TX_4S]; + + } else if (BandWidth == CHANNEL_WIDTH_40) { /* BW40-1S, BW40-2S */ + if (MGN_MCS0 <= Rate && Rate <= MGN_MCS31) + txPower += pHalData->BW40_24G_Diff[RFPath][TX_1S]; + if (MGN_MCS8 <= Rate && Rate <= MGN_MCS31) + txPower += pHalData->BW40_24G_Diff[RFPath][TX_2S]; + if (MGN_MCS16 <= Rate && Rate <= MGN_MCS31) + txPower += pHalData->BW40_24G_Diff[RFPath][TX_3S]; + if (MGN_MCS24 <= Rate && Rate <= MGN_MCS31) + txPower += pHalData->BW40_24G_Diff[RFPath][TX_4S]; - } - } else {/* 3 ============================== 5 G ============================== */ - if (MGN_6M <= Rate) - txPower = pHalData->Index5G_BW40_Base[RFPath][chnlIdx]; - - /* OFDM-1T */ - if ((MGN_6M <= Rate && Rate <= MGN_54M) && !IS_CCK_RATE(Rate)) - txPower += pHalData->OFDM_5G_Diff[RFPath][TX_1S]; - - /* BW20-1S, BW20-2S */ - if (BandWidth == CHANNEL_WIDTH_20) { - if ((MGN_MCS0 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT1SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW20_5G_Diff[RFPath][TX_1S]; - if ((MGN_MCS8 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT2SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW20_5G_Diff[RFPath][TX_2S]; - if ((MGN_MCS16 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT3SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW20_5G_Diff[RFPath][TX_3S]; - if ((MGN_MCS24 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT4SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW20_5G_Diff[RFPath][TX_4S]; - - } else if (BandWidth == CHANNEL_WIDTH_40) { /* BW40-1S, BW40-2S */ - if ((MGN_MCS0 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT1SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW40_5G_Diff[RFPath][TX_1S]; - if ((MGN_MCS8 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT2SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW40_5G_Diff[RFPath][TX_2S]; - if ((MGN_MCS16 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT3SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW40_5G_Diff[RFPath][TX_3S]; - if ((MGN_MCS24 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT4SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW40_5G_Diff[RFPath][TX_4S]; - - } else if (BandWidth == CHANNEL_WIDTH_80) { /* BW80-1S, BW80-2S */ - /* <20121220, Kordan> Get the index of array "Index5G_BW80_Base". */ - u8 channel5G_80M[CHANNEL_MAX_NUMBER_5G_80M] = {42, 58, 106, 122, 138, 155, 171}; - for (i = 0; i < ARRAY_SIZE(channel5G_80M); ++i) - if (channel5G_80M[i] == Channel) - chnlIdx = i; - - txPower = pHalData->Index5G_BW80_Base[RFPath][chnlIdx]; - - if ((MGN_MCS0 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT1SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += + pHalData->BW80_5G_Diff[RFPath][TX_1S]; - if ((MGN_MCS8 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT2SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW80_5G_Diff[RFPath][TX_2S]; - if ((MGN_MCS16 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT3SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW80_5G_Diff[RFPath][TX_3S]; - if ((MGN_MCS23 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT4SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) - txPower += pHalData->BW80_5G_Diff[RFPath][TX_4S]; - } } return txPower; @@ -1252,126 +841,6 @@ u8 PHY_GetRateIndexOfTxPowerByRate(u8 Rate) case MGN_MCS31: index = 43; break; - case MGN_VHT1SS_MCS0: - index = 44; - break; - case MGN_VHT1SS_MCS1: - index = 45; - break; - case MGN_VHT1SS_MCS2: - index = 46; - break; - case MGN_VHT1SS_MCS3: - index = 47; - break; - case MGN_VHT1SS_MCS4: - index = 48; - break; - case MGN_VHT1SS_MCS5: - index = 49; - break; - case MGN_VHT1SS_MCS6: - index = 50; - break; - case MGN_VHT1SS_MCS7: - index = 51; - break; - case MGN_VHT1SS_MCS8: - index = 52; - break; - case MGN_VHT1SS_MCS9: - index = 53; - break; - case MGN_VHT2SS_MCS0: - index = 54; - break; - case MGN_VHT2SS_MCS1: - index = 55; - break; - case MGN_VHT2SS_MCS2: - index = 56; - break; - case MGN_VHT2SS_MCS3: - index = 57; - break; - case MGN_VHT2SS_MCS4: - index = 58; - break; - case MGN_VHT2SS_MCS5: - index = 59; - break; - case MGN_VHT2SS_MCS6: - index = 60; - break; - case MGN_VHT2SS_MCS7: - index = 61; - break; - case MGN_VHT2SS_MCS8: - index = 62; - break; - case MGN_VHT2SS_MCS9: - index = 63; - break; - case MGN_VHT3SS_MCS0: - index = 64; - break; - case MGN_VHT3SS_MCS1: - index = 65; - break; - case MGN_VHT3SS_MCS2: - index = 66; - break; - case MGN_VHT3SS_MCS3: - index = 67; - break; - case MGN_VHT3SS_MCS4: - index = 68; - break; - case MGN_VHT3SS_MCS5: - index = 69; - break; - case MGN_VHT3SS_MCS6: - index = 70; - break; - case MGN_VHT3SS_MCS7: - index = 71; - break; - case MGN_VHT3SS_MCS8: - index = 72; - break; - case MGN_VHT3SS_MCS9: - index = 73; - break; - case MGN_VHT4SS_MCS0: - index = 74; - break; - case MGN_VHT4SS_MCS1: - index = 75; - break; - case MGN_VHT4SS_MCS2: - index = 76; - break; - case MGN_VHT4SS_MCS3: - index = 77; - break; - case MGN_VHT4SS_MCS4: - index = 78; - break; - case MGN_VHT4SS_MCS5: - index = 79; - break; - case MGN_VHT4SS_MCS6: - index = 80; - break; - case MGN_VHT4SS_MCS7: - index = 81; - break; - case MGN_VHT4SS_MCS8: - index = 82; - break; - case MGN_VHT4SS_MCS9: - index = 83; - break; default: break; } @@ -1379,7 +848,7 @@ u8 PHY_GetRateIndexOfTxPowerByRate(u8 Rate) } s8 PHY_GetTxPowerByRate( - struct adapter *padapter, u8 Band, u8 RFPath, u8 TxNum, u8 Rate + struct adapter *padapter, u8 RFPath, u8 TxNum, u8 Rate ) { struct hal_com_data *pHalData = GET_HAL_DATA(padapter); @@ -1390,9 +859,6 @@ s8 PHY_GetTxPowerByRate( padapter->registrypriv.RegEnableTxPowerByRate == 0) return 0; - if (Band != BAND_ON_2_4G && Band != BAND_ON_5G) - return value; - if (RFPath > ODM_RF_PATH_D) return value; @@ -1402,13 +868,12 @@ s8 PHY_GetTxPowerByRate( if (rateIndex >= TX_PWR_BY_RATE_NUM_RATE) return value; - return pHalData->TxPwrByRateOffset[Band][RFPath][TxNum][rateIndex]; + return pHalData->TxPwrByRateOffset[RFPath][TxNum][rateIndex]; } void PHY_SetTxPowerByRate( struct adapter *padapter, - u8 Band, u8 RFPath, u8 TxNum, u8 Rate, @@ -1418,9 +883,6 @@ void PHY_SetTxPowerByRate( struct hal_com_data *pHalData = GET_HAL_DATA(padapter); u8 rateIndex = PHY_GetRateIndexOfTxPowerByRate(Rate); - if (Band != BAND_ON_2_4G && Band != BAND_ON_5G) - return; - if (RFPath > ODM_RF_PATH_D) return; @@ -1430,18 +892,16 @@ void PHY_SetTxPowerByRate( if (rateIndex >= TX_PWR_BY_RATE_NUM_RATE) return; - pHalData->TxPwrByRateOffset[Band][RFPath][TxNum][rateIndex] = Value; + pHalData->TxPwrByRateOffset[RFPath][TxNum][rateIndex] = Value; } void PHY_SetTxPowerLevelByPath(struct adapter *Adapter, u8 channel, u8 path) { struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); - bool bIsIn24G = (pHalData->CurrentBandType == BAND_ON_2_4G); /* if (pMgntInfo->RegNByteAccess == 0) */ { - if (bIsIn24G) - PHY_SetTxPowerIndexByRateSection(Adapter, path, channel, CCK); + PHY_SetTxPowerIndexByRateSection(Adapter, path, channel, CCK); PHY_SetTxPowerIndexByRateSection(Adapter, path, channel, OFDM); PHY_SetTxPowerIndexByRateSection(Adapter, path, channel, HT_MCS0_MCS7); @@ -1483,26 +943,9 @@ static s8 phy_GetWorldWideLimit(s8 *LimitTable) return min; } -static s8 phy_GetChannelIndexOfTxPowerLimit(u8 Band, u8 Channel) +static s8 phy_GetChannelIndexOfTxPowerLimit(u8 Channel) { - s8 channelIndex = -1; - u8 channel5G[CHANNEL_MAX_NUMBER_5G] = { - 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 100, 102, - 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, - 132, 134, 136, 138, 140, 142, 144, 149, 151, 153, 155, 157, 159, 161, - 163, 165, 167, 168, 169, 171, 173, 175, 177 - }; - u8 i = 0; - if (Band == BAND_ON_2_4G) - channelIndex = Channel - 1; - else if (Band == BAND_ON_5G) { - for (i = 0; i < ARRAY_SIZE(channel5G); ++i) { - if (channel5G[i] == Channel) - channelIndex = i; - } - } - - return channelIndex; + return Channel - 1; } static s16 get_bandwidth_idx(const enum channel_width bandwidth) @@ -1512,10 +955,6 @@ static s16 get_bandwidth_idx(const enum channel_width bandwidth) return 0; case CHANNEL_WIDTH_40: return 1; - case CHANNEL_WIDTH_80: - return 2; - case CHANNEL_WIDTH_160: - return 3; default: return -1; } @@ -1541,42 +980,22 @@ static s16 get_rate_sctn_idx(const u8 rate) case MGN_MCS24: case MGN_MCS25: case MGN_MCS26: case MGN_MCS27: case MGN_MCS28: case MGN_MCS29: case MGN_MCS30: case MGN_MCS31: return 5; - case MGN_VHT1SS_MCS0: case MGN_VHT1SS_MCS1: case MGN_VHT1SS_MCS2: - case MGN_VHT1SS_MCS3: case MGN_VHT1SS_MCS4: case MGN_VHT1SS_MCS5: - case MGN_VHT1SS_MCS6: case MGN_VHT1SS_MCS7: case MGN_VHT1SS_MCS8: - case MGN_VHT1SS_MCS9: - return 6; - case MGN_VHT2SS_MCS0: case MGN_VHT2SS_MCS1: case MGN_VHT2SS_MCS2: - case MGN_VHT2SS_MCS3: case MGN_VHT2SS_MCS4: case MGN_VHT2SS_MCS5: - case MGN_VHT2SS_MCS6: case MGN_VHT2SS_MCS7: case MGN_VHT2SS_MCS8: - case MGN_VHT2SS_MCS9: - return 7; - case MGN_VHT3SS_MCS0: case MGN_VHT3SS_MCS1: case MGN_VHT3SS_MCS2: - case MGN_VHT3SS_MCS3: case MGN_VHT3SS_MCS4: case MGN_VHT3SS_MCS5: - case MGN_VHT3SS_MCS6: case MGN_VHT3SS_MCS7: case MGN_VHT3SS_MCS8: - case MGN_VHT3SS_MCS9: - return 8; - case MGN_VHT4SS_MCS0: case MGN_VHT4SS_MCS1: case MGN_VHT4SS_MCS2: - case MGN_VHT4SS_MCS3: case MGN_VHT4SS_MCS4: case MGN_VHT4SS_MCS5: - case MGN_VHT4SS_MCS6: case MGN_VHT4SS_MCS7: case MGN_VHT4SS_MCS8: - case MGN_VHT4SS_MCS9: - return 9; default: return -1; } } s8 phy_get_tx_pwr_lmt(struct adapter *adapter, u32 reg_pwr_tbl_sel, - enum band_type band_type, enum channel_width bandwidth, + enum channel_width bandwidth, u8 rf_path, u8 data_rate, u8 channel) { - s16 idx_band = -1; s16 idx_regulation = -1; s16 idx_bandwidth = -1; s16 idx_rate_sctn = -1; s16 idx_channel = -1; s8 pwr_lmt = MAX_POWER_INDEX; struct hal_com_data *hal_data = GET_HAL_DATA(adapter); + s8 limits[10] = {0}; u8 i = 0; if (((adapter->registrypriv.RegEnableTxPowerLimit == 2) && (hal_data->EEPROMRegulatory != 1)) || @@ -1597,17 +1016,10 @@ s8 phy_get_tx_pwr_lmt(struct adapter *adapter, u32 reg_pwr_tbl_sel, idx_regulation = TXPWR_LMT_WW; break; default: - idx_regulation = (band_type == BAND_ON_2_4G) ? - hal_data->Regulation2_4G : - hal_data->Regulation5G; + idx_regulation = hal_data->Regulation2_4G; break; } - if (band_type == BAND_ON_2_4G) - idx_band = 0; - else if (band_type == BAND_ON_5G) - idx_band = 1; - idx_bandwidth = get_bandwidth_idx(bandwidth); idx_rate_sctn = get_rate_sctn_idx(data_rate); @@ -1617,107 +1029,30 @@ s8 phy_get_tx_pwr_lmt(struct adapter *adapter, u32 reg_pwr_tbl_sel, /* HT on 80M will reference to HT on 40M */ if (idx_rate_sctn == 0 || idx_rate_sctn == 1) idx_bandwidth = 0; - else if ((idx_rate_sctn == 2 || idx_rate_sctn == 3) && - (band_type == BAND_ON_5G) && (idx_bandwidth == 2)) - idx_bandwidth = 1; - if (band_type == BAND_ON_2_4G || band_type == BAND_ON_5G) - channel = phy_GetChannelIndexOfTxPowerLimit(band_type, channel); + channel = phy_GetChannelIndexOfTxPowerLimit(channel); - if (idx_band == -1 || idx_regulation == -1 || idx_bandwidth == -1 || + if (idx_regulation == -1 || idx_bandwidth == -1 || idx_rate_sctn == -1 || idx_channel == -1) return MAX_POWER_INDEX; - if (band_type == BAND_ON_2_4G) { - s8 limits[10] = {0}; u8 i = 0; - - for (i = 0; i < MAX_REGULATION_NUM; i++) - limits[i] = hal_data->TxPwrLimit_2_4G[i] - [idx_bandwidth] - [idx_rate_sctn] - [idx_channel] - [rf_path]; - - pwr_lmt = (idx_regulation == TXPWR_LMT_WW) ? - phy_GetWorldWideLimit(limits) : - hal_data->TxPwrLimit_2_4G[idx_regulation] - [idx_bandwidth] - [idx_rate_sctn] - [idx_channel] - [rf_path]; - - } else if (band_type == BAND_ON_5G) { - s8 limits[10] = {0}; u8 i = 0; - - for (i = 0; i < MAX_REGULATION_NUM; ++i) - limits[i] = hal_data->TxPwrLimit_5G[i] - [idx_bandwidth] - [idx_rate_sctn] - [idx_channel] - [rf_path]; - - pwr_lmt = (idx_regulation == TXPWR_LMT_WW) ? - phy_GetWorldWideLimit(limits) : - hal_data->TxPwrLimit_5G[idx_regulation] - [idx_bandwidth] - [idx_rate_sctn] - [idx_channel] - [rf_path]; - } - return pwr_lmt; -} + for (i = 0; i < MAX_REGULATION_NUM; i++) + limits[i] = hal_data->TxPwrLimit_2_4G[i] + [idx_bandwidth] + [idx_rate_sctn] + [idx_channel] + [rf_path]; -static void phy_CrossReferenceHTAndVHTTxPowerLimit(struct adapter *padapter) -{ - struct hal_com_data *pHalData = GET_HAL_DATA(padapter); - u8 regulation, bw, channel, rateSection; - s8 tempPwrLmt = 0; + pwr_lmt = (idx_regulation == TXPWR_LMT_WW) ? + phy_GetWorldWideLimit(limits) : + hal_data->TxPwrLimit_2_4G[idx_regulation] + [idx_bandwidth] + [idx_rate_sctn] + [idx_channel] + [rf_path]; - for (regulation = 0; regulation < MAX_REGULATION_NUM; ++regulation) { - for (bw = 0; bw < MAX_5G_BANDWIDTH_NUM; ++bw) { - for (channel = 0; channel < CHANNEL_MAX_NUMBER_5G; ++channel) { - for (rateSection = 0; rateSection < MAX_RATE_SECTION_NUM; ++rateSection) { - tempPwrLmt = pHalData->TxPwrLimit_5G[regulation][bw][rateSection][channel][ODM_RF_PATH_A]; - if (tempPwrLmt == MAX_POWER_INDEX) { - u8 baseSection = 2, refSection = 6; - if (bw == 0 || bw == 1) { /* 5G 20M 40M VHT and HT can cross reference */ - /* 1, bw, rateSection, channel, ODM_RF_PATH_A); */ - if (rateSection >= 2 && rateSection <= 9) { - if (rateSection == 2) { - baseSection = 2; - refSection = 6; - } else if (rateSection == 3) { - baseSection = 3; - refSection = 7; - } else if (rateSection == 4) { - baseSection = 4; - refSection = 8; - } else if (rateSection == 5) { - baseSection = 5; - refSection = 9; - } else if (rateSection == 6) { - baseSection = 6; - refSection = 2; - } else if (rateSection == 7) { - baseSection = 7; - refSection = 3; - } else if (rateSection == 8) { - baseSection = 8; - refSection = 4; - } else if (rateSection == 9) { - baseSection = 9; - refSection = 5; - } - pHalData->TxPwrLimit_5G[regulation][bw][baseSection][channel][ODM_RF_PATH_A] = - pHalData->TxPwrLimit_5G[regulation][bw][refSection][channel][ODM_RF_PATH_A]; - } - } - } - } - } - } - } + return pwr_lmt; } void PHY_ConvertTxPowerLimitToPowerIndex(struct adapter *Adapter) @@ -1728,8 +1063,6 @@ void PHY_ConvertTxPowerLimitToPowerIndex(struct adapter *Adapter) s8 tempValue = 0, tempPwrLmt = 0; u8 rfPath = 0; - phy_CrossReferenceHTAndVHTTxPowerLimit(Adapter); - for (regulation = 0; regulation < MAX_REGULATION_NUM; ++regulation) { for (bw = 0; bw < MAX_2_4G_BANDWIDTH_NUM; ++bw) { for (channel = 0; channel < CHANNEL_MAX_NUMBER_2G; ++channel) { @@ -1739,17 +1072,17 @@ void PHY_ConvertTxPowerLimitToPowerIndex(struct adapter *Adapter) for (rfPath = ODM_RF_PATH_A; rfPath < MAX_RF_PATH_NUM; ++rfPath) { if (pHalData->odmpriv.PhyRegPgValueType == PHY_REG_PG_EXACT_VALUE) { if (rateSection == 5) /* HT 4T */ - BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, BAND_ON_2_4G, rfPath, RF_4TX, HT_MCS24_MCS31); + BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, RF_4TX, HT_MCS24_MCS31); else if (rateSection == 4) /* HT 3T */ - BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, BAND_ON_2_4G, rfPath, RF_3TX, HT_MCS16_MCS23); + BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, RF_3TX, HT_MCS16_MCS23); else if (rateSection == 3) /* HT 2T */ - BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, BAND_ON_2_4G, rfPath, RF_2TX, HT_MCS8_MCS15); + BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, RF_2TX, HT_MCS8_MCS15); else if (rateSection == 2) /* HT 1T */ - BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, BAND_ON_2_4G, rfPath, RF_1TX, HT_MCS0_MCS7); + BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, RF_1TX, HT_MCS0_MCS7); else if (rateSection == 1) /* OFDM */ - BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, BAND_ON_2_4G, rfPath, RF_1TX, OFDM); + BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, RF_1TX, OFDM); else if (rateSection == 0) /* CCK */ - BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, BAND_ON_2_4G, rfPath, RF_1TX, CCK); + BW40PwrBasedBm2_4G = PHY_GetTxPowerByRateBase(Adapter, rfPath, RF_1TX, CCK); } else BW40PwrBasedBm2_4G = Adapter->registrypriv.RegPowerBase * 2; @@ -1776,20 +1109,11 @@ void PHY_InitTxPowerLimit(struct adapter *Adapter) for (l = 0; l < MAX_RF_PATH_NUM; ++l) pHalData->TxPwrLimit_2_4G[i][j][k][m][l] = MAX_POWER_INDEX; } - - for (i = 0; i < MAX_REGULATION_NUM; ++i) { - for (j = 0; j < MAX_5G_BANDWIDTH_NUM; ++j) - for (k = 0; k < MAX_RATE_SECTION_NUM; ++k) - for (m = 0; m < CHANNEL_MAX_NUMBER_5G; ++m) - for (l = 0; l < MAX_RF_PATH_NUM; ++l) - pHalData->TxPwrLimit_5G[i][j][k][m][l] = MAX_POWER_INDEX; - } } void PHY_SetTxPowerLimit( struct adapter *Adapter, u8 *Regulation, - u8 *Band, u8 *Bandwidth, u8 *RateSection, u8 *RfPath, @@ -1827,14 +1151,6 @@ void PHY_SetTxPowerLimit( rateSection = 4; else if (eqNByte(RateSection, (u8 *)("HT"), 2) && eqNByte(RfPath, (u8 *)("4T"), 2)) rateSection = 5; - else if (eqNByte(RateSection, (u8 *)("VHT"), 3) && eqNByte(RfPath, (u8 *)("1T"), 2)) - rateSection = 6; - else if (eqNByte(RateSection, (u8 *)("VHT"), 3) && eqNByte(RfPath, (u8 *)("2T"), 2)) - rateSection = 7; - else if (eqNByte(RateSection, (u8 *)("VHT"), 3) && eqNByte(RfPath, (u8 *)("3T"), 2)) - rateSection = 8; - else if (eqNByte(RateSection, (u8 *)("VHT"), 3) && eqNByte(RfPath, (u8 *)("4T"), 2)) - rateSection = 9; else return; @@ -1847,38 +1163,21 @@ void PHY_SetTxPowerLimit( else if (eqNByte(Bandwidth, (u8 *)("160M"), 4)) bandwidth = 3; - if (eqNByte(Band, (u8 *)("2.4G"), 4)) { - channelIndex = phy_GetChannelIndexOfTxPowerLimit(BAND_ON_2_4G, channel); + channelIndex = phy_GetChannelIndexOfTxPowerLimit(channel); - if (channelIndex == -1) - return; - - prevPowerLimit = pHalData->TxPwrLimit_2_4G[regulation][bandwidth][rateSection][channelIndex][ODM_RF_PATH_A]; - - if (powerLimit < prevPowerLimit) - pHalData->TxPwrLimit_2_4G[regulation][bandwidth][rateSection][channelIndex][ODM_RF_PATH_A] = powerLimit; - - } else if (eqNByte(Band, (u8 *)("5G"), 2)) { - channelIndex = phy_GetChannelIndexOfTxPowerLimit(BAND_ON_5G, channel); - - if (channelIndex == -1) - return; - - prevPowerLimit = pHalData->TxPwrLimit_5G[regulation][bandwidth][rateSection][channelIndex][ODM_RF_PATH_A]; + if (channelIndex == -1) + return; - if (powerLimit < prevPowerLimit) - pHalData->TxPwrLimit_5G[regulation][bandwidth][rateSection][channelIndex][ODM_RF_PATH_A] = powerLimit; + prevPowerLimit = pHalData->TxPwrLimit_2_4G[regulation][bandwidth][rateSection][channelIndex][ODM_RF_PATH_A]; - } else { - return; - } + if (powerLimit < prevPowerLimit) + pHalData->TxPwrLimit_2_4G[regulation][bandwidth][rateSection][channelIndex][ODM_RF_PATH_A] = powerLimit; } void Hal_ChannelPlanToRegulation(struct adapter *Adapter, u16 ChannelPlan) { struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); pHalData->Regulation2_4G = TXPWR_LMT_WW; - pHalData->Regulation5G = TXPWR_LMT_WW; switch (ChannelPlan) { case RT_CHANNEL_DOMAIN_WORLD_NULL: @@ -1898,139 +1197,105 @@ void Hal_ChannelPlanToRegulation(struct adapter *Adapter, u16 ChannelPlan) break; case RT_CHANNEL_DOMAIN_FCC1_FCC1: pHalData->Regulation2_4G = TXPWR_LMT_FCC; - pHalData->Regulation5G = TXPWR_LMT_FCC; break; case RT_CHANNEL_DOMAIN_WORLD_ETSI1: pHalData->Regulation2_4G = TXPWR_LMT_FCC; - pHalData->Regulation5G = TXPWR_LMT_ETSI; break; case RT_CHANNEL_DOMAIN_MKK1_MKK1: pHalData->Regulation2_4G = TXPWR_LMT_MKK; - pHalData->Regulation5G = TXPWR_LMT_MKK; break; case RT_CHANNEL_DOMAIN_WORLD_KCC1: pHalData->Regulation2_4G = TXPWR_LMT_FCC; - pHalData->Regulation5G = TXPWR_LMT_MKK; break; case RT_CHANNEL_DOMAIN_WORLD_FCC2: pHalData->Regulation2_4G = TXPWR_LMT_FCC; - pHalData->Regulation5G = TXPWR_LMT_FCC; break; case RT_CHANNEL_DOMAIN_WORLD_FCC3: pHalData->Regulation2_4G = TXPWR_LMT_FCC; - pHalData->Regulation5G = TXPWR_LMT_FCC; break; case RT_CHANNEL_DOMAIN_WORLD_FCC4: pHalData->Regulation2_4G = TXPWR_LMT_FCC; - pHalData->Regulation5G = TXPWR_LMT_FCC; break; case RT_CHANNEL_DOMAIN_WORLD_FCC5: pHalData->Regulation2_4G = TXPWR_LMT_FCC; - pHalData->Regulation5G = TXPWR_LMT_FCC; break; case RT_CHANNEL_DOMAIN_WORLD_FCC6: pHalData->Regulation2_4G = TXPWR_LMT_FCC; - pHalData->Regulation5G = TXPWR_LMT_FCC; break; case RT_CHANNEL_DOMAIN_FCC1_FCC7: pHalData->Regulation2_4G = TXPWR_LMT_FCC; - pHalData->Regulation5G = TXPWR_LMT_FCC; break; case RT_CHANNEL_DOMAIN_WORLD_ETSI2: pHalData->Regulation2_4G = TXPWR_LMT_FCC; - pHalData->Regulation5G = TXPWR_LMT_FCC; break; case RT_CHANNEL_DOMAIN_WORLD_ETSI3: pHalData->Regulation2_4G = TXPWR_LMT_FCC; - pHalData->Regulation5G = TXPWR_LMT_FCC; break; case RT_CHANNEL_DOMAIN_MKK1_MKK2: pHalData->Regulation2_4G = TXPWR_LMT_MKK; - pHalData->Regulation5G = TXPWR_LMT_FCC; break; case RT_CHANNEL_DOMAIN_MKK1_MKK3: pHalData->Regulation2_4G = TXPWR_LMT_MKK; - pHalData->Regulation5G = TXPWR_LMT_FCC; break; case RT_CHANNEL_DOMAIN_FCC1_NCC1: pHalData->Regulation2_4G = TXPWR_LMT_FCC; - pHalData->Regulation5G = TXPWR_LMT_FCC; break; case RT_CHANNEL_DOMAIN_FCC1_NCC2: pHalData->Regulation2_4G = TXPWR_LMT_FCC; - pHalData->Regulation5G = TXPWR_LMT_FCC; break; case RT_CHANNEL_DOMAIN_GLOBAL_NULL: pHalData->Regulation2_4G = TXPWR_LMT_WW; - pHalData->Regulation5G = TXPWR_LMT_WW; break; case RT_CHANNEL_DOMAIN_ETSI1_ETSI4: pHalData->Regulation2_4G = TXPWR_LMT_ETSI; - pHalData->Regulation5G = TXPWR_LMT_ETSI; break; case RT_CHANNEL_DOMAIN_FCC1_FCC2: pHalData->Regulation2_4G = TXPWR_LMT_FCC; - pHalData->Regulation5G = TXPWR_LMT_FCC; break; case RT_CHANNEL_DOMAIN_FCC1_NCC3: pHalData->Regulation2_4G = TXPWR_LMT_FCC; - pHalData->Regulation5G = TXPWR_LMT_FCC; break; case RT_CHANNEL_DOMAIN_WORLD_ETSI5: pHalData->Regulation2_4G = TXPWR_LMT_ETSI; - pHalData->Regulation5G = TXPWR_LMT_ETSI; break; case RT_CHANNEL_DOMAIN_FCC1_FCC8: pHalData->Regulation2_4G = TXPWR_LMT_FCC; - pHalData->Regulation5G = TXPWR_LMT_FCC; break; case RT_CHANNEL_DOMAIN_WORLD_ETSI6: pHalData->Regulation2_4G = TXPWR_LMT_ETSI; - pHalData->Regulation5G = TXPWR_LMT_ETSI; break; case RT_CHANNEL_DOMAIN_WORLD_ETSI7: pHalData->Regulation2_4G = TXPWR_LMT_ETSI; - pHalData->Regulation5G = TXPWR_LMT_ETSI; break; case RT_CHANNEL_DOMAIN_WORLD_ETSI8: pHalData->Regulation2_4G = TXPWR_LMT_ETSI; - pHalData->Regulation5G = TXPWR_LMT_ETSI; break; case RT_CHANNEL_DOMAIN_WORLD_ETSI9: pHalData->Regulation2_4G = TXPWR_LMT_ETSI; - pHalData->Regulation5G = TXPWR_LMT_ETSI; break; case RT_CHANNEL_DOMAIN_WORLD_ETSI10: pHalData->Regulation2_4G = TXPWR_LMT_ETSI; - pHalData->Regulation5G = TXPWR_LMT_ETSI; break; case RT_CHANNEL_DOMAIN_WORLD_ETSI11: pHalData->Regulation2_4G = TXPWR_LMT_ETSI; - pHalData->Regulation5G = TXPWR_LMT_ETSI; break; case RT_CHANNEL_DOMAIN_FCC1_NCC4: pHalData->Regulation2_4G = TXPWR_LMT_FCC; - pHalData->Regulation5G = TXPWR_LMT_FCC; break; case RT_CHANNEL_DOMAIN_WORLD_ETSI12: pHalData->Regulation2_4G = TXPWR_LMT_ETSI; - pHalData->Regulation5G = TXPWR_LMT_ETSI; break; case RT_CHANNEL_DOMAIN_FCC1_FCC9: pHalData->Regulation2_4G = TXPWR_LMT_FCC; - pHalData->Regulation5G = TXPWR_LMT_FCC; break; case RT_CHANNEL_DOMAIN_WORLD_ETSI13: pHalData->Regulation2_4G = TXPWR_LMT_ETSI; - pHalData->Regulation5G = TXPWR_LMT_ETSI; break; case RT_CHANNEL_DOMAIN_FCC1_FCC10: pHalData->Regulation2_4G = TXPWR_LMT_FCC; - pHalData->Regulation5G = TXPWR_LMT_FCC; break; case RT_CHANNEL_DOMAIN_REALTEK_DEFINE: /* Realtek Reserve */ pHalData->Regulation2_4G = TXPWR_LMT_WW; - pHalData->Regulation5G = TXPWR_LMT_WW; break; default: break; diff --git a/drivers/staging/rtl8723bs/hal/hal_intf.c b/drivers/staging/rtl8723bs/hal/hal_intf.c index 8dc4dd8c6d4c..4868a69cdb8f 100644 --- a/drivers/staging/rtl8723bs/hal/hal_intf.c +++ b/drivers/staging/rtl8723bs/hal/hal_intf.c @@ -4,9 +4,6 @@ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. * ******************************************************************************/ - -#define _HAL_INTF_C_ - #include <drv_types.h> #include <rtw_debug.h> #include <hal_data.h> diff --git a/drivers/staging/rtl8723bs/hal/odm.c b/drivers/staging/rtl8723bs/hal/odm.c index 092b32c41ff3..68dfb77772b2 100644 --- a/drivers/staging/rtl8723bs/hal/odm.c +++ b/drivers/staging/rtl8723bs/hal/odm.c @@ -290,8 +290,6 @@ static void odm_CommonInfoSelfInit(struct dm_odm_t *pDM_Odm) pDM_Odm->bCckHighPower = (bool) PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG(CCK_RPT_FORMAT, pDM_Odm), ODM_BIT(CCK_RPT_FORMAT, pDM_Odm)); pDM_Odm->RFPathRxEnable = (u8) PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG(BB_RX_PATH, pDM_Odm), ODM_BIT(BB_RX_PATH, pDM_Odm)); - ODM_InitDebugSetting(pDM_Odm); - pDM_Odm->TxRate = 0xFF; } @@ -323,32 +321,10 @@ static void odm_CommonInfoSelfUpdate(struct dm_odm_t *pDM_Odm) static void odm_CmnInfoInit_Debug(struct dm_odm_t *pDM_Odm) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_CmnInfoInit_Debug ==>\n")); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportPlatform =%d\n", pDM_Odm->SupportPlatform)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportAbility = 0x%x\n", pDM_Odm->SupportAbility)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportInterface =%d\n", pDM_Odm->SupportInterface)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportICType = 0x%x\n", pDM_Odm->SupportICType)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("CutVersion =%d\n", pDM_Odm->CutVersion)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("FabVersion =%d\n", pDM_Odm->FabVersion)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("RFType =%d\n", pDM_Odm->RFType)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("BoardType =%d\n", pDM_Odm->BoardType)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtLNA =%d\n", pDM_Odm->ExtLNA)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtPA =%d\n", pDM_Odm->ExtPA)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtTRSW =%d\n", pDM_Odm->ExtTRSW)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("PatchID =%d\n", pDM_Odm->PatchID)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bInHctTest =%d\n", pDM_Odm->bInHctTest)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bWIFITest =%d\n", pDM_Odm->bWIFITest)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bDualMacSmartConcurrent =%d\n", pDM_Odm->bDualMacSmartConcurrent)); - } static void odm_BasicDbgMessage(struct dm_odm_t *pDM_Odm) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_BasicDbgMsg ==>\n")); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bLinked = %d, RSSI_Min = %d,\n", - pDM_Odm->bLinked, pDM_Odm->RSSI_Min)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("RxRate = 0x%x, RSSI_A = %d, RSSI_B = %d\n", - pDM_Odm->RxRate, pDM_Odm->RSSI_A, pDM_Odm->RSSI_B)); } /* 3 ============================================================ */ @@ -401,7 +377,6 @@ u32 ODM_Get_Rate_Bitmap( break; case (ODM_WM_G): - case (ODM_WM_A): if (rssi_level == DM_RATR_STA_HIGH) rate_bitmap = 0x00000f00; else @@ -420,7 +395,6 @@ u32 ODM_Get_Rate_Bitmap( case (ODM_WM_B|ODM_WM_G|ODM_WM_N24G): case (ODM_WM_B|ODM_WM_N24G): case (ODM_WM_G|ODM_WM_N24G): - case (ODM_WM_A|ODM_WM_N5G): if (pDM_Odm->RFType == ODM_1T2R || pDM_Odm->RFType == ODM_1T1R) { if (rssi_level == DM_RATR_STA_HIGH) rate_bitmap = 0x000f0000; @@ -446,34 +420,6 @@ u32 ODM_Get_Rate_Bitmap( } break; - case (ODM_WM_AC|ODM_WM_G): - if (rssi_level == 1) - rate_bitmap = 0xfc3f0000; - else if (rssi_level == 2) - rate_bitmap = 0xfffff000; - else - rate_bitmap = 0xffffffff; - break; - - case (ODM_WM_AC|ODM_WM_A): - - if (pDM_Odm->RFType == RF_1T1R) { - if (rssi_level == 1) /* add by Gary for ac-series */ - rate_bitmap = 0x003f8000; - else if (rssi_level == 2) - rate_bitmap = 0x003ff000; - else - rate_bitmap = 0x003ff010; - } else { - if (rssi_level == 1) /* add by Gary for ac-series */ - rate_bitmap = 0xfe3f8000; /* VHT 2SS MCS3~9 */ - else if (rssi_level == 2) - rate_bitmap = 0xfffff000; /* VHT 2SS MCS0~9 */ - else - rate_bitmap = 0xfffff010; /* All */ - } - break; - default: if (pDM_Odm->RFType == RF_1T2R) rate_bitmap = 0x000fffff; @@ -482,9 +428,6 @@ u32 ODM_Get_Rate_Bitmap( break; } - /* printk("%s ==> rssi_level:0x%02x, WirelessMode:0x%02x, rate_bitmap:0x%08x\n", __func__, rssi_level, WirelessMode, rate_bitmap); */ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, (" ==> rssi_level:0x%02x, WirelessMode:0x%02x, rate_bitmap:0x%08x\n", rssi_level, WirelessMode, rate_bitmap)); - return ra_mask & rate_bitmap; } @@ -495,12 +438,10 @@ static void odm_RefreshRateAdaptiveMaskCE(struct dm_odm_t *pDM_Odm) struct adapter *padapter = pDM_Odm->Adapter; if (padapter->bDriverStopped) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_TRACE, ("<---- odm_RefreshRateAdaptiveMask(): driver is going to unload\n")); return; } if (!pDM_Odm->bUseRAMask) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("<---- odm_RefreshRateAdaptiveMask(): driver does not control rate adaptive mask\n")); return; } @@ -512,7 +453,6 @@ static void odm_RefreshRateAdaptiveMaskCE(struct dm_odm_t *pDM_Odm) continue; if (true == ODM_RAStateCheck(pDM_Odm, pstat->rssi_stat.UndecoratedSmoothedPWDB, false, &pstat->rssi_level)) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("RSSI:%d, RSSI_LEVEL:%d\n", pstat->rssi_stat.UndecoratedSmoothedPWDB, pstat->rssi_level)); /* printk("RSSI:%d, RSSI_LEVEL:%d\n", pstat->rssi_stat.UndecoratedSmoothedPWDB, pstat->rssi_level); */ rtw_hal_update_ra_mask(pstat, pstat->rssi_level); } @@ -541,9 +481,7 @@ static void odm_RefreshRateAdaptiveMaskCE(struct dm_odm_t *pDM_Odm) static void odm_RefreshRateAdaptiveMask(struct dm_odm_t *pDM_Odm) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_TRACE, ("odm_RefreshRateAdaptiveMask()---------->\n")); if (!(pDM_Odm->SupportAbility & ODM_BB_RA_MASK)) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_TRACE, ("odm_RefreshRateAdaptiveMask(): Return cos not supported\n")); return; } odm_RefreshRateAdaptiveMaskCE(pDM_Odm); @@ -582,7 +520,8 @@ bool ODM_RAStateCheck( break; default: - ODM_RT_ASSERT(pDM_Odm, false, ("wrong rssi level setting %d !", *pRATRState)); + netdev_dbg(pDM_Odm->Adapter->pnetdev, + "wrong rssi level setting %d !", *pRATRState); break; } @@ -596,7 +535,6 @@ bool ODM_RAStateCheck( /* printk("==>%s, RATRState:0x%02x , RSSI:%d\n", __func__, RATRState, RSSI); */ if (*pRATRState != RATRState || bForceUpdate) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("RSSI Level %d -> %d\n", *pRATRState, RATRState)); *pRATRState = RATRState; return true; } @@ -631,11 +569,8 @@ static void FindMinimumRSSI(struct adapter *padapter) (pdmpriv->EntryMinUndecoratedSmoothedPWDB == 0) ) { pdmpriv->MinUndecoratedPWDBForDM = 0; - /* ODM_RT_TRACE(pDM_Odm, COMP_BB_POWERSAVING, DBG_LOUD, ("Not connected to any\n")); */ } else pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB; - - /* ODM_RT_TRACE(pDM_Odm, COMP_DIG, DBG_LOUD, ("MinUndecoratedPWDBForDM =%d\n", pHalData->MinUndecoratedPWDBForDM)); */ } static void odm_RSSIMonitorCheckCE(struct dm_odm_t *pDM_Odm) @@ -838,9 +773,6 @@ void ODM_DMInit(struct dm_odm_t *pDM_Odm) ODM_ClearTxPowerTrackingState(pDM_Odm); - if (*(pDM_Odm->mp_mode) != 1) - odm_PathDiversityInit(pDM_Odm); - odm_DynamicBBPowerSavingInit(pDM_Odm); odm_DynamicTxPowerInit(pDM_Odm); @@ -858,7 +790,6 @@ void ODM_DMWatchdog(struct dm_odm_t *pDM_Odm) odm_BasicDbgMessage(pDM_Odm); odm_FalseAlarmCounterStatistics(pDM_Odm); odm_NHMCounterStatistics(pDM_Odm); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): RSSI = 0x%x\n", pDM_Odm->RSSI_Min)); odm_RSSIMonitorCheck(pDM_Odm); @@ -872,8 +803,6 @@ void ODM_DMWatchdog(struct dm_odm_t *pDM_Odm) /* (pDM_Odm->SupportICType & (ODM_RTL8188E) &&(&&(((pDM_Odm->SupportInterface == ODM_ITRF_SDIO))) */ /* */ ) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("----Step1: odm_DIG is in LPS mode\n")); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("---Step2: 8723AS is in LPS mode\n")); odm_DIGbyRSSI_LPS(pDM_Odm); } else odm_DIG(pDM_Odm); @@ -891,7 +820,6 @@ void ODM_DMWatchdog(struct dm_odm_t *pDM_Odm) odm_RefreshRateAdaptiveMask(pDM_Odm); odm_EdcaTurboCheck(pDM_Odm); - odm_PathDiversity(pDM_Odm); ODM_CfoTracking(pDM_Odm); ODM_TXPowerTrackingCheck(pDM_Odm); @@ -956,10 +884,6 @@ void ODM_CmnInfoInit(struct dm_odm_t *pDM_Odm, enum odm_cmninfo_e CmnInfo, u32 V pDM_Odm->AntDivType = (u8)Value; break; - case ODM_CMNINFO_BOARD_TYPE: - pDM_Odm->BoardType = (u8)Value; - break; - case ODM_CMNINFO_PACKAGE_TYPE: pDM_Odm->PackageType = (u8)Value; break; @@ -968,18 +892,10 @@ void ODM_CmnInfoInit(struct dm_odm_t *pDM_Odm, enum odm_cmninfo_e CmnInfo, u32 V pDM_Odm->ExtLNA = (u8)Value; break; - case ODM_CMNINFO_5G_EXT_LNA: - pDM_Odm->ExtLNA5G = (u8)Value; - break; - case ODM_CMNINFO_EXT_PA: pDM_Odm->ExtPA = (u8)Value; break; - case ODM_CMNINFO_5G_EXT_PA: - pDM_Odm->ExtPA5G = (u8)Value; - break; - case ODM_CMNINFO_GPA: pDM_Odm->TypeGPA = (enum odm_type_gpa_e)Value; break; @@ -1044,10 +960,6 @@ void ODM_CmnInfoHook(struct dm_odm_t *pDM_Odm, enum odm_cmninfo_e CmnInfo, void pDM_Odm->pwirelessmode = pValue; break; - case ODM_CMNINFO_BAND: - pDM_Odm->pBandType = pValue; - break; - case ODM_CMNINFO_SEC_CHNL_OFFSET: pDM_Odm->pSecChOffset = pValue; break; @@ -1214,13 +1126,6 @@ void ODM_CmnInfoUpdate(struct dm_odm_t *pDM_Odm, u32 CmnInfo, u64 Value) pDM_Odm->RSSI_Min = (u8)Value; break; - case ODM_CMNINFO_DBG_COMP: - pDM_Odm->DebugComponents = Value; - break; - - case ODM_CMNINFO_DBG_LEVEL: - pDM_Odm->DebugLevel = (u32)Value; - break; case ODM_CMNINFO_RA_THRESHOLD_HIGH: pDM_Odm->RateAdaptive.HighRSSIThresh = (u8)Value; break; @@ -1262,10 +1167,6 @@ void ODM_CmnInfoUpdate(struct dm_odm_t *pDM_Odm, u32 CmnInfo, u64 Value) pDM_Odm->WirelessMode = (u8)Value; break; - case ODM_CMNINFO_BAND: - pDM_Odm->BandType = (u8)Value; - break; - case ODM_CMNINFO_SEC_CHNL_OFFSET: pDM_Odm->SecChOffset = (u8)Value; break; diff --git a/drivers/staging/rtl8723bs/hal/odm.h b/drivers/staging/rtl8723bs/hal/odm.h index ff21343fbe0b..abf6547518fb 100644 --- a/drivers/staging/rtl8723bs/hal/odm.h +++ b/drivers/staging/rtl8723bs/hal/odm.h @@ -11,7 +11,6 @@ #include "odm_EdcaTurboCheck.h" #include "odm_DIG.h" -#include "odm_PathDiv.h" #include "odm_DynamicBBPowerSaving.h" #include "odm_DynamicTxPower.h" #include "odm_CfoTracking.h" @@ -152,7 +151,6 @@ struct swat_t { /* _SW_Antenna_Switch_ */ bool ANTB_ON; /* To indicate Ant B is on or not */ bool Pre_Aux_FailDetec; bool RSSI_AntDect_bResult; - u8 Ant5G; u8 Ant2G; s32 RSSI_sum_A; @@ -197,10 +195,7 @@ struct odm_rate_adaptive { #define AVG_THERMAL_NUM 8 #define IQK_Matrix_REG_NUM 8 -#define IQK_Matrix_Settings_NUM (14 + 24 + 21) /* Channels_2_4G_NUM - * + Channels_5G_20M_NUM - * + Channels_5G - */ +#define IQK_Matrix_Settings_NUM 14 /* Channels_2_4G_NUM */ #define DM_Type_ByFW 0 #define DM_Type_ByDriver 1 @@ -293,12 +288,9 @@ enum odm_cmninfo_e { ODM_CMNINFO_FAB_VER, /* ODM_FAB_E */ ODM_CMNINFO_RF_TYPE, /* ODM_RF_PATH_E or ODM_RF_TYPE_E? */ ODM_CMNINFO_RFE_TYPE, - ODM_CMNINFO_BOARD_TYPE, /* ODM_BOARD_TYPE_E */ ODM_CMNINFO_PACKAGE_TYPE, ODM_CMNINFO_EXT_LNA, /* true */ - ODM_CMNINFO_5G_EXT_LNA, ODM_CMNINFO_EXT_PA, - ODM_CMNINFO_5G_EXT_PA, ODM_CMNINFO_GPA, ODM_CMNINFO_APA, ODM_CMNINFO_GLNA, @@ -316,7 +308,6 @@ enum odm_cmninfo_e { ODM_CMNINFO_TX_UNI, ODM_CMNINFO_RX_UNI, ODM_CMNINFO_WM_MODE, /* ODM_WIRELESS_MODE_E */ - ODM_CMNINFO_BAND, /* ODM_BAND_TYPE_E */ ODM_CMNINFO_SEC_CHNL_OFFSET, /* ODM_SEC_CHNL_OFFSET_E */ ODM_CMNINFO_SEC_MODE, /* ODM_SECURITY_E */ ODM_CMNINFO_BW, /* ODM_BW_E */ @@ -456,33 +447,17 @@ enum { /* tag_Wireless_Mode_Definition */ ODM_WM_UNKNOWN = 0x0, ODM_WM_B = BIT0, ODM_WM_G = BIT1, - ODM_WM_A = BIT2, ODM_WM_N24G = BIT3, - ODM_WM_N5G = BIT4, ODM_WM_AUTO = BIT5, - ODM_WM_AC = BIT6, -}; - -/* ODM_CMNINFO_BAND */ -enum { /* tag_Band_Type_Definition */ - ODM_BAND_2_4G = 0, - ODM_BAND_5G, - ODM_BAND_ON_BOTH, - ODM_BANDMAX }; /* ODM_CMNINFO_BW */ enum { /* tag_Bandwidth_Definition */ ODM_BW20M = 0, ODM_BW40M = 1, - ODM_BW80M = 2, - ODM_BW160M = 3, - ODM_BW10M = 4, }; -/* ODM_CMNINFO_BOARD_TYPE */ -/* For non-AC-series IC , ODM_BOARD_5G_EXT_PA and ODM_BOARD_5G_EXT_LNA are ignored */ -/* For AC-series IC, external PA & LNA can be indivisuallly added on 2.4G and/or 5G */ +/* For AC-series IC, external PA & LNA can be individually added on 2.4G */ enum odm_type_gpa_e { /* tag_ODM_TYPE_GPA_Definition */ TYPE_GPA0 = 0, @@ -530,7 +505,6 @@ struct odm_rf_cal_t { /* ODM_RF_Calibration_Structure */ bool bTXPowerTracking; u8 TxPowerTrackControl; /* for mp mode, turn off txpwrtracking as default */ u8 TM_Trigger; - u8 InternalPA5G[2]; /* pathA / pathB */ u8 ThermalMeter[2]; /* ThermalMeter, index 0 for RFIC0, and 1 for RFIC1 */ u8 ThermalValue; @@ -565,7 +539,7 @@ struct odm_rf_cal_t { /* ODM_RF_Calibration_Structure */ bool bIQKInProgress; u8 Delta_IQK; u8 Delta_LCK; - s8 BBSwingDiff2G, BBSwingDiff5G; /* Unit: dB */ + s8 BBSwingDiff2G; /* Unit: dB */ u8 DeltaSwingTableIdx_2GCCKA_P[DELTA_SWINGIDX_SIZE]; u8 DeltaSwingTableIdx_2GCCKA_N[DELTA_SWINGIDX_SIZE]; u8 DeltaSwingTableIdx_2GCCKB_P[DELTA_SWINGIDX_SIZE]; @@ -574,10 +548,6 @@ struct odm_rf_cal_t { /* ODM_RF_Calibration_Structure */ u8 DeltaSwingTableIdx_2GA_N[DELTA_SWINGIDX_SIZE]; u8 DeltaSwingTableIdx_2GB_P[DELTA_SWINGIDX_SIZE]; u8 DeltaSwingTableIdx_2GB_N[DELTA_SWINGIDX_SIZE]; - u8 DeltaSwingTableIdx_5GA_P[BAND_NUM][DELTA_SWINGIDX_SIZE]; - u8 DeltaSwingTableIdx_5GA_N[BAND_NUM][DELTA_SWINGIDX_SIZE]; - u8 DeltaSwingTableIdx_5GB_P[BAND_NUM][DELTA_SWINGIDX_SIZE]; - u8 DeltaSwingTableIdx_5GB_N[BAND_NUM][DELTA_SWINGIDX_SIZE]; u8 DeltaSwingTableIdx_2GA_P_8188E[DELTA_SWINGIDX_SIZE]; u8 DeltaSwingTableIdx_2GA_N_8188E[DELTA_SWINGIDX_SIZE]; @@ -643,8 +613,6 @@ struct fat_t { /* _FAST_ANTENNA_TRAINNING_ */ bool bBecomeLinked; u32 MinMaxRSSI; u8 idx_AntDiv_counter_2G; - u8 idx_AntDiv_counter_5G; - u32 AntDiv_2G_5G; u32 CCK_counter_main; u32 CCK_counter_aux; u32 OFDM_counter_main; @@ -710,9 +678,6 @@ struct dm_odm_t { /* DM_Out_Source_Dynamic_Mechanism_Structure */ enum phy_reg_pg_type PhyRegPgValueType; u8 PhyRegPgVersion; - u64 DebugComponents; - u32 DebugLevel; - u32 NumQryPhyStatusAll; /* CCK + OFDM */ u32 LastNumQryPhyStatusAll; u32 RxPWDBAve; @@ -766,10 +731,8 @@ struct dm_odm_t { /* DM_Out_Source_Dynamic_Mechanism_Structure */ u8 TypeAPA; /* with external LNA NO/Yes = 0/1 */ u8 ExtLNA; - u8 ExtLNA5G; /* with external PA NO/Yes = 0/1 */ u8 ExtPA; - u8 ExtPA5G; /* with external TRSW NO/Yes = 0/1 */ u8 ExtTRSW; u8 PatchID; /* Customer ID */ @@ -798,8 +761,6 @@ struct dm_odm_t { /* DM_Out_Source_Dynamic_Mechanism_Structure */ u64 *pNumRxBytesUnicast; /* Wireless mode B/G/A/N = BIT0/BIT1/BIT2/BIT3 */ u8 *pwirelessmode; /* ODM_WIRELESS_MODE_E */ - /* Frequence band 2.4G/5G = 0/1 */ - u8 *pBandType; /* Secondary channel offset don't_care/below/above = 0/1/2 */ u8 *pSecChOffset; /* Security mode Open/WEP/AES/TKIP = 0/1/2/3 */ @@ -1068,7 +1029,6 @@ enum ODM_BB_Config_Type { CONFIG_BB_PHY_REG, CONFIG_BB_AGC_TAB, CONFIG_BB_AGC_TAB_2G, - CONFIG_BB_AGC_TAB_5G, CONFIG_BB_PHY_REG_PG, CONFIG_BB_PHY_REG_MP, CONFIG_BB_AGC_TAB_DIFF, diff --git a/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c b/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c index 75471c6c168e..0f6b9d661e39 100644 --- a/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c +++ b/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c @@ -25,16 +25,6 @@ static void odm_SetCrystalCap(void *pDM_VOID, u8 CrystalCap) 0x00FFF000, (CrystalCap | (CrystalCap << 6)) ); - - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_CFO_TRACKING, - ODM_DBG_LOUD, - ( - "odm_SetCrystalCap(): CrystalCap = 0x%x\n", - CrystalCap - ) - ); } static u8 odm_GetDefaultCrytaltalCap(void *pDM_VOID) @@ -98,22 +88,6 @@ void ODM_CfoTrackingInit(void *pDM_VOID) pCfoTrack->CrystalCap = odm_GetDefaultCrytaltalCap(pDM_Odm); pCfoTrack->bATCStatus = odm_GetATCStatus(pDM_Odm); pCfoTrack->bAdjust = true; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_CFO_TRACKING, - ODM_DBG_LOUD, - ("ODM_CfoTracking_init() =========>\n") - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_CFO_TRACKING, - ODM_DBG_LOUD, - ( - "ODM_CfoTracking_init(): bATCStatus = %d, CrystalCap = 0x%x\n", - pCfoTrack->bATCStatus, - pCfoTrack->DefXCap - ) - ); } void ODM_CfoTracking(void *pDM_VOID) @@ -127,47 +101,16 @@ void ODM_CfoTracking(void *pDM_VOID) /* 4 Support ability */ if (!(pDM_Odm->SupportAbility & ODM_BB_CFO_TRACKING)) { - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_CFO_TRACKING, - ODM_DBG_LOUD, - ("ODM_CfoTracking(): Return: SupportAbility ODM_BB_CFO_TRACKING is disabled\n") - ); return; } - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_CFO_TRACKING, - ODM_DBG_LOUD, - ("ODM_CfoTracking() =========>\n") - ); - if (!pDM_Odm->bLinked || !pDM_Odm->bOneEntryOnly) { /* 4 No link or more than one entry */ ODM_CfoTrackingReset(pDM_Odm); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_CFO_TRACKING, - ODM_DBG_LOUD, - ( - "ODM_CfoTracking(): Reset: bLinked = %d, bOneEntryOnly = %d\n", - pDM_Odm->bLinked, - pDM_Odm->bOneEntryOnly - ) - ); } else { /* 3 1. CFO Tracking */ /* 4 1.1 No new packet */ if (pCfoTrack->packetCount == pCfoTrack->packetCount_pre) { - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_CFO_TRACKING, - ODM_DBG_LOUD, - ( - "ODM_CfoTracking(): packet counter doesn't change\n" - ) - ); return; } pCfoTrack->packetCount_pre = pCfoTrack->packetCount; @@ -180,17 +123,6 @@ void ODM_CfoTracking(void *pDM_VOID) CFO_ave = CFO_kHz_A; else CFO_ave = (int)(CFO_kHz_A + CFO_kHz_B) >> 1; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_CFO_TRACKING, - ODM_DBG_LOUD, - ( - "ODM_CfoTracking(): CFO_kHz_A = %dkHz, CFO_kHz_B = %dkHz, CFO_ave = %dkHz\n", - CFO_kHz_A, - CFO_kHz_B, - CFO_ave - ) - ); /* 4 1.3 Avoid abnormal large CFO */ CFO_ave_diff = @@ -203,7 +135,6 @@ void ODM_CfoTracking(void *pDM_VOID) pCfoTrack->largeCFOHit == 0 && !pCfoTrack->bAdjust ) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("ODM_CfoTracking(): first large CFO hit\n")); pCfoTrack->largeCFOHit = 1; return; } else @@ -223,12 +154,6 @@ void ODM_CfoTracking(void *pDM_VOID) if (pDM_Odm->bBtEnabled) { pCfoTrack->bAdjust = false; odm_SetCrystalCap(pDM_Odm, pCfoTrack->DefXCap); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_CFO_TRACKING, - ODM_DBG_LOUD, - ("ODM_CfoTracking(): Disable CFO tracking for BT!!\n") - ); } /* 4 1.6 Big jump */ @@ -237,16 +162,6 @@ void ODM_CfoTracking(void *pDM_VOID) Adjust_Xtal = Adjust_Xtal+((CFO_ave-CFO_TH_XTAL_LOW)>>2); else if (CFO_ave < (-CFO_TH_XTAL_LOW)) Adjust_Xtal = Adjust_Xtal+((CFO_TH_XTAL_LOW-CFO_ave)>>2); - - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_CFO_TRACKING, - ODM_DBG_LOUD, - ( - "ODM_CfoTracking(): Crystal cap offset = %d\n", - Adjust_Xtal - ) - ); } /* 4 1.7 Adjust Crystal Cap. */ @@ -263,34 +178,12 @@ void ODM_CfoTracking(void *pDM_VOID) odm_SetCrystalCap(pDM_Odm, (u8)CrystalCap); } - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_CFO_TRACKING, - ODM_DBG_LOUD, - ( - "ODM_CfoTracking(): Crystal cap = 0x%x, Default Crystal cap = 0x%x\n", - pCfoTrack->CrystalCap, - pCfoTrack->DefXCap - ) - ); /* 3 2. Dynamic ATC switch */ if (CFO_ave < CFO_TH_ATC && CFO_ave > -CFO_TH_ATC) { odm_SetATCStatus(pDM_Odm, false); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_CFO_TRACKING, - ODM_DBG_LOUD, - ("ODM_CfoTracking(): Disable ATC!!\n") - ); } else { odm_SetATCStatus(pDM_Odm, true); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_CFO_TRACKING, - ODM_DBG_LOUD, - ("ODM_CfoTracking(): Enable ATC!!\n") - ); } } } diff --git a/drivers/staging/rtl8723bs/hal/odm_DIG.c b/drivers/staging/rtl8723bs/hal/odm_DIG.c index dcef7fb17389..ef5b48bb01b2 100644 --- a/drivers/staging/rtl8723bs/hal/odm_DIG.c +++ b/drivers/staging/rtl8723bs/hal/odm_DIG.c @@ -81,17 +81,6 @@ void odm_NHMBB(void *pDM_VOID) *(pDM_Odm->pNumTxBytesUnicast); pDM_Odm->NHMLastRxOkcnt = *(pDM_Odm->pNumRxBytesUnicast); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_DIG, - ODM_DBG_LOUD, - ( - "NHM_cnt_0 =%d, NHMCurTxOkcnt = %llu, NHMCurRxOkcnt = %llu\n", - pDM_Odm->NHM_cnt_0, - pDM_Odm->NHMCurTxOkcnt, - pDM_Odm->NHMCurRxOkcnt - ) - ); if ((pDM_Odm->NHMCurTxOkcnt) + 1 > (u64)(pDM_Odm->NHMCurRxOkcnt<<2) + 1) { /* Tx > 4*Rx possible for adaptivity test */ @@ -127,8 +116,6 @@ void odm_NHMBB(void *pDM_VOID) } } } - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("adaptivity_flag = %d\n ", pDM_Odm->adaptivity_flag)); } void odm_SearchPwdBLowerBound(void *pDM_VOID, u8 IGI_target) @@ -165,7 +152,6 @@ void odm_SearchPwdBLowerBound(void *pDM_VOID, u8 IGI_target) else pDM_Odm->txEdcca0 = pDM_Odm->txEdcca0 + 1; } - /* DbgPrint("txEdcca1 = %d, txEdcca0 = %d\n", pDM_Odm->txEdcca1, pDM_Odm->txEdcca0); */ if (pDM_Odm->txEdcca1 > 5) { IGI = IGI-1; @@ -199,8 +185,6 @@ void odm_SearchPwdBLowerBound(void *pDM_VOID, u8 IGI_target) pDM_Odm->Adaptivity_IGI_upper = IGI; } } - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("IGI = 0x%x, H2L_lb = 0x%x, L2H_lb = 0x%x\n", IGI, pDM_Odm->H2L_lb, pDM_Odm->L2H_lb)); } void odm_AdaptivityInit(void *pDM_VOID) @@ -239,19 +223,13 @@ void odm_Adaptivity(void *pDM_VOID, u8 IGI) bool EDCCA_State = false; if (!(pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY)) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("Go to odm_DynamicEDCCA()\n")); return; } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_Adaptivity() =====>\n")); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("ForceEDCCA =%d, IGI_Base = 0x%x, TH_L2H_ini = %d, TH_EDCCA_HL_diff = %d, AdapEn_RSSI = %d\n", - pDM_Odm->ForceEDCCA, pDM_Odm->IGI_Base, pDM_Odm->TH_L2H_ini, pDM_Odm->TH_EDCCA_HL_diff, pDM_Odm->AdapEn_RSSI)); if (*pDM_Odm->pBandWidth == ODM_BW20M) /* CHANNEL_WIDTH_20 */ IGI_target = pDM_Odm->IGI_Base; else if (*pDM_Odm->pBandWidth == ODM_BW40M) IGI_target = pDM_Odm->IGI_Base + 2; - else if (*pDM_Odm->pBandWidth == ODM_BW80M) - IGI_target = pDM_Odm->IGI_Base + 2; else IGI_target = pDM_Odm->IGI_Base; pDM_Odm->IGI_target = (u8) IGI_target; @@ -284,19 +262,6 @@ void odm_Adaptivity(void *pDM_VOID, u8 IGI) ) odm_NHMBB(pDM_Odm); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_DIG, - ODM_DBG_LOUD, - ( - "BandWidth =%s, IGI_target = 0x%x, EDCCA_State =%d\n", - (*pDM_Odm->pBandWidth == ODM_BW80M) ? "80M" : - ((*pDM_Odm->pBandWidth == ODM_BW40M) ? "40M" : "20M"), - IGI_target, - EDCCA_State - ) - ); - if (EDCCA_State) { Diff = IGI_target-(s8)IGI; TH_L2H_dmc = pDM_Odm->TH_L2H_ini + Diff; @@ -314,8 +279,6 @@ void odm_Adaptivity(void *pDM_VOID, u8 IGI) TH_L2H_dmc = 0x7f; TH_H2L_dmc = 0x7f; } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("IGI = 0x%x, TH_L2H_dmc = %d, TH_H2L_dmc = %d\n", - IGI, TH_L2H_dmc, TH_H2L_dmc)); PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, (u8)TH_L2H_dmc); PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, (u8)TH_H2L_dmc); } @@ -326,18 +289,13 @@ void ODM_Write_DIG(void *pDM_VOID, u8 CurrentIGI) struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; if (pDM_DigTable->bStopDIG) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("Stop Writing IGI\n")); return; } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_TRACE, ("ODM_REG(IGI_A, pDM_Odm) = 0x%x, ODM_BIT(IGI, pDM_Odm) = 0x%x\n", - ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm))); - if (pDM_DigTable->CurIGValue != CurrentIGI) { /* 1 Check initial gain by upper bound */ if (!pDM_DigTable->bPSDInProgress) { if (CurrentIGI > pDM_DigTable->rx_gain_range_max) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_TRACE, ("CurrentIGI(0x%02x) is larger than upper bound !!\n", pDM_DigTable->rx_gain_range_max)); CurrentIGI = pDM_DigTable->rx_gain_range_max; } @@ -352,8 +310,6 @@ void ODM_Write_DIG(void *pDM_VOID, u8 CurrentIGI) pDM_DigTable->CurIGValue = CurrentIGI; } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_TRACE, ("CurrentIGI(0x%02x).\n", CurrentIGI)); - } void odm_PauseDIG( @@ -366,18 +322,10 @@ void odm_PauseDIG( struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; static bool bPaused; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_PauseDIG() =========>\n")); - if ( (pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY) && pDM_Odm->TxHangFlg == true ) { - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_DIG, - ODM_DBG_LOUD, - ("odm_PauseDIG(): Dynamic adjust threshold in progress !!\n") - ); return; } @@ -385,12 +333,6 @@ void odm_PauseDIG( !bPaused && (!(pDM_Odm->SupportAbility & ODM_BB_DIG) || !(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)) ){ - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_DIG, - ODM_DBG_LOUD, - ("odm_PauseDIG(): Return: SupportAbility ODM_BB_DIG or ODM_BB_FA_CNT is disabled\n") - ); return; } @@ -399,18 +341,15 @@ void odm_PauseDIG( case ODM_PAUSE_DIG: /* 2 Disable DIG */ ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_ABILITY, pDM_Odm->SupportAbility & (~ODM_BB_DIG)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_PauseDIG(): Pause DIG !!\n")); /* 2 Backup IGI value */ if (!bPaused) { pDM_DigTable->IGIBackup = pDM_DigTable->CurIGValue; bPaused = true; } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_PauseDIG(): Backup IGI = 0x%x\n", pDM_DigTable->IGIBackup)); /* 2 Write new IGI value */ ODM_Write_DIG(pDM_Odm, IGIValue); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_PauseDIG(): Write new IGI = 0x%x\n", IGIValue)); break; /* 1 Resume DIG */ @@ -419,16 +358,13 @@ void odm_PauseDIG( /* 2 Write backup IGI value */ ODM_Write_DIG(pDM_Odm, pDM_DigTable->IGIBackup); bPaused = false; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_PauseDIG(): Write original IGI = 0x%x\n", pDM_DigTable->IGIBackup)); /* 2 Enable DIG */ ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_ABILITY, pDM_Odm->SupportAbility | ODM_BB_DIG); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_PauseDIG(): Resume DIG !!\n")); } break; default: - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_PauseDIG(): Wrong type !!\n")); break; } } @@ -439,25 +375,21 @@ bool odm_DigAbort(void *pDM_VOID) /* SupportAbility */ if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Return: SupportAbility ODM_BB_FA_CNT is disabled\n")); return true; } /* SupportAbility */ if (!(pDM_Odm->SupportAbility & ODM_BB_DIG)) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Return: SupportAbility ODM_BB_DIG is disabled\n")); return true; } /* ScanInProcess */ if (*(pDM_Odm->pbScanInProcess)) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Return: In Scan Progress\n")); return true; } /* add by Neil Chen to avoid PSD is processing */ if (pDM_Odm->bDMInitialGainEnable == false) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Return: PSD is Processing\n")); return true; } @@ -523,8 +455,6 @@ void odm_DIG(void *pDM_VOID) if (odm_DigAbort(pDM_Odm)) return; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG() ===========================>\n\n")); - if (pDM_Odm->adaptivity_flag == true) Adap_IGI_Upper = pDM_Odm->Adaptivity_IGI_upper; @@ -540,15 +470,12 @@ void odm_DIG(void *pDM_VOID) dm_dig_min = DM_DIG_MIN_NIC; DIG_MaxOfMin = DM_DIG_MAX_AP; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Absolutely upper bound = 0x%x, lower bound = 0x%x\n", dm_dig_max, dm_dig_min)); - /* 1 Adjust boundary by RSSI */ if (pDM_Odm->bLinked && bPerformance) { /* 2 Modify DIG upper bound */ /* 4 Modify DIG upper bound for 92E, 8723A\B, 8821 & 8812 BT */ if (pDM_Odm->bBtLimitedDig == 1) { offset = 10; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Coex. case: Force upper bound to RSSI + %d !!!!!!\n", offset)); } else offset = 15; @@ -586,49 +513,9 @@ void odm_DIG(void *pDM_VOID) DIG_Dynamic_MIN = DIG_MaxOfMin; else DIG_Dynamic_MIN = (u8) pDM_DigTable->AntDiv_RSSI_max; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_ANT_DIV, - ODM_DBG_LOUD, - ( - "odm_DIG(): Antenna diversity case: Force lower bound to 0x%x !!!!!!\n", - DIG_Dynamic_MIN - ) - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_ANT_DIV, - ODM_DBG_LOUD, - ( - "odm_DIG(): Antenna diversity case: RSSI_max = 0x%x !!!!!!\n", - pDM_DigTable->AntDiv_RSSI_max - ) - ); } } } - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_DIG, - ODM_DBG_LOUD, - ( - "odm_DIG(): Adjust boundary by RSSI Upper bound = 0x%x, Lower bound = 0x%x\n", - pDM_DigTable->rx_gain_range_max, - DIG_Dynamic_MIN - ) - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_DIG, - ODM_DBG_LOUD, - ( - "odm_DIG(): Link status: bLinked = %d, RSSI = %d, bFirstConnect = %d, bFirsrDisConnect = %d\n\n", - pDM_Odm->bLinked, - pDM_Odm->RSSI_Min, - FirstConnect, - FirstDisConnect - ) - ); /* 1 Modify DIG lower bound, deal with abnormal case */ /* 2 Abnormal false alarm case */ @@ -645,47 +532,20 @@ void odm_DIG(void *pDM_VOID) pDM_Odm->bsta_state ) { pDM_DigTable->rx_gain_range_min = dm_dig_min; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_DIG, - ODM_DBG_LOUD, - ( - "odm_DIG(): Abnormal #beacon (%d) case in STA mode: Force lower bound to 0x%x !!!!!!\n\n", - pDM_Odm->PhyDbgInfo.NumQryBeaconPkt, - pDM_DigTable->rx_gain_range_min - ) - ); } } /* 2 Abnormal lower bound case */ if (pDM_DigTable->rx_gain_range_min > pDM_DigTable->rx_gain_range_max) { pDM_DigTable->rx_gain_range_min = pDM_DigTable->rx_gain_range_max; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_DIG, - ODM_DBG_LOUD, - ( - "odm_DIG(): Abnormal lower bound case: Force lower bound to 0x%x !!!!!!\n\n", - pDM_DigTable->rx_gain_range_min - ) - ); } /* 1 False alarm threshold decision */ odm_FAThresholdCheck(pDM_Odm, bDFSBand, bPerformance, RxTp, TxTp, dm_FA_thres); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): False alarm threshold = %d, %d, %d\n\n", dm_FA_thres[0], dm_FA_thres[1], dm_FA_thres[2])); /* 1 Adjust initial gain by false alarm */ if (pDM_Odm->bLinked && bPerformance) { - /* 2 After link */ - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_DIG, - ODM_DBG_LOUD, - ("odm_DIG(): Adjust IGI after link\n") - ); if (bFirstTpTarget || (FirstConnect && bPerformance)) { pDM_DigTable->LargeFAHit = 0; @@ -698,16 +558,6 @@ void odm_DIG(void *pDM_VOID) CurrentIGI = DIG_MaxOfMin; } - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_DIG, - ODM_DBG_LOUD, - ( - "odm_DIG(): First connect case: IGI does on-shot to 0x%x\n", - CurrentIGI - ) - ); - } else { if (pFalseAlmCnt->Cnt_all > dm_FA_thres[2]) CurrentIGI = CurrentIGI + 4; @@ -722,35 +572,12 @@ void odm_DIG(void *pDM_VOID) (pDM_Odm->bsta_state) ) { CurrentIGI = pDM_DigTable->rx_gain_range_min; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_DIG, - ODM_DBG_LOUD, - ( - "odm_DIG(): Abnormal #beacon (%d) case: IGI does one-shot to 0x%x\n", - pDM_Odm->PhyDbgInfo.NumQryBeaconPkt, - CurrentIGI - ) - ); } } } else { - /* 2 Before link */ - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_DIG, - ODM_DBG_LOUD, - ("odm_DIG(): Adjust IGI before link\n") - ); if (FirstDisConnect || bFirstCoverage) { CurrentIGI = dm_dig_min; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_DIG, - ODM_DBG_LOUD, - ("odm_DIG(): First disconnect case: IGI does on-shot to lower bound\n") - ); } else { if (pFalseAlmCnt->Cnt_all > dm_FA_thres[2]) CurrentIGI = CurrentIGI + 4; @@ -768,17 +595,6 @@ void odm_DIG(void *pDM_VOID) if (CurrentIGI > pDM_DigTable->rx_gain_range_max) CurrentIGI = pDM_DigTable->rx_gain_range_max; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_DIG, - ODM_DBG_LOUD, - ( - "odm_DIG(): CurIGValue = 0x%x, TotalFA = %d\n\n", - CurrentIGI, - pFalseAlmCnt->Cnt_all - ) - ); - /* 1 Force upper bound and lower bound for adaptivity */ if ( pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY && @@ -791,8 +607,6 @@ void odm_DIG(void *pDM_VOID) if (CurrentIGI < pDM_Odm->IGI_LowerBound) CurrentIGI = pDM_Odm->IGI_LowerBound; } - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Adaptivity case: Force upper bound to 0x%x !!!!!!\n", Adap_IGI_Upper)); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Adaptivity case: Force lower bound to 0x%x !!!!!!\n\n", pDM_Odm->IGI_LowerBound)); } @@ -831,13 +645,6 @@ void odm_DIGbyRSSI_LPS(void *pDM_VOID) CurrentIGI = CurrentIGI+RSSI_OFFSET_DIG; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_DIG, - ODM_DBG_LOUD, - ("odm_DIGbyRSSI_LPS() ==>\n") - ); - /* Using FW PS mode to make IGI */ /* Adjust by FA in LPS MODE */ if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2_LPS) @@ -862,26 +669,6 @@ void odm_DIGbyRSSI_LPS(void *pDM_VOID) else if (CurrentIGI < RSSI_Lower) CurrentIGI = RSSI_Lower; - - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_DIG, - ODM_DBG_LOUD, - ("odm_DIGbyRSSI_LPS(): pFalseAlmCnt->Cnt_all = %d\n", pFalseAlmCnt->Cnt_all) - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_DIG, - ODM_DBG_LOUD, - ("odm_DIGbyRSSI_LPS(): pDM_Odm->RSSI_Min = %d\n", pDM_Odm->RSSI_Min) - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_DIG, - ODM_DBG_LOUD, - ("odm_DIGbyRSSI_LPS(): CurrentIGI = 0x%x\n", CurrentIGI) - ); - ODM_Write_DIG(pDM_Odm, CurrentIGI); /* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */ } @@ -970,86 +757,6 @@ void odm_FalseAlarmCounterStatistics(void *pDM_VOID) FalseAlmCnt->Cnt_CCA_all = FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA; - - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_FA_CNT, - ODM_DBG_LOUD, - ("Enter odm_FalseAlarmCounterStatistics\n") - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_FA_CNT, - ODM_DBG_LOUD, - ( - "Cnt_Fast_Fsync =%d, Cnt_SB_Search_fail =%d\n", - FalseAlmCnt->Cnt_Fast_Fsync, - FalseAlmCnt->Cnt_SB_Search_fail - ) - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_FA_CNT, - ODM_DBG_LOUD, - ( - "Cnt_Parity_Fail =%d, Cnt_Rate_Illegal =%d\n", - FalseAlmCnt->Cnt_Parity_Fail, - FalseAlmCnt->Cnt_Rate_Illegal - ) - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_FA_CNT, - ODM_DBG_LOUD, - ( - "Cnt_Crc8_fail =%d, Cnt_Mcs_fail =%d\n", - FalseAlmCnt->Cnt_Crc8_fail, - FalseAlmCnt->Cnt_Mcs_fail - ) - ); - - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_FA_CNT, - ODM_DBG_LOUD, - ("Cnt_OFDM_CCA =%d\n", FalseAlmCnt->Cnt_OFDM_CCA) - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_FA_CNT, - ODM_DBG_LOUD, - ("Cnt_CCK_CCA =%d\n", FalseAlmCnt->Cnt_CCK_CCA) - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_FA_CNT, - ODM_DBG_LOUD, - ("Cnt_CCA_all =%d\n", FalseAlmCnt->Cnt_CCA_all) - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_FA_CNT, - ODM_DBG_LOUD, - ("Cnt_Ofdm_fail =%d\n", FalseAlmCnt->Cnt_Ofdm_fail) - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_FA_CNT, - ODM_DBG_LOUD, - ("Cnt_Cck_fail =%d\n", FalseAlmCnt->Cnt_Cck_fail) - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_FA_CNT, - ODM_DBG_LOUD, - ("Cnt_Ofdm_fail =%d\n", FalseAlmCnt->Cnt_Ofdm_fail) - ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_FA_CNT, - ODM_DBG_LOUD, - ("Total False Alarm =%d\n", FalseAlmCnt->Cnt_all) - ); } @@ -1084,8 +791,6 @@ u8 odm_ForbiddenIGICheck(void *pDM_VOID, u8 DIG_Dynamic_MIN, u8 CurrentIGI) u8 rx_gain_range_min = pDM_DigTable->rx_gain_range_min; if (pFalseAlmCnt->Cnt_all > 10000) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Abnormally false alarm case.\n")); - if (pDM_DigTable->LargeFAHit != 3) pDM_DigTable->LargeFAHit++; @@ -1102,22 +807,18 @@ u8 odm_ForbiddenIGICheck(void *pDM_VOID, u8 DIG_Dynamic_MIN, u8 CurrentIGI) else rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 2); pDM_DigTable->Recover_cnt = 1800; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Abnormally false alarm case: Recover_cnt = %d\n", pDM_DigTable->Recover_cnt)); } } else { if (pDM_DigTable->Recover_cnt != 0) { pDM_DigTable->Recover_cnt--; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Normal Case: Recover_cnt = %d\n", pDM_DigTable->Recover_cnt)); } else { if (pDM_DigTable->LargeFAHit < 3) { if ((pDM_DigTable->ForbiddenIGI - 2) < DIG_Dynamic_MIN) { /* DM_DIG_MIN) */ pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN; /* DM_DIG_MIN; */ rx_gain_range_min = DIG_Dynamic_MIN; /* DM_DIG_MIN; */ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Normal Case: At Lower Bound\n")); } else { pDM_DigTable->ForbiddenIGI -= 2; rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 2); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Normal Case: Approach Lower Bound\n")); } } else pDM_DigTable->LargeFAHit = 0; @@ -1143,25 +844,12 @@ void odm_CCKPacketDetectionThresh(void *pDM_VOID) !(pDM_Odm->SupportAbility & ODM_BB_CCK_PD) || !(pDM_Odm->SupportAbility & ODM_BB_FA_CNT) ) { - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_CCK_PD, - ODM_DBG_LOUD, - ("odm_CCKPacketDetectionThresh() return ==========\n") - ); return; } if (pDM_Odm->ExtLNA) return; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_CCK_PD, - ODM_DBG_LOUD, - ("odm_CCKPacketDetectionThresh() ==========>\n") - ); - if (pDM_Odm->bLinked) { if (pDM_Odm->RSSI_Min > 25) CurCCK_CCAThres = 0xcd; @@ -1181,16 +869,6 @@ void odm_CCKPacketDetectionThresh(void *pDM_VOID) } ODM_Write_CCK_CCA_Thres(pDM_Odm, CurCCK_CCAThres); - - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_CCK_PD, - ODM_DBG_LOUD, - ( - "odm_CCKPacketDetectionThresh() CurCCK_CCAThres = 0x%x\n", - CurCCK_CCAThres - ) - ); } void ODM_Write_CCK_CCA_Thres(void *pDM_VOID, u8 CurCCK_CCAThres) diff --git a/drivers/staging/rtl8723bs/hal/odm_EdcaTurboCheck.c b/drivers/staging/rtl8723bs/hal/odm_EdcaTurboCheck.c index 12b37c17ea0c..578d5712645c 100644 --- a/drivers/staging/rtl8723bs/hal/odm_EdcaTurboCheck.c +++ b/drivers/staging/rtl8723bs/hal/odm_EdcaTurboCheck.c @@ -37,19 +37,6 @@ void ODM_EdcaTurboInit(void *pDM_VOID) pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false; pDM_Odm->DM_EDCA_Table.bIsCurRDLState = false; Adapter->recvpriv.bIsAnyNonBEPkts = false; - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, - ("Original VO PARAM: 0x%x\n", - rtw_read32(pDM_Odm->Adapter, ODM_EDCA_VO_PARAM))); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, - ("Original VI PARAM: 0x%x\n", - rtw_read32(pDM_Odm->Adapter, ODM_EDCA_VI_PARAM))); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, - ("Original BE PARAM: 0x%x\n", - rtw_read32(pDM_Odm->Adapter, ODM_EDCA_BE_PARAM))); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, - ("Original BK PARAM: 0x%x\n", - rtw_read32(pDM_Odm->Adapter, ODM_EDCA_BK_PARAM))); } /* ODM_InitEdcaTurbo */ void odm_EdcaTurboCheck(void *pDM_VOID) @@ -60,15 +47,10 @@ void odm_EdcaTurboCheck(void *pDM_VOID) */ struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, - ("odm_EdcaTurboCheck ========================>\n")); - if (!(pDM_Odm->SupportAbility & ODM_MAC_EDCA_TURBO)) return; odm_EdcaTurboCheckCE(pDM_Odm); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, - ("<========================odm_EdcaTurboCheck\n")); } /* odm_CheckEdcaTurbo */ void odm_EdcaTurboCheckCE(void *pDM_VOID) @@ -142,12 +124,10 @@ void odm_EdcaTurboCheckCE(void *pDM_VOID) } else if ((iot_peer == HT_IOT_PEER_CISCO) && ((wirelessmode == ODM_WM_G) || (wirelessmode == (ODM_WM_B | ODM_WM_G)) || - (wirelessmode == ODM_WM_A) || (wirelessmode == ODM_WM_B))) { EDCA_BE_DL = edca_setting_DL_GMode[iot_peer]; } else if ((iot_peer == HT_IOT_PEER_AIRGO) && - ((wirelessmode == ODM_WM_G) || - (wirelessmode == ODM_WM_A))) { + (wirelessmode == ODM_WM_G)) { EDCA_BE_DL = 0xa630; } else if (iot_peer == HT_IOT_PEER_MARVELL) { EDCA_BE_DL = edca_setting_DL[iot_peer]; diff --git a/drivers/staging/rtl8723bs/hal/odm_HWConfig.c b/drivers/staging/rtl8723bs/hal/odm_HWConfig.c index 638c16f5c668..32f7eb952ca8 100644 --- a/drivers/staging/rtl8723bs/hal/odm_HWConfig.c +++ b/drivers/staging/rtl8723bs/hal/odm_HWConfig.c @@ -59,9 +59,6 @@ static u8 odm_EVMdbToPercentage(s8 Value) ret_val = Value; ret_val /= 2; - /* DbgPrint("Value =%d\n", Value); */ - /* ODM_RT_DISP(FRX, RX_PHY_SQ, ("EVMdbToPercentage92C Value =%d / %x\n", ret_val, ret_val)); */ - if (ret_val >= 0) ret_val = 0; if (ret_val <= -33) @@ -141,7 +138,6 @@ static void odm_RxPhyStatus92CSeries_Parsing( } - /* DbgPrint("cck SQ = %d\n", SQ); */ pPhyInfo->signal_quality = SQ; pPhyInfo->rx_mimo_signal_quality[ODM_RF_PATH_A] = SQ; pPhyInfo->rx_mimo_signal_quality[ODM_RF_PATH_B] = -1; @@ -168,7 +164,6 @@ static void odm_RxPhyStatus92CSeries_Parsing( /* Translate DBM to percentage. */ RSSI = odm_QueryRxPwrPercentage(rx_pwr[i]); total_rssi += RSSI; - /* RT_DISP(FRX, RX_PHY_SS, ("RF-%d RXPWR =%x RSSI =%d\n", i, rx_pwr[i], RSSI)); */ pPhyInfo->rx_mimo_signal_strength[i] = (u8) RSSI; @@ -183,10 +178,8 @@ static void odm_RxPhyStatus92CSeries_Parsing( rx_pwr_all = (((pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all) >> 1)&0x7f)-110; PWDB_ALL_BT = PWDB_ALL = odm_QueryRxPwrPercentage(rx_pwr_all); - /* RT_DISP(FRX, RX_PHY_SS, ("PWDB_ALL =%d\n", PWDB_ALL)); */ pPhyInfo->rx_pwd_ba11 = PWDB_ALL; - /* ODM_RT_TRACE(pDM_Odm, ODM_COMP_RSSI_MONITOR, ODM_DBG_LOUD, ("ODM OFDM RSSI =%d\n", pPhyInfo->rx_pwd_ba11)); */ pPhyInfo->bt_rx_rssi_percentage = PWDB_ALL_BT; pPhyInfo->rx_power = rx_pwr_all; pPhyInfo->recv_signal_power = rx_pwr_all; @@ -206,9 +199,6 @@ static void odm_RxPhyStatus92CSeries_Parsing( /* value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore. */ EVM = odm_EVMdbToPercentage((pPhyStaRpt->stream_rxevm[i])); /* dbm */ - /* RT_DISP(FRX, RX_PHY_SQ, ("RXRATE =%x RXEVM =%x EVM =%s%d\n", */ - /* GET_RX_STATUS_DESC_RX_MCS(pDesc), pDrvInfo->rxevm[i], "%", EVM)); */ - /* if (pPktinfo->bPacketMatchBSSID) */ { if (i == ODM_RF_PATH_A) /* Fill value in RFD, Get the first spatial stream only */ @@ -232,9 +222,6 @@ static void odm_RxPhyStatus92CSeries_Parsing( pPhyInfo->signal_strength = (u8)(odm_SignalScaleMapping(pDM_Odm, total_rssi /= rf_rx_num)); } } - - /* DbgPrint("isCCKrate = %d, pPhyInfo->rx_pwd_ba11 = %d, pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a = 0x%x\n", */ - /* isCCKrate, pPhyInfo->rx_pwd_ba11, pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a); */ } static void odm_Process_RSSIForDM( @@ -286,8 +273,6 @@ static void odm_Process_RSSIForDM( pDM_Odm->RSSI_A = pPhyInfo->rx_mimo_signal_strength[ODM_RF_PATH_A]; pDM_Odm->RSSI_B = 0; } else { - /* DbgPrint("pRfd->Status.rx_mimo_signal_strength[0] = %d, pRfd->Status.rx_mimo_signal_strength[1] = %d\n", */ - /* pRfd->Status.rx_mimo_signal_strength[0], pRfd->Status.rx_mimo_signal_strength[1]); */ pDM_Odm->RSSI_A = pPhyInfo->rx_mimo_signal_strength[ODM_RF_PATH_A]; pDM_Odm->RSSI_B = pPhyInfo->rx_mimo_signal_strength[ODM_RF_PATH_B]; @@ -377,11 +362,6 @@ static void odm_Process_RSSIForDM( pEntry->rssi_stat.UndecoratedSmoothedCCK = UndecoratedSmoothedCCK; pEntry->rssi_stat.UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM; pEntry->rssi_stat.UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB; - - /* DbgPrint("OFDM_pkt =%d, Weighting =%d\n", OFDM_pkt, Weighting); */ - /* DbgPrint("UndecoratedSmoothedOFDM =%d, UndecoratedSmoothedPWDB =%d, UndecoratedSmoothedCCK =%d\n", */ - /* UndecoratedSmoothedOFDM, UndecoratedSmoothedPWDB, UndecoratedSmoothedCCK); */ - } } @@ -427,12 +407,6 @@ enum hal_status ODM_ConfigRFWithHeaderFile( enum odm_rf_radio_path_e eRFPath ) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD, - ("===>ODM_ConfigRFWithHeaderFile (%s)\n", (pDM_Odm->bIsMPChip) ? "MPChip" : "TestChip")); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD, - ("pDM_Odm->SupportPlatform: 0x%X, pDM_Odm->SupportInterface: 0x%X, pDM_Odm->BoardType: 0x%X\n", - pDM_Odm->SupportPlatform, pDM_Odm->SupportInterface, pDM_Odm->BoardType)); - if (ConfigType == CONFIG_RF_RADIO) READ_AND_CONFIG(8723B, _RadioA); else if (ConfigType == CONFIG_RF_TXPWR_LMT) @@ -443,12 +417,6 @@ enum hal_status ODM_ConfigRFWithHeaderFile( enum hal_status ODM_ConfigRFWithTxPwrTrackHeaderFile(struct dm_odm_t *pDM_Odm) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD, - ("===>ODM_ConfigRFWithTxPwrTrackHeaderFile (%s)\n", (pDM_Odm->bIsMPChip) ? "MPChip" : "TestChip")); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD, - ("pDM_Odm->SupportPlatform: 0x%X, pDM_Odm->SupportInterface: 0x%X, pDM_Odm->BoardType: 0x%X\n", - pDM_Odm->SupportPlatform, pDM_Odm->SupportInterface, pDM_Odm->BoardType)); - if (pDM_Odm->SupportInterface == ODM_ITRF_SDIO) READ_AND_CONFIG(8723B, _TxPowerTrack_SDIO); @@ -459,12 +427,6 @@ enum hal_status ODM_ConfigBBWithHeaderFile( struct dm_odm_t *pDM_Odm, enum ODM_BB_Config_Type ConfigType ) { - ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD, - ("===>ODM_ConfigBBWithHeaderFile (%s)\n", (pDM_Odm->bIsMPChip) ? "MPChip" : "TestChip")); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD, - ("pDM_Odm->SupportPlatform: 0x%X, pDM_Odm->SupportInterface: 0x%X, pDM_Odm->BoardType: 0x%X\n", - pDM_Odm->SupportPlatform, pDM_Odm->SupportInterface, pDM_Odm->BoardType)); - if (ConfigType == CONFIG_BB_PHY_REG) READ_AND_CONFIG(8723B, _PHY_REG); else if (ConfigType == CONFIG_BB_AGC_TAB) diff --git a/drivers/staging/rtl8723bs/hal/odm_NoiseMonitor.c b/drivers/staging/rtl8723bs/hal/odm_NoiseMonitor.c index c3de123e2a48..ad169704f3e9 100644 --- a/drivers/staging/rtl8723bs/hal/odm_NoiseMonitor.c +++ b/drivers/staging/rtl8723bs/hal/odm_NoiseMonitor.c @@ -29,9 +29,8 @@ static s16 odm_InbandNoise_Monitor_NSeries( u8 max_rf_path = 0, rf_path; u8 reg_c50, reg_c58, valid_done = 0; struct noise_level noise_data; - u32 start = 0, func_start = 0, func_end = 0; + u32 start = 0; - func_start = jiffies; pDM_Odm->noise_level.noise_all = 0; if ((pDM_Odm->RFType == ODM_1T2R) || (pDM_Odm->RFType == ODM_2T2R)) @@ -39,8 +38,6 @@ static s16 odm_InbandNoise_Monitor_NSeries( else max_rf_path = 1; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_DebugControlInbandNoise_Nseries() ==>\n")); - memset(&noise_data, 0, sizeof(struct noise_level)); /* */ @@ -65,7 +62,6 @@ static s16 odm_InbandNoise_Monitor_NSeries( /* Read Noise Floor Report */ tmp4b = PHY_QueryBBReg(pDM_Odm->Adapter, 0x8f8, bMaskDWord); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("Noise Floor Report (0x8f8) = 0x%08x\n", tmp4b)); /* PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XAAGCCore1, bMaskByte0, TestInitialGain); */ /* if (max_rf_path == 2) */ @@ -77,17 +73,10 @@ static s16 odm_InbandNoise_Monitor_NSeries( noise_data.value[ODM_RF_PATH_A] = (u8)(tmp4b&0xff); noise_data.value[ODM_RF_PATH_B] = (u8)((tmp4b&0xff00)>>8); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("value_a = 0x%x(%d), value_b = 0x%x(%d)\n", - noise_data.value[ODM_RF_PATH_A], noise_data.value[ODM_RF_PATH_A], noise_data.value[ODM_RF_PATH_B], noise_data.value[ODM_RF_PATH_B])); - for (rf_path = ODM_RF_PATH_A; rf_path < max_rf_path; rf_path++) { noise_data.sval[rf_path] = (s8)noise_data.value[rf_path]; noise_data.sval[rf_path] /= 2; } - - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("sval_a = %d, sval_b = %d\n", - noise_data.sval[ODM_RF_PATH_A], noise_data.sval[ODM_RF_PATH_B])); /* mdelay(10); */ /* msleep(10); */ @@ -95,11 +84,8 @@ static s16 odm_InbandNoise_Monitor_NSeries( if ((noise_data.valid_cnt[rf_path] < ValidCnt) && (noise_data.sval[rf_path] < Valid_Max && noise_data.sval[rf_path] >= Valid_Min)) { noise_data.valid_cnt[rf_path]++; noise_data.sum[rf_path] += noise_data.sval[rf_path]; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("RF_Path:%d Valid sval = %d\n", rf_path, noise_data.sval[rf_path])); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("Sum of sval = %d,\n", noise_data.sum[rf_path])); if (noise_data.valid_cnt[rf_path] == ValidCnt) { valid_done++; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("After divided, RF_Path:%d , sum = %d\n", rf_path, noise_data.sum[rf_path])); } } @@ -120,43 +106,23 @@ static s16 odm_InbandNoise_Monitor_NSeries( } reg_c50 = (s32)PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XAAGCCore1, bMaskByte0); reg_c50 &= ~BIT7; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("0x%x = 0x%02x(%d)\n", rOFDM0_XAAGCCore1, reg_c50, reg_c50)); pDM_Odm->noise_level.noise[ODM_RF_PATH_A] = -110 + reg_c50 + noise_data.sum[ODM_RF_PATH_A]; pDM_Odm->noise_level.noise_all += pDM_Odm->noise_level.noise[ODM_RF_PATH_A]; if (max_rf_path == 2) { reg_c58 = (s32)PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XBAGCCore1, bMaskByte0); reg_c58 &= ~BIT7; - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("0x%x = 0x%02x(%d)\n", rOFDM0_XBAGCCore1, reg_c58, reg_c58)); pDM_Odm->noise_level.noise[ODM_RF_PATH_B] = -110 + reg_c58 + noise_data.sum[ODM_RF_PATH_B]; pDM_Odm->noise_level.noise_all += pDM_Odm->noise_level.noise[ODM_RF_PATH_B]; } pDM_Odm->noise_level.noise_all /= max_rf_path; - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_COMMON, - ODM_DBG_LOUD, - ( - "noise_a = %d, noise_b = %d\n", - pDM_Odm->noise_level.noise[ODM_RF_PATH_A], - pDM_Odm->noise_level.noise[ODM_RF_PATH_B] - ) - ); - /* */ /* Step 4. Recover the Dig */ /* */ if (bPauseDIG) odm_PauseDIG(pDM_Odm, ODM_RESUME_DIG, IGIValue); - func_end = jiffies_to_msecs(jiffies - func_start); - /* printk("%s noise_a = %d, noise_b = %d noise_all:%d (%d ms)\n", __func__, */ - /* pDM_Odm->noise_level.noise[ODM_RF_PATH_A], */ - /* pDM_Odm->noise_level.noise[ODM_RF_PATH_B], */ - /* pDM_Odm->noise_level.noise_all, func_end); */ - - ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_DebugControlInbandNoise_Nseries() <==\n")); return pDM_Odm->noise_level.noise_all; } diff --git a/drivers/staging/rtl8723bs/hal/odm_PathDiv.c b/drivers/staging/rtl8723bs/hal/odm_PathDiv.c deleted file mode 100644 index 92b708265d47..000000000000 --- a/drivers/staging/rtl8723bs/hal/odm_PathDiv.c +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ - -#include "odm_precomp.h" - -void odm_PathDiversityInit(void *pDM_VOID) -{ - struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; - - if (!(pDM_Odm->SupportAbility & ODM_BB_PATH_DIV)) - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_PATH_DIV, - ODM_DBG_LOUD, - ("Return: Not Support PathDiv\n") - ); -} - -void odm_PathDiversity(void *pDM_VOID) -{ - struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; - - if (!(pDM_Odm->SupportAbility & ODM_BB_PATH_DIV)) - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_PATH_DIV, - ODM_DBG_LOUD, - ("Return: Not Support PathDiv\n") - ); -} diff --git a/drivers/staging/rtl8723bs/hal/odm_PathDiv.h b/drivers/staging/rtl8723bs/hal/odm_PathDiv.h deleted file mode 100644 index 7a5bc00c3682..000000000000 --- a/drivers/staging/rtl8723bs/hal/odm_PathDiv.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ - -#ifndef __ODMPATHDIV_H__ -#define __ODMPATHDIV_H__ - -void -odm_PathDiversityInit( - void *pDM_VOID - ); - -void -odm_PathDiversity( - void *pDM_VOID - ); - - #endif /* ifndef __ODMPATHDIV_H__ */ diff --git a/drivers/staging/rtl8723bs/hal/odm_RTL8723B.c b/drivers/staging/rtl8723bs/hal/odm_RTL8723B.c index ecf0045fcad9..54518ea1be6b 100644 --- a/drivers/staging/rtl8723bs/hal/odm_RTL8723B.c +++ b/drivers/staging/rtl8723bs/hal/odm_RTL8723B.c @@ -29,7 +29,6 @@ s8 odm_CCKRSSI_8723B(u8 LNA_idx, u8 VGA_idx) break; default: /* rx_pwr_all = -53+(2*(31-VGA_idx)); */ - /* DbgPrint("wrong LNA index\n"); */ break; } diff --git a/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.c b/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.c index 63bf5ba3e0d5..a29bd9375023 100644 --- a/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.c +++ b/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.c @@ -38,17 +38,6 @@ void odm_ConfigRFReg_8723B( PHY_SetRFReg(pDM_Odm->Adapter, RF_PATH, RegAddr, bRFRegOffsetMask, Data); udelay(1); getvalue = PHY_QueryRFReg(pDM_Odm->Adapter, RF_PATH, Addr, bMaskDWord); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_TRACE, - ( - "===> ODM_ConfigRFWithHeaderFile: [B6] getvalue 0x%x, Data 0x%x, count %d\n", - getvalue, - Data, - count - ) - ); if (count > 5) break; } @@ -86,17 +75,6 @@ void odm_ConfigRFReg_8723B( getvalue = PHY_QueryRFReg( pDM_Odm->Adapter, RF_PATH, Addr, bMaskDWord ); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_TRACE, - ( - "===> ODM_ConfigRFWithHeaderFile: [B2] getvalue 0x%x, Data 0x%x, count %d\n", - getvalue, - Data, - count - ) - ); if (count > 5) break; @@ -118,32 +96,11 @@ void odm_ConfigRF_RadioA_8723B(struct dm_odm_t *pDM_Odm, u32 Addr, u32 Data) ODM_RF_PATH_A, Addr|maskforPhySet ); - - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_TRACE, - ( - "===> ODM_ConfigRFWithHeaderFile: [RadioA] %08X %08X\n", - Addr, - Data - ) - ); } void odm_ConfigMAC_8723B(struct dm_odm_t *pDM_Odm, u32 Addr, u8 Data) { rtw_write8(pDM_Odm->Adapter, Addr, Data); - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_TRACE, - ( - "===> ODM_ConfigMACWithHeaderFile: [MAC_REG] %08X %08X\n", - Addr, - Data - ) - ); } void odm_ConfigBB_AGC_8723B( @@ -156,22 +113,10 @@ void odm_ConfigBB_AGC_8723B( PHY_SetBBReg(pDM_Odm->Adapter, Addr, Bitmask, Data); /* Add 1us delay between BB/RF register setting. */ udelay(1); - - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_TRACE, - ( - "===> ODM_ConfigBBWithHeaderFile: [AGC_TAB] %08X %08X\n", - Addr, - Data - ) - ); } void odm_ConfigBB_PHY_REG_PG_8723B( struct dm_odm_t *pDM_Odm, - u32 Band, u32 RfPath, u32 TxNum, u32 Addr, @@ -182,19 +127,8 @@ void odm_ConfigBB_PHY_REG_PG_8723B( if (Addr == 0xfe || Addr == 0xffe) msleep(50); else { - PHY_StoreTxPowerByRate(pDM_Odm->Adapter, Band, RfPath, TxNum, Addr, Bitmask, Data); + PHY_StoreTxPowerByRate(pDM_Odm->Adapter, RfPath, TxNum, Addr, Bitmask, Data); } - ODM_RT_TRACE( - pDM_Odm, - ODM_COMP_INIT, - ODM_DBG_LOUD, - ( - "===> ODM_ConfigBBWithHeaderFile: [PHY_REG] %08X %08X %08X\n", - Addr, - Bitmask, - Data - ) - ); } void odm_ConfigBB_PHY_8723B( @@ -222,13 +156,11 @@ void odm_ConfigBB_PHY_8723B( /* Add 1us delay between BB/RF register setting. */ udelay(1); - ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_TRACE, ("===> ODM_ConfigBBWithHeaderFile: [PHY_REG] %08X %08X\n", Addr, Data)); } void odm_ConfigBB_TXPWR_LMT_8723B( struct dm_odm_t *pDM_Odm, u8 *Regulation, - u8 *Band, u8 *Bandwidth, u8 *RateSection, u8 *RfPath, @@ -239,7 +171,6 @@ void odm_ConfigBB_TXPWR_LMT_8723B( PHY_SetTxPowerLimit( pDM_Odm->Adapter, Regulation, - Band, Bandwidth, RateSection, RfPath, diff --git a/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.h b/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.h index b392d14c389d..bdd6fde49fc6 100644 --- a/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.h +++ b/drivers/staging/rtl8723bs/hal/odm_RegConfig8723B.h @@ -25,7 +25,6 @@ void odm_ConfigBB_AGC_8723B(struct dm_odm_t *pDM_Odm, ); void odm_ConfigBB_PHY_REG_PG_8723B(struct dm_odm_t *pDM_Odm, - u32 Band, u32 RfPath, u32 TxNum, u32 Addr, @@ -41,7 +40,6 @@ void odm_ConfigBB_PHY_8723B(struct dm_odm_t *pDM_Odm, void odm_ConfigBB_TXPWR_LMT_8723B(struct dm_odm_t *pDM_Odm, u8 *Regulation, - u8 *Band, u8 *Bandwidth, u8 *RateSection, u8 *RfPath, diff --git a/drivers/staging/rtl8723bs/hal/odm_debug.c b/drivers/staging/rtl8723bs/hal/odm_debug.c deleted file mode 100644 index b35451bcb437..000000000000 --- a/drivers/staging/rtl8723bs/hal/odm_debug.c +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ - -#include "odm_precomp.h" - -void ODM_InitDebugSetting(struct dm_odm_t *pDM_Odm) -{ - pDM_Odm->DebugLevel = ODM_DBG_LOUD; - - pDM_Odm->DebugComponents = -/* BB Functions */ -/* ODM_COMP_DIG | */ -/* ODM_COMP_RA_MASK | */ -/* ODM_COMP_DYNAMIC_TXPWR | */ -/* ODM_COMP_FA_CNT | */ -/* ODM_COMP_RSSI_MONITOR | */ -/* ODM_COMP_CCK_PD | */ -/* ODM_COMP_ANT_DIV | */ -/* ODM_COMP_PWR_SAVE | */ -/* ODM_COMP_PWR_TRAIN | */ -/* ODM_COMP_RATE_ADAPTIVE | */ -/* ODM_COMP_PATH_DIV | */ -/* ODM_COMP_DYNAMIC_PRICCA | */ -/* ODM_COMP_RXHP | */ -/* ODM_COMP_MP | */ -/* ODM_COMP_CFO_TRACKING | */ - -/* MAC Functions */ -/* ODM_COMP_EDCA_TURBO | */ -/* ODM_COMP_EARLY_MODE | */ -/* RF Functions */ -/* ODM_COMP_TX_PWR_TRACK | */ -/* ODM_COMP_RX_GAIN_TRACK | */ -/* ODM_COMP_CALIBRATION | */ -/* Common */ -/* ODM_COMP_COMMON | */ -/* ODM_COMP_INIT | */ -/* ODM_COMP_PSD | */ -0; -} diff --git a/drivers/staging/rtl8723bs/hal/odm_debug.h b/drivers/staging/rtl8723bs/hal/odm_debug.h deleted file mode 100644 index be0d4c49a747..000000000000 --- a/drivers/staging/rtl8723bs/hal/odm_debug.h +++ /dev/null @@ -1,165 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ - -#ifndef __ODM_DBG_H__ -#define __ODM_DBG_H__ - - -/* */ -/* Define the debug levels */ -/* */ -/* 1. DBG_TRACE and DBG_LOUD are used for normal cases. */ -/* So that, they can help SW engineer to developed or trace states changed */ -/* and also help HW enginner to trace every operation to and from HW, */ -/* e.g IO, Tx, Rx. */ -/* */ -/* 2. DBG_WARNNING and DBG_SERIOUS are used for unusual or error cases, */ -/* which help us to debug SW or HW. */ -/* */ -/* */ -/* */ -/* Never used in a call to ODM_RT_TRACE()! */ -/* */ -#define ODM_DBG_OFF 1 - -/* */ -/* Fatal bug. */ -/* For example, Tx/Rx/IO locked up, OS hangs, memory access violation, */ -/* resource allocation failed, unexpected HW behavior, HW BUG and so on. */ -/* */ -#define ODM_DBG_SERIOUS 2 - -/* */ -/* Abnormal, rare, or unexpected cases. */ -/* For example, */ -/* IRP/Packet/OID canceled, */ -/* device suprisely unremoved and so on. */ -/* */ -#define ODM_DBG_WARNING 3 - -/* */ -/* Normal case with useful information about current SW or HW state. */ -/* For example, Tx/Rx descriptor to fill, Tx/Rx descriptor completed status, */ -/* SW protocol state change, dynamic mechanism state change and so on. */ -/* */ -#define ODM_DBG_LOUD 4 - -/* */ -/* Normal case with detail execution flow or information. */ -/* */ -#define ODM_DBG_TRACE 5 - -/* */ -/* Define the tracing components */ -/* */ -/* */ -/* BB Functions */ -#define ODM_COMP_DIG BIT0 -#define ODM_COMP_RA_MASK BIT1 -#define ODM_COMP_DYNAMIC_TXPWR BIT2 -#define ODM_COMP_FA_CNT BIT3 -#define ODM_COMP_RSSI_MONITOR BIT4 -#define ODM_COMP_CCK_PD BIT5 -#define ODM_COMP_ANT_DIV BIT6 -#define ODM_COMP_PWR_SAVE BIT7 -#define ODM_COMP_PWR_TRAIN BIT8 -#define ODM_COMP_RATE_ADAPTIVE BIT9 -#define ODM_COMP_PATH_DIV BIT10 -#define ODM_COMP_PSD BIT11 -#define ODM_COMP_DYNAMIC_PRICCA BIT12 -#define ODM_COMP_RXHP BIT13 -#define ODM_COMP_MP BIT14 -#define ODM_COMP_CFO_TRACKING BIT15 -/* MAC Functions */ -#define ODM_COMP_EDCA_TURBO BIT16 -#define ODM_COMP_EARLY_MODE BIT17 -/* RF Functions */ -#define ODM_COMP_TX_PWR_TRACK BIT24 -#define ODM_COMP_RX_GAIN_TRACK BIT25 -#define ODM_COMP_CALIBRATION BIT26 -/* Common Functions */ -#define ODM_COMP_COMMON BIT30 -#define ODM_COMP_INIT BIT31 - -/*------------------------Export Marco Definition---------------------------*/ - #define DbgPrint printk - #define RT_PRINTK(fmt, args...)\ - DbgPrint("%s(): " fmt, __func__, ## args) - #define RT_DISP(dbgtype, dbgflag, printstr) - -#ifndef ASSERT - #define ASSERT(expr) -#endif - -#if DBG -#define ODM_RT_TRACE(pDM_Odm, comp, level, fmt)\ - do {\ - if (\ - (comp & pDM_Odm->DebugComponents) &&\ - (level <= pDM_Odm->DebugLevel ||\ - level == ODM_DBG_SERIOUS)\ - ) {\ - RT_PRINTK fmt;\ - } \ - } while (0) - -#define ODM_RT_TRACE_F(pDM_Odm, comp, level, fmt)\ - do {\ - if (\ - (comp & pDM_Odm->DebugComponents) &&\ - (level <= pDM_Odm->DebugLevel)\ - ) {\ - RT_PRINTK fmt;\ - } \ - } while (0) - -#define ODM_RT_ASSERT(pDM_Odm, expr, fmt)\ - do {\ - if (!expr) {\ - DbgPrint("Assertion failed! %s at ......\n", #expr);\ - DbgPrint(\ - " ......%s,%s, line =%d\n",\ - __FILE__,\ - __func__,\ - __LINE__\ - );\ - RT_PRINTK fmt;\ - ASSERT(false);\ - } \ - } while (0) -#define ODM_dbg_trace(str) { DbgPrint("%s:%s\n", __func__, str); } - -#define ODM_PRINT_ADDR(pDM_Odm, comp, level, title_str, ptr)\ - do {\ - if (\ - (comp & pDM_Odm->DebugComponents) &&\ - (level <= pDM_Odm->DebugLevel)\ - ) {\ - int __i;\ - u8 *__ptr = (u8 *)ptr;\ - DbgPrint("[ODM] ");\ - DbgPrint(title_str);\ - DbgPrint(" ");\ - for (__i = 0; __i < 6; __i++)\ - DbgPrint("%02X%s", __ptr[__i], (__i == 5) ? "" : "-");\ - DbgPrint("\n");\ - } \ - } while (0) -#else -#define ODM_RT_TRACE(pDM_Odm, comp, level, fmt) no_printk fmt -#define ODM_RT_TRACE_F(pDM_Odm, comp, level, fmt) no_printk fmt -#define ODM_RT_ASSERT(pDM_Odm, expr, fmt) no_printk fmt -#define ODM_dbg_enter() do {} while (0) -#define ODM_dbg_exit() do {} while (0) -#define ODM_dbg_trace(str) no_printk("%s", str) -#define ODM_PRINT_ADDR(pDM_Odm, comp, level, title_str, ptr) \ - no_printk("%s %p", title_str, ptr) -#endif - -void ODM_InitDebugSetting(struct dm_odm_t *pDM_Odm); - -#endif /* __ODM_DBG_H__ */ diff --git a/drivers/staging/rtl8723bs/hal/odm_precomp.h b/drivers/staging/rtl8723bs/hal/odm_precomp.h index d48d681472d5..5041c9535e9a 100644 --- a/drivers/staging/rtl8723bs/hal/odm_precomp.h +++ b/drivers/staging/rtl8723bs/hal/odm_precomp.h @@ -27,11 +27,9 @@ #include "odm.h" #include "odm_HWConfig.h" -#include "odm_debug.h" #include "odm_RegDefine11N.h" #include "odm_EdcaTurboCheck.h" #include "odm_DIG.h" -#include "odm_PathDiv.h" #include "odm_DynamicBBPowerSaving.h" #include "odm_DynamicTxPower.h" #include "odm_CfoTracking.h" diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c index 2451875ab3c0..2b7077bb52df 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c @@ -114,14 +114,13 @@ static void ConstructBeacon(struct adapter *padapter, u8 *pframe, u32 *pLength) struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); - u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; pwlanhdr = (struct ieee80211_hdr *)pframe; fctrl = &(pwlanhdr->frame_control); *(fctrl) = 0; - memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); + eth_broadcast_addr(pwlanhdr->addr1); memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN); @@ -309,9 +308,6 @@ static void rtl8723b_set_FwRsvdPage_cmd(struct adapter *padapter, struct rsvdpag SET_8723B_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocQosNull); SET_8723B_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocBTQosNull); - print_hex_dump_debug(DRIVER_PREFIX ": u1H2CRsvdPageParm:", DUMP_PREFIX_NONE, - 16, 1, u1H2CRsvdPageParm, H2C_RSVDPAGE_LOC_LEN, false); - FillH2CCmd8723B(padapter, H2C_8723B_RSVD_PAGE, H2C_RSVDPAGE_LOC_LEN, u1H2CRsvdPageParm); } @@ -329,9 +325,6 @@ void rtl8723b_set_FwMediaStatusRpt_cmd(struct adapter *padapter, u8 mstatus, u8 SET_8723B_H2CCMD_MSRRPT_PARM_MACID(u1H2CMediaStatusRptParm, macid); SET_8723B_H2CCMD_MSRRPT_PARM_MACID_END(u1H2CMediaStatusRptParm, macid_end); - print_hex_dump_debug(DRIVER_PREFIX ": u1H2CMediaStatusRptParm:", DUMP_PREFIX_NONE, - 16, 1, u1H2CMediaStatusRptParm, H2C_MEDIA_STATUS_RPT_LEN, false); - FillH2CCmd8723B(padapter, H2C_8723B_MEDIA_STATUS_RPT, H2C_MEDIA_STATUS_RPT_LEN, u1H2CMediaStatusRptParm); } @@ -348,9 +341,6 @@ void rtl8723b_set_FwMacIdConfig_cmd(struct adapter *padapter, u8 mac_id, u8 raid SET_8723B_H2CCMD_MACID_CFG_RATE_MASK2(u1H2CMacIdConfigParm, (u8)((mask & 0x00ff0000) >> 16)); SET_8723B_H2CCMD_MACID_CFG_RATE_MASK3(u1H2CMacIdConfigParm, (u8)((mask & 0xff000000) >> 24)); - print_hex_dump_debug(DRIVER_PREFIX ": u1H2CMacIdConfigParm:", DUMP_PREFIX_NONE, - 16, 1, u1H2CMacIdConfigParm, H2C_MACID_CFG_LEN, false); - FillH2CCmd8723B(padapter, H2C_8723B_MACID_CFG, H2C_MACID_CFG_LEN, u1H2CMacIdConfigParm); } @@ -365,9 +355,6 @@ void rtl8723b_set_rssi_cmd(struct adapter *padapter, u8 *param) SET_8723B_H2CCMD_RSSI_SETTING_RSSI(u1H2CRssiSettingParm, rssi); SET_8723B_H2CCMD_RSSI_SETTING_ULDL_STATE(u1H2CRssiSettingParm, uldl_state); - print_hex_dump_debug(DRIVER_PREFIX ": u1H2CRssiSettingParm:", DUMP_PREFIX_NONE, - 16, 1, u1H2CRssiSettingParm, H2C_RSSI_SETTING_LEN, false); - FillH2CCmd8723B(padapter, H2C_8723B_RSSI_SETTING, H2C_RSSI_SETTING_LEN, u1H2CRssiSettingParm); } @@ -465,9 +452,6 @@ void rtl8723b_set_FwPwrMode_cmd(struct adapter *padapter, u8 psmode) hal_btcoex_RecordPwrMode(padapter, u1H2CPwrModeParm, H2C_PWRMODE_LEN); - print_hex_dump_debug(DRIVER_PREFIX ": u1H2CPwrModeParm:", DUMP_PREFIX_NONE, - 16, 1, u1H2CPwrModeParm, H2C_PWRMODE_LEN, false); - FillH2CCmd8723B(padapter, H2C_8723B_SET_PWR_MODE, H2C_PWRMODE_LEN, u1H2CPwrModeParm); } @@ -485,9 +469,6 @@ void rtl8723b_set_FwPsTuneParam_cmd(struct adapter *padapter) SET_8723B_H2CCMD_PSTUNE_PARM_ADOPT(u1H2CPsTuneParm, 1); SET_8723B_H2CCMD_PSTUNE_PARM_DTIM_PERIOD(u1H2CPsTuneParm, dtim_period); - print_hex_dump_debug(DRIVER_PREFIX ": u1H2CPsTuneParm:", DUMP_PREFIX_NONE, - 16, 1, u1H2CPsTuneParm, H2C_PSTUNEPARAM_LEN, false); - FillH2CCmd8723B(padapter, H2C_8723B_PS_TUNING_PARA, H2C_PSTUNEPARAM_LEN, u1H2CPsTuneParm); } diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_dm.c b/drivers/staging/rtl8723bs/hal/rtl8723b_dm.c index 23be025ceb5b..5840a5241fde 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_dm.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_dm.c @@ -109,7 +109,6 @@ static void Update_ODM_ComInfo_8723b(struct adapter *Adapter) ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_CHNL, &(pHalData->CurrentChannel)); ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_NET_CLOSED, &(Adapter->net_closed)); ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_MP_MODE, &zero); - ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_BAND, &(pHalData->CurrentBandType)); ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_FORCED_IGI_LB, &(pHalData->u1ForcedIgiLb)); ODM_CmnInfoHook(pDM_Odm, ODM_CMNINFO_FORCED_RATE, &(pHalData->ForcedDataRate)); diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c index 082448557b53..059d3050acc6 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c @@ -122,7 +122,6 @@ static int _WriteFW(struct adapter *padapter, void *buffer, u32 size) u8 *bufferPtr = buffer; pageNums = size / MAX_DLFW_PAGE_SIZE; - /* RT_ASSERT((pageNums <= 4), ("Page numbers should not greater then 4\n")); */ remainSize = size % MAX_DLFW_PAGE_SIZE; for (page = 0; page < pageNums; page++) { @@ -1149,10 +1148,8 @@ static u16 hal_EfuseGetCurrentSize_BT(struct adapter *padapter, u8 bPseudoTest) retU2 = ((bank-1)*EFUSE_BT_REAL_BANK_CONTENT_LEN)+efuse_addr; if (bPseudoTest) { pEfuseHal->fakeBTEfuseUsedBytes = retU2; - /* RT_DISP(FEEPROM, EFUSE_PG, ("Hal_EfuseGetCurrentSize_BT92C(), already use %u bytes\n", pEfuseHal->fakeBTEfuseUsedBytes)); */ } else { pEfuseHal->BTEfuseUsedBytes = retU2; - /* RT_DISP(FEEPROM, EFUSE_PG, ("Hal_EfuseGetCurrentSize_BT92C(), already use %u bytes\n", pEfuseHal->BTEfuseUsedBytes)); */ } return retU2; @@ -2512,15 +2509,8 @@ u8 BWMapping_8723B(struct adapter *Adapter, struct pkt_attrib *pattrib) u8 BWSettingOfDesc = 0; struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); - if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_80) { - if (pattrib->bwmode == CHANNEL_WIDTH_80) - BWSettingOfDesc = 2; - else if (pattrib->bwmode == CHANNEL_WIDTH_40) - BWSettingOfDesc = 1; - else - BWSettingOfDesc = 0; - } else if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) { - if ((pattrib->bwmode == CHANNEL_WIDTH_40) || (pattrib->bwmode == CHANNEL_WIDTH_80)) + if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) { + if (pattrib->bwmode == CHANNEL_WIDTH_40) BWSettingOfDesc = 1; else BWSettingOfDesc = 0; @@ -2538,38 +2528,20 @@ u8 SCMapping_8723B(struct adapter *Adapter, struct pkt_attrib *pattrib) u8 SCSettingOfDesc = 0; struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); - if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_80) { - if (pattrib->bwmode == CHANNEL_WIDTH_80) { - SCSettingOfDesc = VHT_DATA_SC_DONOT_CARE; - } else if (pattrib->bwmode == CHANNEL_WIDTH_40) { - if (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) - SCSettingOfDesc = VHT_DATA_SC_40_LOWER_OF_80MHZ; - else if (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) - SCSettingOfDesc = VHT_DATA_SC_40_UPPER_OF_80MHZ; - } else { - if ((pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) && (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER)) - SCSettingOfDesc = VHT_DATA_SC_20_LOWEST_OF_80MHZ; - else if ((pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) && (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER)) - SCSettingOfDesc = VHT_DATA_SC_20_LOWER_OF_80MHZ; - else if ((pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) && (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER)) - SCSettingOfDesc = VHT_DATA_SC_20_UPPER_OF_80MHZ; - else if ((pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) && (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER)) - SCSettingOfDesc = VHT_DATA_SC_20_UPPERST_OF_80MHZ; - } - } else if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) { + if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) { if (pattrib->bwmode == CHANNEL_WIDTH_40) { - SCSettingOfDesc = VHT_DATA_SC_DONOT_CARE; + SCSettingOfDesc = HT_DATA_SC_DONOT_CARE; } else if (pattrib->bwmode == CHANNEL_WIDTH_20) { if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) { - SCSettingOfDesc = VHT_DATA_SC_20_UPPER_OF_80MHZ; + SCSettingOfDesc = HT_DATA_SC_20_UPPER_OF_40MHZ; } else if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) { - SCSettingOfDesc = VHT_DATA_SC_20_LOWER_OF_80MHZ; + SCSettingOfDesc = HT_DATA_SC_20_LOWER_OF_40MHZ; } else { - SCSettingOfDesc = VHT_DATA_SC_DONOT_CARE; + SCSettingOfDesc = HT_DATA_SC_DONOT_CARE; } } } else { - SCSettingOfDesc = VHT_DATA_SC_DONOT_CARE; + SCSettingOfDesc = HT_DATA_SC_DONOT_CARE; } return SCSettingOfDesc; @@ -3315,9 +3287,6 @@ void C2HPacketHandler_8723B(struct adapter *padapter, u8 *pbuffer, u16 length) C2hEvent.CmdLen = length-2; tmpBuf = pbuffer+2; - print_hex_dump_debug(DRIVER_PREFIX ": C2HPacketHandler_8723B(): Command Content:\n", - DUMP_PREFIX_NONE, 16, 1, tmpBuf, C2hEvent.CmdLen, false); - process_c2h_event(padapter, &C2hEvent, tmpBuf); /* c2h_handler_8723b(padapter,&C2hEvent); */ } @@ -3898,27 +3867,19 @@ u8 GetHalDefVar8723B(struct adapter *padapter, enum hal_def_variable variable, v { u8 mac_id = *(u8 *)pval; u32 cmd; - u32 ra_info1, ra_info2; - u32 rate_mask1, rate_mask2; - u8 curr_tx_rate, curr_tx_sgi, hight_rate, lowest_rate; cmd = 0x40000100 | mac_id; rtw_write32(padapter, REG_HMEBOX_DBG_2_8723B, cmd); msleep(10); - ra_info1 = rtw_read32(padapter, 0x2F0); - curr_tx_rate = ra_info1&0x7F; - curr_tx_sgi = (ra_info1>>7)&0x01; + rtw_read32(padapter, 0x2F0); // info 1 cmd = 0x40000400 | mac_id; rtw_write32(padapter, REG_HMEBOX_DBG_2_8723B, cmd); msleep(10); - ra_info1 = rtw_read32(padapter, 0x2F0); - ra_info2 = rtw_read32(padapter, 0x2F4); - rate_mask1 = rtw_read32(padapter, 0x2F8); - rate_mask2 = rtw_read32(padapter, 0x2FC); - hight_rate = ra_info2&0xFF; - lowest_rate = (ra_info2>>8) & 0xFF; - + rtw_read32(padapter, 0x2F0); // info 1 + rtw_read32(padapter, 0x2F4); // info 2 + rtw_read32(padapter, 0x2F8); // rate mask 1 + rtw_read32(padapter, 0x2FC); // rate mask 2 } break; diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c index f43abf9b0d22..6e524034f388 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c @@ -38,7 +38,7 @@ static u32 phy_CalculateBitShift(u32 BitMask) /** - * PHY_QueryBBReg - Read "specific bits" from BB register. + * PHY_QueryBBReg_8723B - Read "specific bits" from BB register. * @Adapter: * @RegAddr: The target address to be readback * @BitMask: The target bit position in the target address @@ -53,10 +53,6 @@ u32 PHY_QueryBBReg_8723B(struct adapter *Adapter, u32 RegAddr, u32 BitMask) { u32 OriginalValue, BitShift; -#if (DISABLE_BB_RF == 1) - return 0; -#endif - OriginalValue = rtw_read32(Adapter, RegAddr); BitShift = phy_CalculateBitShift(BitMask); @@ -66,7 +62,7 @@ u32 PHY_QueryBBReg_8723B(struct adapter *Adapter, u32 RegAddr, u32 BitMask) /** - * PHY_SetBBReg - Write "Specific bits" to BB register (page 8~). + * PHY_SetBBReg_8723B - Write "Specific bits" to BB register (page 8~). * @Adapter: * @RegAddr: The target address to be modified * @BitMask: The target bit position in the target address @@ -88,10 +84,6 @@ void PHY_SetBBReg_8723B( /* u16 BBWaitCounter = 0; */ u32 OriginalValue, BitShift; -#if (DISABLE_BB_RF == 1) - return; -#endif - if (BitMask != bMaskDWord) { /* if not "double word" write */ OriginalValue = rtw_read32(Adapter, RegAddr); BitShift = phy_CalculateBitShift(BitMask); @@ -231,10 +223,10 @@ static void phy_RFSerialWrite_8723B( /** - * PHY_QueryRFReg - Query "Specific bits" to RF register (page 8~). + * PHY_QueryRFReg_8723B - Query "Specific bits" to RF register (page 8~). * @Adapter: * @eRFPath: Radio path of A/B/C/D - * @RegAdd: The target address to be read + * @RegAddr: The target address to be read * @BitMask: The target bit position in the target address * to be read * @@ -252,10 +244,6 @@ u32 PHY_QueryRFReg_8723B( { u32 Original_Value, BitShift; -#if (DISABLE_BB_RF == 1) - return 0; -#endif - Original_Value = phy_RFSerialRead_8723B(Adapter, eRFPath, RegAddr); BitShift = phy_CalculateBitShift(BitMask); @@ -263,7 +251,7 @@ u32 PHY_QueryRFReg_8723B( } /** - * PHY_SetRFReg - Write "Specific bits" to RF register (page 8~). + * PHY_SetRFReg_8723B - Write "Specific bits" to RF register (page 8~). * @Adapter: * @eRFPath: Radio path of A/B/C/D * @RegAddr: The target address to be modified @@ -285,10 +273,6 @@ void PHY_SetRFReg_8723B( { u32 Original_Value, BitShift; -#if (DISABLE_BB_RF == 1) - return; -#endif - /* RF data is 12 bits only */ if (BitMask != bRFRegOffsetMask) { Original_Value = phy_RFSerialRead_8723B(Adapter, eRFPath, RegAddr); @@ -562,15 +546,13 @@ u8 PHY_GetTxPowerIndex( { struct hal_com_data *pHalData = GET_HAL_DATA(padapter); s8 txPower = 0, powerDiffByRate = 0, limit = 0; - bool bIn24G = false; - txPower = (s8) PHY_GetTxPowerIndexBase(padapter, RFPath, Rate, BandWidth, Channel, &bIn24G); - powerDiffByRate = PHY_GetTxPowerByRate(padapter, BAND_ON_2_4G, ODM_RF_PATH_A, RF_1TX, Rate); + txPower = (s8) PHY_GetTxPowerIndexBase(padapter, RFPath, Rate, BandWidth, Channel); + powerDiffByRate = PHY_GetTxPowerByRate(padapter, ODM_RF_PATH_A, RF_1TX, Rate); limit = phy_get_tx_pwr_lmt( padapter, padapter->registrypriv.RegPwrTblSel, - (u8)(!bIn24G), pHalData->CurrentChannelBW, RFPath, Rate, @@ -625,11 +607,6 @@ static void phy_SetRegBW_8723B( rtw_write16(Adapter, REG_TRXPTCL_CTL_8723B, (u2tmp & 0xFEFF)); /* BIT 7 = 1, BIT 8 = 0 */ break; - case CHANNEL_WIDTH_80: - u2tmp = RegRfMod_BW | BIT8; - rtw_write16(Adapter, REG_TRXPTCL_CTL_8723B, (u2tmp & 0xFF7F)); /* BIT 7 = 0, BIT 8 = 1 */ - break; - default: break; } @@ -640,37 +617,11 @@ static u8 phy_GetSecondaryChnl_8723B(struct adapter *Adapter) u8 SCSettingOf40 = 0, SCSettingOf20 = 0; struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); - if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_80) { - if (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) - SCSettingOf40 = VHT_DATA_SC_40_LOWER_OF_80MHZ; - else if (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) - SCSettingOf40 = VHT_DATA_SC_40_UPPER_OF_80MHZ; - - if ( - (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) && - (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) - ) - SCSettingOf20 = VHT_DATA_SC_20_LOWEST_OF_80MHZ; - else if ( - (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) && - (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) - ) - SCSettingOf20 = VHT_DATA_SC_20_LOWER_OF_80MHZ; - else if ( - (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) && - (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) - ) - SCSettingOf20 = VHT_DATA_SC_20_UPPER_OF_80MHZ; - else if ( - (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) && - (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) - ) - SCSettingOf20 = VHT_DATA_SC_20_UPPERST_OF_80MHZ; - } else if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) { + if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) { if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) - SCSettingOf20 = VHT_DATA_SC_20_UPPER_OF_80MHZ; + SCSettingOf20 = HT_DATA_SC_20_UPPER_OF_40MHZ; else if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) - SCSettingOf20 = VHT_DATA_SC_20_LOWER_OF_80MHZ; + SCSettingOf20 = HT_DATA_SC_20_LOWER_OF_40MHZ; } return (SCSettingOf40 << 4) | SCSettingOf20; diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c index 7c2680b6508c..ad803ffc0696 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c @@ -108,7 +108,7 @@ static void update_recvframe_phyinfo(union recv_frame *precvframe, !pattrib->icv_err && !pattrib->crc_err && ether_addr_equal(rx_bssid, my_bssid)); - rx_ra = get_ra(wlanhdr); + rx_ra = rtl8723bs_get_ra(wlanhdr); my_hwaddr = myid(&padapter->eeprompriv); pkt_info.to_self = pkt_info.bssid_match && ether_addr_equal(rx_ra, my_hwaddr); diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c index bd95e62fb053..a05d43b716ee 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c @@ -178,7 +178,7 @@ static s32 xmit_xmitframes(struct adapter *padapter, struct xmit_priv *pxmitpriv struct hw_xmit *hwxmits, *phwxmit; u8 idx, hwentry; struct tx_servq *ptxservq; - struct list_head *sta_plist, *sta_phead, *frame_plist, *frame_phead; + struct list_head *sta_plist, *sta_phead, *frame_plist, *frame_phead, *tmp; struct xmit_frame *pxmitframe; struct __queue *pframe_queue; struct xmit_buf *pxmitbuf; @@ -223,12 +223,11 @@ static s32 xmit_xmitframes(struct adapter *padapter, struct xmit_priv *pxmitpriv spin_lock_bh(&pxmitpriv->lock); sta_phead = get_list_head(phwxmit->sta_queue); - sta_plist = get_next(sta_phead); /* because stop_sta_xmit may delete sta_plist at any time */ /* so we should add lock here, or while loop can not exit */ - while (sta_phead != sta_plist) { - ptxservq = container_of(sta_plist, struct tx_servq, tx_pending); - sta_plist = get_next(sta_plist); + list_for_each_safe(sta_plist, tmp, sta_phead) { + ptxservq = list_entry(sta_plist, struct tx_servq, + tx_pending); pframe_queue = &ptxservq->sta_pending; diff --git a/drivers/staging/rtl8723bs/hal/sdio_halinit.c b/drivers/staging/rtl8723bs/hal/sdio_halinit.c index abd90026a8c7..a07a6dacec42 100644 --- a/drivers/staging/rtl8723bs/hal/sdio_halinit.c +++ b/drivers/staging/rtl8723bs/hal/sdio_halinit.c @@ -4,8 +4,6 @@ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. * ******************************************************************************/ -#define _SDIO_HALINIT_C_ - #include <drv_types.h> #include <rtw_debug.h> #include <rtl8723b_hal.h> @@ -228,7 +226,6 @@ static void _InitNormalChipOneOutEpPriority(struct adapter *Adapter) value = QUEUE_NORMAL; break; default: - /* RT_ASSERT(false, ("Shall not reach here!\n")); */ break; } @@ -262,7 +259,6 @@ static void _InitNormalChipTwoOutEpPriority(struct adapter *Adapter) valueLow = QUEUE_NORMAL; break; default: - /* RT_ASSERT(false, ("Shall not reach here!\n")); */ break; } @@ -327,7 +323,6 @@ static void _InitQueuePriority(struct adapter *Adapter) _InitNormalChipThreeOutEpPriority(Adapter); break; default: - /* RT_ASSERT(false, ("Shall not reach here!\n")); */ break; } @@ -517,9 +512,6 @@ static void _InitOperationMode(struct adapter *padapter) case WIRELESS_MODE_B: regBwOpMode = BW_OPMODE_20MHZ; break; - case WIRELESS_MODE_A: -/* RT_ASSERT(false, ("Error wireless a mode\n")); */ - break; case WIRELESS_MODE_G: regBwOpMode = BW_OPMODE_20MHZ; break; @@ -531,10 +523,6 @@ static void _InitOperationMode(struct adapter *padapter) /* CCK rate will be filtered out only when associated AP does not support it. */ regBwOpMode = BW_OPMODE_20MHZ; break; - case WIRELESS_MODE_N_5G: -/* RT_ASSERT(false, ("Error wireless mode")); */ - regBwOpMode = BW_OPMODE_5G; - break; default: /* for MacOSX compiler warning. */ break; @@ -567,11 +555,6 @@ static void _InitRFType(struct adapter *padapter) { struct hal_com_data *pHalData = GET_HAL_DATA(padapter); -#if DISABLE_BB_RF - pHalData->rf_chip = RF_PSEUDO_11N; - return; -#endif - pHalData->rf_chip = RF_6052; pHalData->rf_type = RF_1T1R; @@ -695,29 +678,23 @@ static u32 rtl8723bs_hal_init(struct adapter *padapter) /* <Roger_Notes> Current Channel will be updated again later. */ pHalData->CurrentChannel = 6; -#if (HAL_MAC_ENABLE == 1) ret = PHY_MACConfig8723B(padapter); if (ret != _SUCCESS) return ret; -#endif /* */ /* d. Initialize BB related configurations. */ /* */ -#if (HAL_BB_ENABLE == 1) ret = PHY_BBConfig8723B(padapter); if (ret != _SUCCESS) return ret; -#endif /* If RF is on, we need to init RF. Otherwise, skip the procedure. */ /* We need to follow SU method to change the RF cfg.txt. Default disable RF TX/RX mode. */ /* if (pHalData->eRFPowerState == eRfOn) */ { -#if (HAL_RF_ENABLE == 1) ret = PHY_RFConfig8723B(padapter); if (ret != _SUCCESS) return ret; -#endif } /* */ @@ -798,8 +775,6 @@ static u32 rtl8723bs_hal_init(struct adapter *padapter) rtl8723b_InitHalDm(padapter); - /* DbgPrint("pHalData->DefaultTxPwrDbm = %d\n", pHalData->DefaultTxPwrDbm); */ - /* */ /* Update current Tx FIFO page status. */ /* */ @@ -878,10 +853,9 @@ static void CardDisableRTL8723BSdio(struct adapter *padapter) { u8 u1bTmp; u8 bMacPwrCtrlOn; - u8 ret = _FAIL; /* Run LPS WL RFOFF flow */ - ret = HalPwrSeqCmdParsing(padapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, rtl8723B_enter_lps_flow); + HalPwrSeqCmdParsing(padapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, rtl8723B_enter_lps_flow); /* ==== Reset digital sequence ====== */ @@ -909,9 +883,8 @@ static void CardDisableRTL8723BSdio(struct adapter *padapter) /* ==== Reset digital sequence end ====== */ bMacPwrCtrlOn = false; /* Disable CMD53 R/W */ - ret = false; rtw_hal_set_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); - ret = HalPwrSeqCmdParsing(padapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, rtl8723B_card_disable_flow); + HalPwrSeqCmdParsing(padapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, rtl8723B_card_disable_flow); } static u32 rtl8723bs_hal_deinit(struct adapter *padapter) @@ -1046,11 +1019,7 @@ static void _ReadRFType(struct adapter *Adapter) { struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); -#if DISABLE_BB_RF - pHalData->rf_chip = RF_PSEUDO_11N; -#else pHalData->rf_chip = RF_6052; -#endif } diff --git a/drivers/staging/rtl8723bs/hal/sdio_ops.c b/drivers/staging/rtl8723bs/hal/sdio_ops.c index a31694525bc1..2dd251ce177e 100644 --- a/drivers/staging/rtl8723bs/hal/sdio_ops.c +++ b/drivers/staging/rtl8723bs/hal/sdio_ops.c @@ -4,8 +4,6 @@ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. * *******************************************************************************/ -#define _SDIO_OPS_C_ - #include <drv_types.h> #include <rtw_debug.h> #include <rtl8723b_hal.h> @@ -160,7 +158,7 @@ static u32 sdio_read32(struct intf_hdl *intfhdl, u32 addr) u32 ftaddr; u8 shift; u32 val; - s32 err; + s32 __maybe_unused err; __le32 le_tmp; adapter = intfhdl->padapter; @@ -348,11 +346,6 @@ static s32 sdio_writeN(struct intf_hdl *intfhdl, u32 addr, u32 cnt, u8 *buf) return err; } -static u8 sdio_f0_read8(struct intf_hdl *intfhdl, u32 addr) -{ - return sd_f0_read8(intfhdl, addr, NULL); -} - static void sdio_read_mem( struct intf_hdl *intfhdl, u32 addr, @@ -360,10 +353,7 @@ static void sdio_read_mem( u8 *rmem ) { - s32 err; - - err = sdio_readN(intfhdl, addr, cnt, rmem); - /* TODO: Report error is err not zero */ + sdio_readN(intfhdl, addr, cnt, rmem); } static void sdio_write_mem( @@ -486,8 +476,6 @@ void sdio_set_intf_ops(struct adapter *adapter, struct _io_ops *ops) ops->_writeN = &sdio_writeN; ops->_write_mem = &sdio_write_mem; ops->_write_port = &sdio_write_port; - - ops->_sd_f0_read8 = sdio_f0_read8; } /* diff --git a/drivers/staging/rtl8723bs/include/Hal8192CPhyReg.h b/drivers/staging/rtl8723bs/include/Hal8192CPhyReg.h index 4b3a7c051630..aad962548278 100644 --- a/drivers/staging/rtl8723bs/include/Hal8192CPhyReg.h +++ b/drivers/staging/rtl8723bs/include/Hal8192CPhyReg.h @@ -558,7 +558,6 @@ #define b3WireRFPowerDown 0x1 /* Useless now */ /* define bHWSISelect 0x8 */ -#define b5GPAPEPolarity 0x40000000 #define b2GPAPEPolarity 0x80000000 #define bRFSW_TxDefaultAnt 0x3 #define bRFSW_TxOptionAnt 0x30 @@ -577,7 +576,6 @@ #define bRFSI_ANTSW 0x100 #define bRFSI_ANTSWB 0x200 #define bRFSI_PAPE 0x400 -#define bRFSI_PAPE5G 0x800 #define bBandSelect 0x1 #define bHTSIG2_GI 0x80 #define bHTSIG2_Smoothing 0x01 diff --git a/drivers/staging/rtl8723bs/include/autoconf.h b/drivers/staging/rtl8723bs/include/autoconf.h deleted file mode 100644 index 944a7d2a1e53..000000000000 --- a/drivers/staging/rtl8723bs/include/autoconf.h +++ /dev/null @@ -1,50 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ - -/* - * Automatically generated C config: don't edit - */ - -/* - * Functions Config - */ - -#ifndef CONFIG_WIRELESS_EXT -#error CONFIG_WIRELESS_EXT needs to be enabled for this driver to work -#endif - -/* - * Auto Config Section - */ -#define LPS_RPWM_WAIT_MS 300 -#ifndef DISABLE_BB_RF -#define DISABLE_BB_RF 0 -#endif - -#if DISABLE_BB_RF - #define HAL_MAC_ENABLE 0 - #define HAL_BB_ENABLE 0 - #define HAL_RF_ENABLE 0 -#else - #define HAL_MAC_ENABLE 1 - #define HAL_BB_ENABLE 1 - #define HAL_RF_ENABLE 1 -#endif - -/* - * Platform dependent - */ -#define WAKEUP_GPIO_IDX 12 /* WIFI Chip Side */ - -/* - * Debug Related Config - */ - -#define DBG 0 /* for ODM & BTCOEX debug */ - -/* define DBG_XMIT_BUF */ -/* define DBG_XMIT_BUF_EXT */ diff --git a/drivers/staging/rtl8723bs/include/drv_conf.h b/drivers/staging/rtl8723bs/include/drv_conf.h deleted file mode 100644 index 9cef9ce589a1..000000000000 --- a/drivers/staging/rtl8723bs/include/drv_conf.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __DRV_CONF_H__ -#define __DRV_CONF_H__ -#include "autoconf.h" - -#define DYNAMIC_CAMID_ALLOC - -#ifndef CONFIG_RTW_HIQ_FILTER - #define CONFIG_RTW_HIQ_FILTER 1 -#endif - -//#include <rtl871x_byteorder.h> - -#endif // __DRV_CONF_H__ diff --git a/drivers/staging/rtl8723bs/include/drv_types.h b/drivers/staging/rtl8723bs/include/drv_types.h index 83d43e5726dd..895c41526164 100644 --- a/drivers/staging/rtl8723bs/include/drv_types.h +++ b/drivers/staging/rtl8723bs/include/drv_types.h @@ -15,7 +15,6 @@ #define __DRV_TYPES_H__ #include <linux/sched/signal.h> -#include <autoconf.h> #include <basic_types.h> #include <osdep_service.h> #include <rtw_byteorder.h> @@ -109,9 +108,11 @@ struct registry_priv { struct wlan_bssid_ex dev_network; u8 ht_enable; - /* 0: 20 MHz, 1: 40 MHz, 2: 80 MHz, 3: 160MHz */ - /* 2.4G use bit 0 ~ 3, 5G use bit 4 ~ 7 */ - /* 0x21 means enable 2.4G 40MHz & 5G 80MHz */ + /* + * 0: 20 MHz, 1: 40 MHz + * 2.4G use bit 0 ~ 3 + * 0x01 means enable 2.4G 40MHz + */ u8 bw_mode; u8 ampdu_enable;/* for tx */ u8 rx_stbc; @@ -170,9 +171,7 @@ struct registry_priv { u8 RegPowerBase; u8 RegPwrTblSel; s8 TxBBSwing_2G; - s8 TxBBSwing_5G; u8 AmplifierType_2G; - u8 AmplifierType_5G; u8 bEn_RFE; u8 RFE_Type; u8 check_fw_ps; @@ -503,7 +502,6 @@ static inline u8 *myid(struct eeprom_priv *peepriv) void rtw_indicate_wx_disassoc_event(struct adapter *padapter); void rtw_indicate_wx_assoc_event(struct adapter *padapter); -void rtw_indicate_wx_disassoc_event(struct adapter *padapter); void indicate_wx_scan_complete_event(struct adapter *padapter); int rtw_change_ifname(struct adapter *padapter, const char *ifname); diff --git a/drivers/staging/rtl8723bs/include/hal_btcoex.h b/drivers/staging/rtl8723bs/include/hal_btcoex.h index 3c03be210d87..849fb90b43b7 100644 --- a/drivers/staging/rtl8723bs/include/hal_btcoex.h +++ b/drivers/staging/rtl8723bs/include/hal_btcoex.h @@ -9,6 +9,8 @@ #include <drv_types.h> +#define LPS_RPWM_WAIT_MS 300 + /* Some variables can't get from outsrc BT-Coex, */ /* so we need to save here */ struct bt_coexist { @@ -53,7 +55,5 @@ u8 hal_btcoex_LpsVal(struct adapter *); u32 hal_btcoex_GetRaMask(struct adapter *); void hal_btcoex_RecordPwrMode(struct adapter *padapter, u8 *pCmdBuf, u8 cmdLen); void hal_btcoex_DisplayBtCoexInfo(struct adapter *, u8 *pbuf, u32 bufsize); -void hal_btcoex_SetDBG(struct adapter *, u32 *pDbgModule); -u32 hal_btcoex_GetDBG(struct adapter *, u8 *pStrBuf, u32 bufSize); #endif /* !__HAL_BTCOEX_H__ */ diff --git a/drivers/staging/rtl8723bs/include/hal_com.h b/drivers/staging/rtl8723bs/include/hal_com.h index 6bcc443d59fb..1bc332261b2a 100644 --- a/drivers/staging/rtl8723bs/include/hal_com.h +++ b/drivers/staging/rtl8723bs/include/hal_com.h @@ -69,46 +69,6 @@ #define DESC_RATEMCS29 0x29 #define DESC_RATEMCS30 0x2A #define DESC_RATEMCS31 0x2B -#define DESC_RATEVHTSS1MCS0 0x2C -#define DESC_RATEVHTSS1MCS1 0x2D -#define DESC_RATEVHTSS1MCS2 0x2E -#define DESC_RATEVHTSS1MCS3 0x2F -#define DESC_RATEVHTSS1MCS4 0x30 -#define DESC_RATEVHTSS1MCS5 0x31 -#define DESC_RATEVHTSS1MCS6 0x32 -#define DESC_RATEVHTSS1MCS7 0x33 -#define DESC_RATEVHTSS1MCS8 0x34 -#define DESC_RATEVHTSS1MCS9 0x35 -#define DESC_RATEVHTSS2MCS0 0x36 -#define DESC_RATEVHTSS2MCS1 0x37 -#define DESC_RATEVHTSS2MCS2 0x38 -#define DESC_RATEVHTSS2MCS3 0x39 -#define DESC_RATEVHTSS2MCS4 0x3A -#define DESC_RATEVHTSS2MCS5 0x3B -#define DESC_RATEVHTSS2MCS6 0x3C -#define DESC_RATEVHTSS2MCS7 0x3D -#define DESC_RATEVHTSS2MCS8 0x3E -#define DESC_RATEVHTSS2MCS9 0x3F -#define DESC_RATEVHTSS3MCS0 0x40 -#define DESC_RATEVHTSS3MCS1 0x41 -#define DESC_RATEVHTSS3MCS2 0x42 -#define DESC_RATEVHTSS3MCS3 0x43 -#define DESC_RATEVHTSS3MCS4 0x44 -#define DESC_RATEVHTSS3MCS5 0x45 -#define DESC_RATEVHTSS3MCS6 0x46 -#define DESC_RATEVHTSS3MCS7 0x47 -#define DESC_RATEVHTSS3MCS8 0x48 -#define DESC_RATEVHTSS3MCS9 0x49 -#define DESC_RATEVHTSS4MCS0 0x4A -#define DESC_RATEVHTSS4MCS1 0x4B -#define DESC_RATEVHTSS4MCS2 0x4C -#define DESC_RATEVHTSS4MCS3 0x4D -#define DESC_RATEVHTSS4MCS4 0x4E -#define DESC_RATEVHTSS4MCS5 0x4F -#define DESC_RATEVHTSS4MCS6 0x50 -#define DESC_RATEVHTSS4MCS7 0x51 -#define DESC_RATEVHTSS4MCS8 0x52 -#define DESC_RATEVHTSS4MCS9 0x53 #define HDATA_RATE(rate)\ (rate == DESC_RATE1M) ? "CCK_1M" : \ @@ -138,27 +98,7 @@ (rate == DESC_RATEMCS12) ? "MCS12" : \ (rate == DESC_RATEMCS13) ? "MCS13" : \ (rate == DESC_RATEMCS14) ? "MCS14" : \ -(rate == DESC_RATEMCS15) ? "MCS15" : \ -(rate == DESC_RATEVHTSS1MCS0) ? "VHTSS1MCS0" : \ -(rate == DESC_RATEVHTSS1MCS1) ? "VHTSS1MCS1" : \ -(rate == DESC_RATEVHTSS1MCS2) ? "VHTSS1MCS2" : \ -(rate == DESC_RATEVHTSS1MCS3) ? "VHTSS1MCS3" : \ -(rate == DESC_RATEVHTSS1MCS4) ? "VHTSS1MCS4" : \ -(rate == DESC_RATEVHTSS1MCS5) ? "VHTSS1MCS5" : \ -(rate == DESC_RATEVHTSS1MCS6) ? "VHTSS1MCS6" : \ -(rate == DESC_RATEVHTSS1MCS7) ? "VHTSS1MCS7" : \ -(rate == DESC_RATEVHTSS1MCS8) ? "VHTSS1MCS8" : \ -(rate == DESC_RATEVHTSS1MCS9) ? "VHTSS1MCS9" : \ -(rate == DESC_RATEVHTSS2MCS0) ? "VHTSS2MCS0" : \ -(rate == DESC_RATEVHTSS2MCS1) ? "VHTSS2MCS1" : \ -(rate == DESC_RATEVHTSS2MCS2) ? "VHTSS2MCS2" : \ -(rate == DESC_RATEVHTSS2MCS3) ? "VHTSS2MCS3" : \ -(rate == DESC_RATEVHTSS2MCS4) ? "VHTSS2MCS4" : \ -(rate == DESC_RATEVHTSS2MCS5) ? "VHTSS2MCS5" : \ -(rate == DESC_RATEVHTSS2MCS6) ? "VHTSS2MCS6" : \ -(rate == DESC_RATEVHTSS2MCS7) ? "VHTSS2MCS7" : \ -(rate == DESC_RATEVHTSS2MCS8) ? "VHTSS2MCS8" : \ -(rate == DESC_RATEVHTSS2MCS9) ? "VHTSS2MCS9" : "UNKNOWN" +(rate == DESC_RATEMCS15) ? "MCS15" : "UNKNOWN" enum{ diff --git a/drivers/staging/rtl8723bs/include/hal_com_phycfg.h b/drivers/staging/rtl8723bs/include/hal_com_phycfg.h index 73f6cadb5c79..c966d0e3e5ae 100644 --- a/drivers/staging/rtl8723bs/include/hal_com_phycfg.h +++ b/drivers/staging/rtl8723bs/include/hal_com_phycfg.h @@ -19,10 +19,6 @@ enum rate_section { HT_MCS8_MCS15, HT_MCS16_MCS23, HT_MCS24_MCS31, - VHT_1SSMCS0_1SSMCS9, - VHT_2SSMCS0_2SSMCS9, - VHT_3SSMCS0_3SSMCS9, - VHT_4SSMCS0_4SSMCS9, }; enum { @@ -70,153 +66,55 @@ struct bb_register_def { }; -u8 -PHY_GetTxPowerByRateBase( -struct adapter *Adapter, -u8 Band, -u8 RfPath, -u8 TxNum, -enum rate_section RateSection - ); - -u8 -PHY_GetRateSectionIndexOfTxPowerByRate( -struct adapter *padapter, -u32 RegAddr, -u32 BitMask - ); - -void -PHY_GetRateValuesOfTxPowerByRate( -struct adapter *padapter, -u32 RegAddr, -u32 BitMask, -u32 Value, -u8 *RateIndex, -s8 *PwrByRateVal, -u8 *RateNum - ); - -u8 -PHY_GetRateIndexOfTxPowerByRate( -u8 Rate - ); - -void -PHY_SetTxPowerIndexByRateSection( -struct adapter *padapter, -u8 RFPath, -u8 Channel, -u8 RateSection - ); - -s8 -PHY_GetTxPowerByRate( -struct adapter *padapter, -u8 Band, -u8 RFPath, -u8 TxNum, -u8 RateIndex - ); - -void -PHY_SetTxPowerByRate( -struct adapter *padapter, -u8 Band, -u8 RFPath, -u8 TxNum, -u8 Rate, -s8 Value - ); - -void -PHY_SetTxPowerLevelByPath( -struct adapter *Adapter, -u8 channel, -u8 path - ); - -void -PHY_SetTxPowerIndexByRateArray( -struct adapter *padapter, -u8 RFPath, -enum channel_width BandWidth, -u8 Channel, -u8 *Rates, -u8 RateArraySize - ); - -void -PHY_InitTxPowerByRate( -struct adapter *padapter - ); - -void -PHY_StoreTxPowerByRate( -struct adapter *padapter, -u32 Band, -u32 RfPath, -u32 TxNum, -u32 RegAddr, -u32 BitMask, -u32 Data - ); - -void -PHY_TxPowerByRateConfiguration( - struct adapter *padapter - ); - -u8 -PHY_GetTxPowerIndexBase( -struct adapter *padapter, -u8 RFPath, -u8 Rate, -enum channel_width BandWidth, -u8 Channel, - bool *bIn24G - ); +u8 PHY_GetTxPowerByRateBase(struct adapter *Adapter, u8 RfPath, u8 TxNum, + enum rate_section RateSection); + +u8 PHY_GetRateSectionIndexOfTxPowerByRate(struct adapter *padapter, u32 RegAddr, + u32 BitMask); + +void PHY_GetRateValuesOfTxPowerByRate(struct adapter *padapter, u32 RegAddr, + u32 BitMask, u32 Value, u8 *RateIndex, + s8 *PwrByRateVal, u8 *RateNum); + +u8 PHY_GetRateIndexOfTxPowerByRate(u8 Rate); + +void PHY_SetTxPowerIndexByRateSection(struct adapter *padapter, u8 RFPath, u8 Channel, + u8 RateSection); + +s8 PHY_GetTxPowerByRate(struct adapter *padapter, u8 RFPath, u8 TxNum, u8 RateIndex); + +void PHY_SetTxPowerByRate(struct adapter *padapter, u8 RFPath, u8 TxNum, u8 Rate, + s8 Value); + +void PHY_SetTxPowerLevelByPath(struct adapter *Adapter, u8 channel, u8 path); + +void PHY_SetTxPowerIndexByRateArray(struct adapter *padapter, u8 RFPath, + enum channel_width BandWidth, u8 Channel, + u8 *Rates, u8 RateArraySize); + +void PHY_InitTxPowerByRate(struct adapter *padapter); + +void PHY_StoreTxPowerByRate(struct adapter *padapter, u32 RfPath, u32 TxNum, + u32 RegAddr, u32 BitMask, u32 Data); + +void PHY_TxPowerByRateConfiguration(struct adapter *padapter); + +u8 PHY_GetTxPowerIndexBase(struct adapter *padapter, u8 RFPath, u8 Rate, + enum channel_width BandWidth, u8 Channel); s8 phy_get_tx_pwr_lmt(struct adapter *adapter, u32 RegPwrTblSel, - enum band_type Band, enum channel_width Bandwidth, -u8 RfPath, -u8 DataRate, -u8 Channel - ); - -void -PHY_SetTxPowerLimit( -struct adapter *Adapter, -u8 *Regulation, -u8 *Band, -u8 *Bandwidth, -u8 *RateSection, -u8 *RfPath, -u8 *Channel, -u8 *PowerLimit - ); - -void -PHY_ConvertTxPowerLimitToPowerIndex( -struct adapter *Adapter - ); - -void -PHY_InitTxPowerLimit( -struct adapter *Adapter - ); - -s8 -PHY_GetTxPowerTrackingOffset( - struct adapter *padapter, - u8 Rate, - u8 RFPath - ); - -void -Hal_ChannelPlanToRegulation( -struct adapter *Adapter, -u16 ChannelPlan - ); + enum channel_width Bandwidth, u8 RfPath, u8 DataRate, + u8 Channel); + +void PHY_SetTxPowerLimit(struct adapter *Adapter, u8 *Regulation, u8 *Bandwidth, + u8 *RateSection, u8 *RfPath, u8 *Channel, u8 *PowerLimit); + +void PHY_ConvertTxPowerLimitToPowerIndex(struct adapter *Adapter); + +void PHY_InitTxPowerLimit(struct adapter *Adapter); + +s8 PHY_GetTxPowerTrackingOffset(struct adapter *padapter, u8 Rate, u8 RFPath); + +void Hal_ChannelPlanToRegulation(struct adapter *Adapter, u16 ChannelPlan); #endif /* __HAL_COMMON_H__ */ diff --git a/drivers/staging/rtl8723bs/include/hal_com_reg.h b/drivers/staging/rtl8723bs/include/hal_com_reg.h index b14585cb0233..b2f179b48019 100644 --- a/drivers/staging/rtl8723bs/include/hal_com_reg.h +++ b/drivers/staging/rtl8723bs/include/hal_com_reg.h @@ -717,7 +717,6 @@ Default: 00b. /* BW_OPMODE bits (Offset 0x603, 8bit) */ /* */ #define BW_OPMODE_20MHZ BIT2 -#define BW_OPMODE_5G BIT1 /* */ /* CAM Config Setting (offset 0x680, 1 byte) */ diff --git a/drivers/staging/rtl8723bs/include/hal_data.h b/drivers/staging/rtl8723bs/include/hal_data.h index babcb03a7c23..3298fa8eb682 100644 --- a/drivers/staging/rtl8723bs/include/hal_data.h +++ b/drivers/staging/rtl8723bs/include/hal_data.h @@ -46,21 +46,16 @@ enum rt_ampdu_burst { RT_AMPDU_BURST_8723B = 7, }; -#define CHANNEL_MAX_NUMBER (14 + 24 + 21) /* 14 is the max channel number */ +#define CHANNEL_MAX_NUMBER (14) /* 14 is the max channel number */ #define CHANNEL_MAX_NUMBER_2G 14 -#define CHANNEL_MAX_NUMBER_5G 54 /* Please refer to "phy_GetChnlGroup8812A" and "Hal_ReadTxPowerInfo8812A" */ -#define CHANNEL_MAX_NUMBER_5G_80M 7 #define MAX_PG_GROUP 13 /* Tx Power Limit Table Size */ #define MAX_REGULATION_NUM 4 #define MAX_2_4G_BANDWIDTH_NUM 4 #define MAX_RATE_SECTION_NUM 10 -#define MAX_5G_BANDWIDTH_NUM 4 #define MAX_BASE_NUM_IN_PHY_REG_PG_2_4G 10 /* CCK:1, OFDM:1, HT:4, VHT:4 */ -#define MAX_BASE_NUM_IN_PHY_REG_PG_5G 9 /* OFDM:1, HT:4, VHT:4 */ - /* duplicate code, will move to ODM ######### */ /* define IQK_MAC_REG_NUM 4 */ @@ -182,8 +177,6 @@ struct hal_com_data { /* current WIFI_PHY values */ enum wireless_mode CurrentWirelessMode; enum channel_width CurrentChannelBW; - enum band_type CurrentBandType; /* 0:2.4G, 1:5G */ - enum band_type BandSet; u8 CurrentChannel; u8 CurrentCenterFrequencyIndex1; u8 nCur40MhzPrimeSC;/* Control channel sub-carrier */ @@ -236,16 +229,8 @@ struct hal_com_data { s8 OFDM_24G_Diff[MAX_RF_PATH][MAX_TX_COUNT]; s8 BW20_24G_Diff[MAX_RF_PATH][MAX_TX_COUNT]; s8 BW40_24G_Diff[MAX_RF_PATH][MAX_TX_COUNT]; - /* 3 [5G] */ - u8 Index5G_BW40_Base[MAX_RF_PATH][CHANNEL_MAX_NUMBER]; - u8 Index5G_BW80_Base[MAX_RF_PATH][CHANNEL_MAX_NUMBER_5G_80M]; - s8 OFDM_5G_Diff[MAX_RF_PATH][MAX_TX_COUNT]; - s8 BW20_5G_Diff[MAX_RF_PATH][MAX_TX_COUNT]; - s8 BW40_5G_Diff[MAX_RF_PATH][MAX_TX_COUNT]; - s8 BW80_5G_Diff[MAX_RF_PATH][MAX_TX_COUNT]; u8 Regulation2_4G; - u8 Regulation5G; u8 TxPwrInPercentage; @@ -253,15 +238,13 @@ struct hal_com_data { /* TX power by rate table at most 4RF path. */ /* The register is */ /* VHT TX power by rate off setArray = */ - /* Band:-2G&5G = 0 / 1 */ /* RF: at most 4*4 = ABCD = 0/1/2/3 */ /* CCK = 0 OFDM = 1/2 HT-MCS 0-15 =3/4/56 VHT =7/8/9/10/11 */ u8 TxPwrByRateTable; u8 TxPwrByRateBand; - s8 TxPwrByRateOffset[TX_PWR_BY_RATE_NUM_BAND] - [TX_PWR_BY_RATE_NUM_RF] - [TX_PWR_BY_RATE_NUM_RF] - [TX_PWR_BY_RATE_NUM_RATE]; + s8 TxPwrByRateOffset[TX_PWR_BY_RATE_NUM_RF] + [TX_PWR_BY_RATE_NUM_RF] + [TX_PWR_BY_RATE_NUM_RATE]; /* */ /* 2 Power Limit Table */ @@ -278,21 +261,10 @@ struct hal_com_data { [CHANNEL_MAX_NUMBER_2G] [MAX_RF_PATH_NUM]; - /* Power Limit Table for 5G */ - s8 TxPwrLimit_5G[MAX_REGULATION_NUM] - [MAX_5G_BANDWIDTH_NUM] - [MAX_RATE_SECTION_NUM] - [CHANNEL_MAX_NUMBER_5G] - [MAX_RF_PATH_NUM]; - - /* Store the original power by rate value of the base of each rate section of rf path A & B */ u8 TxPwrByRateBase2_4G[TX_PWR_BY_RATE_NUM_RF] [TX_PWR_BY_RATE_NUM_RF] [MAX_BASE_NUM_IN_PHY_REG_PG_2_4G]; - u8 TxPwrByRateBase5G[TX_PWR_BY_RATE_NUM_RF] - [TX_PWR_BY_RATE_NUM_RF] - [MAX_BASE_NUM_IN_PHY_REG_PG_5G]; /* For power group */ u8 PwrGroupHT20[RF_PATH_MAX_92C_88E][CHANNEL_MAX_NUMBER]; @@ -319,13 +291,9 @@ struct hal_com_data { u32 AntennaRxPath; /* Antenna path Rx */ u8 PAType_2G; - u8 PAType_5G; u8 LNAType_2G; - u8 LNAType_5G; u8 ExternalPA_2G; u8 ExternalLNA_2G; - u8 ExternalPA_5G; - u8 ExternalLNA_5G; u8 TypeGLNA; u8 TypeGPA; u8 TypeALNA; diff --git a/drivers/staging/rtl8723bs/include/hal_pg.h b/drivers/staging/rtl8723bs/include/hal_pg.h index 0b7a8adf5c74..2d8ccc9ddebb 100644 --- a/drivers/staging/rtl8723bs/include/hal_pg.h +++ b/drivers/staging/rtl8723bs/include/hal_pg.h @@ -16,10 +16,8 @@ /* For VHT series TX power by rate table. */ /* VHT TX power by rate off setArray = */ -/* Band:-2G&5G = 0 / 1 */ /* RF: at most 4*4 = ABCD = 0/1/2/3 */ /* CCK = 0 OFDM = 1/2 HT-MCS 0-15 =3/4/56 VHT =7/8/9/10/11 */ -#define TX_PWR_BY_RATE_NUM_BAND 2 #define TX_PWR_BY_RATE_NUM_RF 4 #define TX_PWR_BY_RATE_NUM_RATE 84 #define MAX_RF_PATH_NUM 2 diff --git a/drivers/staging/rtl8723bs/include/hal_phy.h b/drivers/staging/rtl8723bs/include/hal_phy.h index 521eb1c2efad..861aa71cd179 100644 --- a/drivers/staging/rtl8723bs/include/hal_phy.h +++ b/drivers/staging/rtl8723bs/include/hal_phy.h @@ -6,20 +6,6 @@ ******************************************************************************/ #ifndef __HAL_PHY_H__ #define __HAL_PHY_H__ - - -#if DISABLE_BB_RF -#define HAL_FW_ENABLE 0 -#define HAL_MAC_ENABLE 0 -#define HAL_BB_ENABLE 0 -#define HAL_RF_ENABLE 0 -#else /* FPGA_PHY and ASIC */ -#define HAL_FW_ENABLE 1 -#define HAL_MAC_ENABLE 1 -#define HAL_BB_ENABLE 1 -#define HAL_RF_ENABLE 1 -#endif - /* */ /* Antenna detection method, i.e., using single tone detection or RSSI reported from each antenna detected. */ /* Added by Roger, 2013.05.22. */ @@ -31,13 +17,6 @@ /*--------------------------Define Parameters-------------------------------*/ -enum band_type { - BAND_ON_2_4G = 0, - BAND_ON_5G, - BAND_ON_BOTH, - BANDMAX -}; - enum { RF_TYPE_MIN = 0, /* 0 */ RF_8225 = 1, /* 1 11b/g RF for verification only */ @@ -65,13 +44,10 @@ enum rf_path { enum wireless_mode { WIRELESS_MODE_UNKNOWN = 0x00, - WIRELESS_MODE_A = 0x01, WIRELESS_MODE_B = 0x02, WIRELESS_MODE_G = 0x04, WIRELESS_MODE_AUTO = 0x08, WIRELESS_MODE_N_24G = 0x10, - WIRELESS_MODE_N_5G = 0x20, - WIRELESS_MODE_AC_5G = 0x40, WIRELESS_MODE_AC_24G = 0x80, WIRELESS_MODE_AC_ONLY = 0x100, }; diff --git a/drivers/staging/rtl8723bs/include/ieee80211.h b/drivers/staging/rtl8723bs/include/ieee80211.h index 6540c7a22938..378c21595e05 100644 --- a/drivers/staging/rtl8723bs/include/ieee80211.h +++ b/drivers/staging/rtl8723bs/include/ieee80211.h @@ -60,7 +60,6 @@ enum { #define WLAN_STA_HT BIT(11) #define WLAN_STA_WPS BIT(12) #define WLAN_STA_MAYBE_WPS BIT(13) -#define WLAN_STA_VHT BIT(14) #define WLAN_STA_NONERP BIT(31) #define IEEE_CMD_SET_WPA_PARAM 1 @@ -135,8 +134,6 @@ enum { RATEID_IDX_BG = 6, RATEID_IDX_G = 7, RATEID_IDX_B = 8, - RATEID_IDX_VHT_2SS = 9, - RATEID_IDX_VHT_1SS = 10, }; enum network_type { @@ -144,33 +141,20 @@ enum network_type { /* Sub-Element */ WIRELESS_11B = BIT(0), /* tx: cck only , rx: cck only, hw: cck */ WIRELESS_11G = BIT(1), /* tx: ofdm only, rx: ofdm & cck, hw: cck & ofdm */ - WIRELESS_11A = BIT(2), /* tx: ofdm only, rx: ofdm only, hw: ofdm only */ WIRELESS_11_24N = BIT(3), /* tx: MCS only, rx: MCS & cck, hw: MCS & cck */ - WIRELESS_11_5N = BIT(4), /* tx: MCS only, rx: MCS & ofdm, hw: ofdm only */ WIRELESS_AUTO = BIT(5), - WIRELESS_11AC = BIT(6), /* Combination */ /* Type for current wireless mode */ WIRELESS_11BG = (WIRELESS_11B|WIRELESS_11G), /* tx: cck & ofdm, rx: cck & ofdm & MCS, hw: cck & ofdm */ WIRELESS_11G_24N = (WIRELESS_11G|WIRELESS_11_24N), /* tx: ofdm & MCS, rx: ofdm & cck & MCS, hw: cck & ofdm */ - WIRELESS_11A_5N = (WIRELESS_11A|WIRELESS_11_5N), /* tx: ofdm & MCS, rx: ofdm & MCS, hw: ofdm only */ WIRELESS_11B_24N = (WIRELESS_11B|WIRELESS_11_24N), /* tx: ofdm & cck & MCS, rx: ofdm & cck & MCS, hw: ofdm & cck */ WIRELESS_11BG_24N = (WIRELESS_11B|WIRELESS_11G|WIRELESS_11_24N), /* tx: ofdm & cck & MCS, rx: ofdm & cck & MCS, hw: ofdm & cck */ - WIRELESS_11_24AC = (WIRELESS_11G|WIRELESS_11AC), - WIRELESS_11_5AC = (WIRELESS_11A|WIRELESS_11AC), - - - /* Type for registry default wireless mode */ - WIRELESS_11AGN = (WIRELESS_11A|WIRELESS_11G|WIRELESS_11_24N|WIRELESS_11_5N), /* tx: ofdm & MCS, rx: ofdm & MCS, hw: ofdm only */ - WIRELESS_11ABGN = (WIRELESS_11A|WIRELESS_11B|WIRELESS_11G|WIRELESS_11_24N|WIRELESS_11_5N), - WIRELESS_MODE_24G = (WIRELESS_11B|WIRELESS_11G|WIRELESS_11_24N|WIRELESS_11AC), - WIRELESS_MODE_MAX = (WIRELESS_11A|WIRELESS_11B|WIRELESS_11G|WIRELESS_11_24N|WIRELESS_11_5N|WIRELESS_11AC), }; #define SUPPORTED_24G_NETTYPE_MSK (WIRELESS_11B | WIRELESS_11G | WIRELESS_11_24N) -#define IsLegacyOnly(NetType) ((NetType) == ((NetType) & (WIRELESS_11BG|WIRELESS_11A))) +#define IsLegacyOnly(NetType) ((NetType) == ((NetType) & (WIRELESS_11BG))) #define IsSupported24G(NetType) ((NetType) & SUPPORTED_24G_NETTYPE_MSK ? true : false) @@ -182,11 +166,8 @@ enum network_type { #define IsSupportedRxHT(NetType) IsEnableHWOFDM(NetType) #define IsSupportedTxCCK(NetType) (((NetType) & (WIRELESS_11B)) ? true : false) -#define IsSupportedTxOFDM(NetType) (((NetType) & (WIRELESS_11G|WIRELESS_11A)) ? true : false) -#define IsSupportedHT(NetType) (((NetType) & (WIRELESS_11_24N|WIRELESS_11_5N)) ? true : false) - -#define IsSupportedVHT(NetType) (((NetType) & (WIRELESS_11AC)) ? true : false) - +#define IsSupportedTxOFDM(NetType) (((NetType) & (WIRELESS_11G) ? true : false) +#define IsSupportedHT(NetType) (((NetType) & (WIRELESS_11_24N)) ? true : false) struct ieee_param { u32 cmd; @@ -440,51 +421,10 @@ enum { MGN_MCS29, MGN_MCS30, MGN_MCS31, - MGN_VHT1SS_MCS0, - MGN_VHT1SS_MCS1, - MGN_VHT1SS_MCS2, - MGN_VHT1SS_MCS3, - MGN_VHT1SS_MCS4, - MGN_VHT1SS_MCS5, - MGN_VHT1SS_MCS6, - MGN_VHT1SS_MCS7, - MGN_VHT1SS_MCS8, - MGN_VHT1SS_MCS9, - MGN_VHT2SS_MCS0, - MGN_VHT2SS_MCS1, - MGN_VHT2SS_MCS2, - MGN_VHT2SS_MCS3, - MGN_VHT2SS_MCS4, - MGN_VHT2SS_MCS5, - MGN_VHT2SS_MCS6, - MGN_VHT2SS_MCS7, - MGN_VHT2SS_MCS8, - MGN_VHT2SS_MCS9, - MGN_VHT3SS_MCS0, - MGN_VHT3SS_MCS1, - MGN_VHT3SS_MCS2, - MGN_VHT3SS_MCS3, - MGN_VHT3SS_MCS4, - MGN_VHT3SS_MCS5, - MGN_VHT3SS_MCS6, - MGN_VHT3SS_MCS7, - MGN_VHT3SS_MCS8, - MGN_VHT3SS_MCS9, - MGN_VHT4SS_MCS0, - MGN_VHT4SS_MCS1, - MGN_VHT4SS_MCS2, - MGN_VHT4SS_MCS3, - MGN_VHT4SS_MCS4, - MGN_VHT4SS_MCS5, - MGN_VHT4SS_MCS6, - MGN_VHT4SS_MCS7, - MGN_VHT4SS_MCS8, - MGN_VHT4SS_MCS9, MGN_UNKNOWN }; #define IS_HT_RATE(_rate) (_rate >= MGN_MCS0 && _rate <= MGN_MCS31) -#define IS_VHT_RATE(_rate) (_rate >= MGN_VHT1SS_MCS0 && _rate <= MGN_VHT4SS_MCS9) #define IS_CCK_RATE(_rate) (MGN_1M == _rate || _rate == MGN_2M || _rate == MGN_5_5M || _rate == MGN_11M) #define IS_OFDM_RATE(_rate) (MGN_6M <= _rate && _rate <= MGN_54M && _rate != MGN_11M) @@ -641,7 +581,6 @@ enum { RTW_WLAN_CATEGORY_TDLS = 12, RTW_WLAN_CATEGORY_SELF_PROTECTED = 15, /* add for CONFIG_IEEE80211W, none 11w also can use */ RTW_WLAN_CATEGORY_WMM = 17, - RTW_WLAN_CATEGORY_VHT = 21, RTW_WLAN_CATEGORY_P2P = 0x7f,/* P2P action frames */ }; diff --git a/drivers/staging/rtl8723bs/include/osdep_intf.h b/drivers/staging/rtl8723bs/include/osdep_intf.h index 48c90f00cc2e..111e0179712a 100644 --- a/drivers/staging/rtl8723bs/include/osdep_intf.h +++ b/drivers/staging/rtl8723bs/include/osdep_intf.h @@ -66,7 +66,7 @@ void rtw_ips_pwr_down(struct adapter *padapter); int rtw_drv_register_netdev(struct adapter *padapter); void rtw_ndev_destructor(struct net_device *ndev); -int rtw_suspend_common(struct adapter *padapter); +void rtw_suspend_common(struct adapter *padapter); int rtw_resume_common(struct adapter *padapter); int netdev_open(struct net_device *pnetdev); diff --git a/drivers/staging/rtl8723bs/include/rtl8723b_spec.h b/drivers/staging/rtl8723bs/include/rtl8723b_spec.h index 999555476ebc..6816040a6aff 100644 --- a/drivers/staging/rtl8723bs/include/rtl8723b_spec.h +++ b/drivers/staging/rtl8723bs/include/rtl8723b_spec.h @@ -7,8 +7,6 @@ #ifndef __RTL8723B_SPEC_H__ #define __RTL8723B_SPEC_H__ -#include <autoconf.h> - #define HAL_NAV_UPPER_UNIT_8723B 128 /* micro-second */ /* */ diff --git a/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h b/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h index 56bdc14af47d..9dd329a5208a 100644 --- a/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h +++ b/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h @@ -402,27 +402,6 @@ struct txdesc_8723b { #define DESC8723B_RATEMCS13 0x19 #define DESC8723B_RATEMCS14 0x1a #define DESC8723B_RATEMCS15 0x1b -#define DESC8723B_RATEVHTSS1MCS0 0x2c -#define DESC8723B_RATEVHTSS1MCS1 0x2d -#define DESC8723B_RATEVHTSS1MCS2 0x2e -#define DESC8723B_RATEVHTSS1MCS3 0x2f -#define DESC8723B_RATEVHTSS1MCS4 0x30 -#define DESC8723B_RATEVHTSS1MCS5 0x31 -#define DESC8723B_RATEVHTSS1MCS6 0x32 -#define DESC8723B_RATEVHTSS1MCS7 0x33 -#define DESC8723B_RATEVHTSS1MCS8 0x34 -#define DESC8723B_RATEVHTSS1MCS9 0x35 -#define DESC8723B_RATEVHTSS2MCS0 0x36 -#define DESC8723B_RATEVHTSS2MCS1 0x37 -#define DESC8723B_RATEVHTSS2MCS2 0x38 -#define DESC8723B_RATEVHTSS2MCS3 0x39 -#define DESC8723B_RATEVHTSS2MCS4 0x3a -#define DESC8723B_RATEVHTSS2MCS5 0x3b -#define DESC8723B_RATEVHTSS2MCS6 0x3c -#define DESC8723B_RATEVHTSS2MCS7 0x3d -#define DESC8723B_RATEVHTSS2MCS8 0x3e -#define DESC8723B_RATEVHTSS2MCS9 0x3f - #define RX_HAL_IS_CCK_RATE_8723B(pDesc)\ (GET_RX_STATUS_DESC_RX_RATE_8723B(pDesc) == DESC8723B_RATE1M ||\ diff --git a/drivers/staging/rtl8723bs/include/rtw_ap.h b/drivers/staging/rtl8723bs/include/rtw_ap.h index 4a1ed9eff83a..7a735e691399 100644 --- a/drivers/staging/rtl8723bs/include/rtw_ap.h +++ b/drivers/staging/rtl8723bs/include/rtw_ap.h @@ -14,7 +14,7 @@ void update_beacon(struct adapter *padapter, u8 ie_id, u8 *oui, u8 tx); void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level); void expire_timeout_chk(struct adapter *padapter); void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta); -void start_bss_network(struct adapter *padapter, u8 *pbuf); +void start_bss_network(struct adapter *padapter); int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len); void rtw_ap_restore_network(struct adapter *padapter); void rtw_set_macaddr_acl(struct adapter *padapter, int mode); diff --git a/drivers/staging/rtl8723bs/include/rtw_debug.h b/drivers/staging/rtl8723bs/include/rtw_debug.h index 23f4cb4711d4..7f96ff66915f 100644 --- a/drivers/staging/rtl8723bs/include/rtw_debug.h +++ b/drivers/staging/rtl8723bs/include/rtw_debug.h @@ -7,172 +7,8 @@ #ifndef __RTW_DEBUG_H__ #define __RTW_DEBUG_H__ -#include <linux/trace_seq.h> - -#define _drv_always_ 1 -#define _drv_emerg_ 2 -#define _drv_alert_ 3 -#define _drv_crit_ 4 -#define _drv_err_ 5 -#define _drv_warning_ 6 -#define _drv_notice_ 7 -#define _drv_info_ 8 -#define _drv_dump_ 9 -#define _drv_debug_ 10 - - -#define _module_rtl871x_xmit_c_ BIT(0) -#define _module_xmit_osdep_c_ BIT(1) -#define _module_rtl871x_recv_c_ BIT(2) -#define _module_recv_osdep_c_ BIT(3) -#define _module_rtl871x_mlme_c_ BIT(4) -#define _module_mlme_osdep_c_ BIT(5) -#define _module_rtl871x_sta_mgt_c_ BIT(6) -#define _module_rtl871x_cmd_c_ BIT(7) -#define _module_cmd_osdep_c_ BIT(8) -#define _module_rtl871x_io_c_ BIT(9) -#define _module_io_osdep_c_ BIT(10) -#define _module_os_intfs_c_ BIT(11) -#define _module_rtl871x_security_c_ BIT(12) -#define _module_rtl871x_eeprom_c_ BIT(13) -#define _module_hal_init_c_ BIT(14) -#define _module_hci_hal_init_c_ BIT(15) -#define _module_rtl871x_ioctl_c_ BIT(16) -#define _module_rtl871x_ioctl_set_c_ BIT(17) -#define _module_rtl871x_ioctl_query_c_ BIT(18) -#define _module_rtl871x_pwrctrl_c_ BIT(19) -#define _module_hci_intfs_c_ BIT(20) -#define _module_hci_ops_c_ BIT(21) -#define _module_osdep_service_c_ BIT(22) -#define _module_mp_ BIT(23) -#define _module_hci_ops_os_c_ BIT(24) -#define _module_rtl871x_ioctl_os_c BIT(25) -#define _module_rtl8712_cmd_c_ BIT(26) -/* define _module_efuse_ BIT(27) */ -#define _module_rtl8192c_xmit_c_ BIT(28) -#define _module_hal_xmit_c_ BIT(28) -#define _module_efuse_ BIT(29) -#define _module_rtl8712_recv_c_ BIT(30) -#define _module_rtl8712_led_c_ BIT(31) - -#undef _MODULE_DEFINE_ - -#if defined _RTW_XMIT_C_ - #define _MODULE_DEFINE_ _module_rtl871x_xmit_c_ -#elif defined _XMIT_OSDEP_C_ - #define _MODULE_DEFINE_ _module_xmit_osdep_c_ -#elif defined _RTW_RECV_C_ - #define _MODULE_DEFINE_ _module_rtl871x_recv_c_ -#elif defined _RECV_OSDEP_C_ - #define _MODULE_DEFINE_ _module_recv_osdep_c_ -#elif defined _RTW_MLME_C_ - #define _MODULE_DEFINE_ _module_rtl871x_mlme_c_ -#elif defined _MLME_OSDEP_C_ - #define _MODULE_DEFINE_ _module_mlme_osdep_c_ -#elif defined _RTW_MLME_EXT_C_ - #define _MODULE_DEFINE_ 1 -#elif defined _RTW_STA_MGT_C_ - #define _MODULE_DEFINE_ _module_rtl871x_sta_mgt_c_ -#elif defined _RTW_CMD_C_ - #define _MODULE_DEFINE_ _module_rtl871x_cmd_c_ -#elif defined _CMD_OSDEP_C_ - #define _MODULE_DEFINE_ _module_cmd_osdep_c_ -#elif defined _RTW_IO_C_ - #define _MODULE_DEFINE_ _module_rtl871x_io_c_ -#elif defined _IO_OSDEP_C_ - #define _MODULE_DEFINE_ _module_io_osdep_c_ -#elif defined _OS_INTFS_C_ - #define _MODULE_DEFINE_ _module_os_intfs_c_ -#elif defined _RTW_SECURITY_C_ - #define _MODULE_DEFINE_ _module_rtl871x_security_c_ -#elif defined _RTW_EEPROM_C_ - #define _MODULE_DEFINE_ _module_rtl871x_eeprom_c_ -#elif defined _HAL_INTF_C_ - #define _MODULE_DEFINE_ _module_hal_init_c_ -#elif (defined _HCI_HAL_INIT_C_) || (defined _SDIO_HALINIT_C_) - #define _MODULE_DEFINE_ _module_hci_hal_init_c_ -#elif defined _RTL871X_IOCTL_C_ - #define _MODULE_DEFINE_ _module_rtl871x_ioctl_c_ -#elif defined _RTL871X_IOCTL_SET_C_ - #define _MODULE_DEFINE_ _module_rtl871x_ioctl_set_c_ -#elif defined _RTL871X_IOCTL_QUERY_C_ - #define _MODULE_DEFINE_ _module_rtl871x_ioctl_query_c_ -#elif defined _RTL871X_PWRCTRL_C_ - #define _MODULE_DEFINE_ _module_rtl871x_pwrctrl_c_ -#elif defined _RTW_PWRCTRL_C_ - #define _MODULE_DEFINE_ 1 -#elif defined _HCI_INTF_C_ - #define _MODULE_DEFINE_ _module_hci_intfs_c_ -#elif defined _HCI_OPS_C_ - #define _MODULE_DEFINE_ _module_hci_ops_c_ -#elif defined _SDIO_OPS_C_ - #define _MODULE_DEFINE_ 1 -#elif defined _OSDEP_HCI_INTF_C_ - #define _MODULE_DEFINE_ _module_hci_intfs_c_ -#elif defined _OSDEP_SERVICE_C_ - #define _MODULE_DEFINE_ _module_osdep_service_c_ -#elif defined _HCI_OPS_OS_C_ - #define _MODULE_DEFINE_ _module_hci_ops_os_c_ -#elif defined _RTL871X_IOCTL_LINUX_C_ - #define _MODULE_DEFINE_ _module_rtl871x_ioctl_os_c -#elif defined _RTL8712_CMD_C_ - #define _MODULE_DEFINE_ _module_rtl8712_cmd_c_ -#elif defined _RTL8192C_XMIT_C_ - #define _MODULE_DEFINE_ 1 -#elif defined _RTL8723AS_XMIT_C_ - #define _MODULE_DEFINE_ 1 -#elif defined _RTL8712_RECV_C_ - #define _MODULE_DEFINE_ _module_rtl8712_recv_c_ -#elif defined _RTL8192CU_RECV_C_ - #define _MODULE_DEFINE_ _module_rtl8712_recv_c_ -#elif defined _RTL871X_MLME_EXT_C_ - #define _MODULE_DEFINE_ _module_mlme_osdep_c_ -#elif defined _RTW_EFUSE_C_ - #define _MODULE_DEFINE_ _module_efuse_ -#endif - -#undef _dbgdump - -#ifndef _RTL871X_DEBUG_C_ - extern u32 GlobalDebugLevel; - extern u64 GlobalDebugComponents; -#endif - -#define _dbgdump printk - -#define DRIVER_PREFIX "RTL8723BS: " - -#if defined(_dbgdump) - -/* without driver-defined prefix */ -#undef _DBG_871X_LEVEL -#define _DBG_871X_LEVEL(level, fmt, arg...) \ - do {\ - if (level <= GlobalDebugLevel) {\ - if (level <= _drv_err_ && level > _drv_always_) \ - _dbgdump("ERROR " fmt, ##arg);\ - else \ - _dbgdump(fmt, ##arg);\ - } \ - } while (0) - -#define RTW_DBGDUMP NULL /* 'stream' for _dbgdump */ - -/* dump message to selected 'stream' */ -#define DBG_871X_SEL(sel, fmt, arg...) \ - do { \ - if (sel == RTW_DBGDUMP) \ - _DBG_871X_LEVEL(_drv_always_, fmt, ##arg); \ - else \ - seq_printf(sel, fmt, ##arg); \ - } while (0) - -#endif /* defined(_dbgdump) */ - -void sd_f0_reg_dump(void *sel, struct adapter *adapter); - -void mac_reg_dump(void *sel, struct adapter *adapter); -void bb_reg_dump(void *sel, struct adapter *adapter); -void rf_reg_dump(void *sel, struct adapter *adapter); +void mac_reg_dump(struct adapter *adapter); +void bb_reg_dump(struct adapter *adapter); +void rf_reg_dump(struct adapter *adapter); #endif /* __RTW_DEBUG_H__ */ diff --git a/drivers/staging/rtl8723bs/include/rtw_ht.h b/drivers/staging/rtl8723bs/include/rtw_ht.h index e3f353fe1e47..1527d8be2d7a 100644 --- a/drivers/staging/rtl8723bs/include/rtw_ht.h +++ b/drivers/staging/rtl8723bs/include/rtw_ht.h @@ -42,10 +42,6 @@ enum { HT_AGG_SIZE_16K = 1, HT_AGG_SIZE_32K = 2, HT_AGG_SIZE_64K = 3, - VHT_AGG_SIZE_128K = 4, - VHT_AGG_SIZE_256K = 5, - VHT_AGG_SIZE_512K = 6, - VHT_AGG_SIZE_1024K = 7, }; enum { diff --git a/drivers/staging/rtl8723bs/include/rtw_io.h b/drivers/staging/rtl8723bs/include/rtw_io.h index fbb73e698e09..e98083a07a66 100644 --- a/drivers/staging/rtl8723bs/include/rtw_io.h +++ b/drivers/staging/rtl8723bs/include/rtw_io.h @@ -104,8 +104,6 @@ struct _io_ops { void (*_read_port_cancel)(struct intf_hdl *pintfhdl); void (*_write_port_cancel)(struct intf_hdl *pintfhdl); - - u8 (*_sd_f0_read8)(struct intf_hdl *pintfhdl, u32 addr); }; struct io_req { @@ -170,29 +168,15 @@ extern void unregister_intf_hdl(struct intf_hdl *pintfhdl); extern void _rtw_attrib_read(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem); extern void _rtw_attrib_write(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem); -extern u8 _rtw_read8(struct adapter *adapter, u32 addr); -extern u16 _rtw_read16(struct adapter *adapter, u32 addr); -extern u32 _rtw_read32(struct adapter *adapter, u32 addr); - -extern int _rtw_write8(struct adapter *adapter, u32 addr, u8 val); -extern int _rtw_write16(struct adapter *adapter, u32 addr, u16 val); -extern int _rtw_write32(struct adapter *adapter, u32 addr, u32 val); - -extern u8 _rtw_sd_f0_read8(struct adapter *adapter, u32 addr); - -extern u32 _rtw_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem); +extern u8 rtw_read8(struct adapter *adapter, u32 addr); +extern u16 rtw_read16(struct adapter *adapter, u32 addr); +extern u32 rtw_read32(struct adapter *adapter, u32 addr); -#define rtw_read8(adapter, addr) _rtw_read8((adapter), (addr)) -#define rtw_read16(adapter, addr) _rtw_read16((adapter), (addr)) -#define rtw_read32(adapter, addr) _rtw_read32((adapter), (addr)) +extern int rtw_write8(struct adapter *adapter, u32 addr, u8 val); +extern int rtw_write16(struct adapter *adapter, u32 addr, u16 val); +extern int rtw_write32(struct adapter *adapter, u32 addr, u32 val); -#define rtw_write8(adapter, addr, val) _rtw_write8((adapter), (addr), (val)) -#define rtw_write16(adapter, addr, val) _rtw_write16((adapter), (addr), (val)) -#define rtw_write32(adapter, addr, val) _rtw_write32((adapter), (addr), (val)) - -#define rtw_write_port(adapter, addr, cnt, mem) _rtw_write_port((adapter), (addr), (cnt), (mem)) - -#define rtw_sd_f0_read8(adapter, addr) _rtw_sd_f0_read8((adapter), (addr)) +extern u32 rtw_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem); extern void rtw_write_scsi(struct adapter *adapter, u32 cnt, u8 *pmem); @@ -236,18 +220,4 @@ extern void bus_sync_io(struct io_queue *pio_q); extern u32 _ioreq2rwmem(struct io_queue *pio_q); extern void dev_power_down(struct adapter *Adapter, u8 bpwrup); -#define PlatformEFIOWrite1Byte(_a, _b, _c) \ - rtw_write8(_a, _b, _c) -#define PlatformEFIOWrite2Byte(_a, _b, _c) \ - rtw_write16(_a, _b, _c) -#define PlatformEFIOWrite4Byte(_a, _b, _c) \ - rtw_write32(_a, _b, _c) - -#define PlatformEFIORead1Byte(_a, _b) \ - rtw_read8(_a, _b) -#define PlatformEFIORead2Byte(_a, _b) \ - rtw_read16(_a, _b) -#define PlatformEFIORead4Byte(_a, _b) \ - rtw_read32(_a, _b) - #endif /* _RTL8711_IO_H_ */ diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h index 472818c5fd83..89b389d4c44b 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h @@ -195,47 +195,6 @@ enum { RT_CHANNEL_DOMAIN_2G_MAX, }; -enum { - RT_CHANNEL_DOMAIN_5G_NULL = 0x00, - RT_CHANNEL_DOMAIN_5G_ETSI1 = 0x01, /* Europe */ - RT_CHANNEL_DOMAIN_5G_ETSI2 = 0x02, /* Australia, New Zealand */ - RT_CHANNEL_DOMAIN_5G_ETSI3 = 0x03, /* Russia */ - RT_CHANNEL_DOMAIN_5G_FCC1 = 0x04, /* US */ - RT_CHANNEL_DOMAIN_5G_FCC2 = 0x05, /* FCC o/w DFS Channels */ - RT_CHANNEL_DOMAIN_5G_FCC3 = 0x06, /* India, Mexico */ - RT_CHANNEL_DOMAIN_5G_FCC4 = 0x07, /* Venezuela */ - RT_CHANNEL_DOMAIN_5G_FCC5 = 0x08, /* China */ - RT_CHANNEL_DOMAIN_5G_FCC6 = 0x09, /* Israel */ - RT_CHANNEL_DOMAIN_5G_FCC7_IC1 = 0x0A, /* US, Canada */ - RT_CHANNEL_DOMAIN_5G_KCC1 = 0x0B, /* Korea */ - RT_CHANNEL_DOMAIN_5G_MKK1 = 0x0C, /* Japan */ - RT_CHANNEL_DOMAIN_5G_MKK2 = 0x0D, /* Japan (W52, W53) */ - RT_CHANNEL_DOMAIN_5G_MKK3 = 0x0E, /* Japan (W56) */ - RT_CHANNEL_DOMAIN_5G_NCC1 = 0x0F, /* Taiwan */ - RT_CHANNEL_DOMAIN_5G_NCC2 = 0x10, /* Taiwan o/w DFS */ - RT_CHANNEL_DOMAIN_5G_NCC3 = 0x11, /* Taiwan w/o DFS, Band4 only */ - RT_CHANNEL_DOMAIN_5G_ETSI4 = 0x12, /* Europe w/o DFS, Band1 only */ - RT_CHANNEL_DOMAIN_5G_ETSI5 = 0x13, /* Australia, New Zealand(w/o Weather radar) */ - RT_CHANNEL_DOMAIN_5G_FCC8 = 0x14, /* Latin America */ - RT_CHANNEL_DOMAIN_5G_ETSI6 = 0x15, /* Israel, Bahrain, Egypt, India, China, Malaysia */ - RT_CHANNEL_DOMAIN_5G_ETSI7 = 0x16, /* China */ - RT_CHANNEL_DOMAIN_5G_ETSI8 = 0x17, /* Jordan */ - RT_CHANNEL_DOMAIN_5G_ETSI9 = 0x18, /* Lebanon */ - RT_CHANNEL_DOMAIN_5G_ETSI10 = 0x19, /* Qatar */ - RT_CHANNEL_DOMAIN_5G_ETSI11 = 0x1A, /* Russia */ - RT_CHANNEL_DOMAIN_5G_NCC4 = 0x1B, /* Taiwan, (w/o Weather radar) */ - RT_CHANNEL_DOMAIN_5G_ETSI12 = 0x1C, /* Indonesia */ - RT_CHANNEL_DOMAIN_5G_FCC9 = 0x1D, /* w/o Weather radar) */ - RT_CHANNEL_DOMAIN_5G_ETSI13 = 0x1E, /* w/o Weather radar) */ - RT_CHANNEL_DOMAIN_5G_FCC10 = 0x1F, /* Argentina (w/o Weather radar) */ - /* Add new channel plan above this line =============== */ - /* Driver Self Defined ===== */ - RT_CHANNEL_DOMAIN_5G_FCC = 0x20, - RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS = 0x21, - RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS = 0x22, - RT_CHANNEL_DOMAIN_5G_MAX, -}; - #define rtw_is_channel_plan_valid(chplan) (chplan < RT_CHANNEL_DOMAIN_MAX || chplan == RT_CHANNEL_DOMAIN_REALTEK_DEFINE) struct rt_channel_plan { @@ -248,14 +207,8 @@ struct rt_channel_plan_2g { unsigned char Len; }; -struct rt_channel_plan_5g { - unsigned char Channel[MAX_CHANNEL_NUM_5G]; - unsigned char Len; -}; - struct rt_channel_plan_map { unsigned char Index2G; - unsigned char Index5G; }; enum { @@ -348,13 +301,13 @@ struct FW_Sta_Info { * When the driver scanned RTW_SCAN_NUM_OF_CH channels, it would switch back to AP's operating channel for * RTW_STAY_AP_CH_MILLISECOND * SURVEY_TO milliseconds. * Example: - * For chip supports 2.4G + 5GHz and AP mode is operating in channel 1, + * For chip supports 2.4G and AP mode is operating in channel 1, * RTW_SCAN_NUM_OF_CH is 8, RTW_STAY_AP_CH_MILLISECOND is 3 and SURVEY_TO is 100. * When it's STA mode gets set_scan command, * it would * 1. Doing the scan on channel 1.2.3.4.5.6.7.8 * 2. Back to channel 1 for 300 milliseconds - * 3. Go through doing site survey on channel 9.10.11.36.40.44.48.52 + * 3. Go through doing site survey on channel 9.10.11 * 4. Back to channel 1 for 300 milliseconds * 5. ... and so on, till survey done. */ @@ -411,7 +364,6 @@ struct rt_channel_info { }; int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch); -bool rtw_mlme_band_check(struct adapter *adapter, const u32 ch); /* P2P_MAX_REG_CLASSES - Maximum number of regulatory classes */ #define P2P_MAX_REG_CLASSES 10 @@ -805,38 +757,6 @@ enum { #ifdef _RTW_MLME_EXT_C_ -static struct fwevent wlanevents[] = -{ - {0, rtw_dummy_event_callback}, /*0*/ - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, &rtw_survey_event_callback}, /*8*/ - {sizeof(struct surveydone_event), &rtw_surveydone_event_callback}, /*9*/ - - {0, &rtw_joinbss_event_callback}, /*10*/ - {sizeof(struct stassoc_event), &rtw_stassoc_event_callback}, - {sizeof(struct stadel_event), &rtw_stadel_event_callback}, - {0, &rtw_atimdone_event_callback}, - {0, rtw_dummy_event_callback}, - {0, NULL}, /*15*/ - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, rtw_fwdbg_event_callback}, - {0, NULL}, /*20*/ - {0, NULL}, - {0, NULL}, - {0, &rtw_cpwm_event_callback}, - {0, NULL}, - {0, &rtw_wmm_event_callback}, - -}; - #endif/* _RTL8192C_CMD_C_ */ #endif diff --git a/drivers/staging/rtl8723bs/include/rtw_mp.h b/drivers/staging/rtl8723bs/include/rtw_mp.h index 2788ad80b114..ea3abee325ef 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mp.h +++ b/drivers/staging/rtl8723bs/include/rtw_mp.h @@ -348,7 +348,6 @@ void Hal_SetCarrierSuppressionTx(struct adapter *padapter, u8 bStart); void Hal_SetSingleToneTx(struct adapter *padapter, u8 bStart); void Hal_SetSingleCarrierTx(struct adapter *padapter, u8 bStart); void Hal_SetContinuousTx(struct adapter *padapter, u8 bStart); -void Hal_SetBandwidth(struct adapter *padapter); void Hal_SetDataRate(struct adapter *padapter); void Hal_SetChannel(struct adapter *padapter); diff --git a/drivers/staging/rtl8723bs/include/rtw_rf.h b/drivers/staging/rtl8723bs/include/rtw_rf.h index cb6beccd3d23..6c25707f4ec8 100644 --- a/drivers/staging/rtl8723bs/include/rtw_rf.h +++ b/drivers/staging/rtl8723bs/include/rtw_rf.h @@ -21,16 +21,13 @@ #define RTL8711_RF_MAX_SENS 6 #define RTL8711_RF_DEF_SENS 4 -/* */ -/* We now define the following channels as the max channels in each channel plan. */ -/* 2G, total 14 chnls */ -/* {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14} */ -/* 5G, total 24 chnls */ -/* {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, - * 124, 128, 132, 136, 140, 149, 153, 157, 161, 165} */ +/* + * We now define the following channels as the max channels in each channel plan. + * 2G, total 14 chnls + * {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14} + */ #define MAX_CHANNEL_NUM_2G 14 -#define MAX_CHANNEL_NUM_5G 24 -#define MAX_CHANNEL_NUM 38/* 14+24 */ +#define MAX_CHANNEL_NUM 14 #define NUM_REGULATORYS 1 @@ -83,10 +80,6 @@ enum { enum channel_width { CHANNEL_WIDTH_20 = 0, CHANNEL_WIDTH_40 = 1, - CHANNEL_WIDTH_80 = 2, - CHANNEL_WIDTH_160 = 3, - CHANNEL_WIDTH_80_80 = 4, - CHANNEL_WIDTH_MAX = 5, }; /* Represent Extension Channel Offset in HT Capabilities */ @@ -99,17 +92,9 @@ enum extchnl_offset { }; enum { - VHT_DATA_SC_DONOT_CARE = 0, - VHT_DATA_SC_20_UPPER_OF_80MHZ = 1, - VHT_DATA_SC_20_LOWER_OF_80MHZ = 2, - VHT_DATA_SC_20_UPPERST_OF_80MHZ = 3, - VHT_DATA_SC_20_LOWEST_OF_80MHZ = 4, - VHT_DATA_SC_20_RECV1 = 5, - VHT_DATA_SC_20_RECV2 = 6, - VHT_DATA_SC_20_RECV3 = 7, - VHT_DATA_SC_20_RECV4 = 8, - VHT_DATA_SC_40_UPPER_OF_80MHZ = 9, - VHT_DATA_SC_40_LOWER_OF_80MHZ = 10, + HT_DATA_SC_DONOT_CARE = 0, + HT_DATA_SC_20_UPPER_OF_40MHZ = 1, + HT_DATA_SC_20_LOWER_OF_40MHZ = 2, }; /* 2007/11/15 MH Define different RF type. */ diff --git a/drivers/staging/rtl8723bs/include/rtw_security.h b/drivers/staging/rtl8723bs/include/rtw_security.h index 5c787e999aab..a68b73858462 100644 --- a/drivers/staging/rtl8723bs/include/rtw_security.h +++ b/drivers/staging/rtl8723bs/include/rtw_security.h @@ -7,6 +7,7 @@ #ifndef __RTW_SECURITY_H_ #define __RTW_SECURITY_H_ +#include <crypto/arc4.h> #define _NO_PRIVACY_ 0x0 #define _WEP40_ 0x1 @@ -127,6 +128,8 @@ struct security_priv { u8 wps_ie[MAX_WPS_IE_LEN];/* added in assoc req */ int wps_ie_len; + struct arc4_ctx xmit_arc4_ctx; + struct arc4_ctx recv_arc4_ctx; u8 binstallGrpkey; u8 binstallBIPkey; @@ -191,8 +194,6 @@ do {\ } \ } while (0) -#define _AES_IV_LEN_ 8 - #define SET_ICE_IV_LEN(iv_len, icv_len, encrypt)\ do {\ switch (encrypt)\ @@ -243,110 +244,11 @@ struct mic_data { u32 nBytesInM; /* # bytes in M */ }; -extern const u32 Te0[256]; -extern const u32 Te1[256]; -extern const u32 Te2[256]; -extern const u32 Te3[256]; -extern const u32 Te4[256]; -extern const u32 Td0[256]; -extern const u32 Td1[256]; -extern const u32 Td2[256]; -extern const u32 Td3[256]; -extern const u32 Td4[256]; -extern const u32 rcon[10]; -extern const u8 Td4s[256]; -extern const u8 rcons[10]; - -#define RCON(i) (rcons[(i)] << 24) - -static inline u32 rotr(u32 val, int bits) -{ - return (val >> bits) | (val << (32 - bits)); -} - -#define TE0(i) Te0[((i) >> 24) & 0xff] -#define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8) -#define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16) -#define TE3(i) rotr(Te0[(i) & 0xff], 24) -#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000) -#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000) -#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00) -#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff) -#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000) -#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000) -#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00) -#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff) -#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff) - -#define TD0(i) Td0[((i) >> 24) & 0xff] -#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8) -#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16) -#define TD3(i) rotr(Td0[(i) & 0xff], 24) -#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24) -#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16) -#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8) -#define TD44(i) (Td4s[(i) & 0xff]) -#define TD0_(i) Td0[(i) & 0xff] -#define TD1_(i) rotr(Td0[(i) & 0xff], 8) -#define TD2_(i) rotr(Td0[(i) & 0xff], 16) -#define TD3_(i) rotr(Td0[(i) & 0xff], 24) - -#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \ - ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) - -#define PUTU32(ct, st) { \ -(ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \ -(ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } - -#define WPA_GET_BE32(a) ((((u32) (a)[0]) << 24) | (((u32) (a)[1]) << 16) | \ - (((u32) (a)[2]) << 8) | ((u32) (a)[3])) - -#define WPA_PUT_LE16(a, val) \ - do { \ - (a)[1] = ((u16) (val)) >> 8; \ - (a)[0] = ((u16) (val)) & 0xff; \ - } while (0) - -#define WPA_PUT_BE32(a, val) \ - do { \ - (a)[0] = (u8) ((((u32) (val)) >> 24) & 0xff); \ - (a)[1] = (u8) ((((u32) (val)) >> 16) & 0xff); \ - (a)[2] = (u8) ((((u32) (val)) >> 8) & 0xff); \ - (a)[3] = (u8) (((u32) (val)) & 0xff); \ - } while (0) - -#define WPA_PUT_BE64(a, val) \ - do { \ - (a)[0] = (u8) (((u64) (val)) >> 56); \ - (a)[1] = (u8) (((u64) (val)) >> 48); \ - (a)[2] = (u8) (((u64) (val)) >> 40); \ - (a)[3] = (u8) (((u64) (val)) >> 32); \ - (a)[4] = (u8) (((u64) (val)) >> 24); \ - (a)[5] = (u8) (((u64) (val)) >> 16); \ - (a)[6] = (u8) (((u64) (val)) >> 8); \ - (a)[7] = (u8) (((u64) (val)) & 0xff); \ - } while (0) - /* ===== start - public domain SHA256 implementation ===== */ /* This is based on SHA256 implementation in LibTomCrypt that was released into * public domain by Tom St Denis. */ -/* Various logical functions */ -#define RORc(x, y) \ -(((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \ - ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL) -#define Ch(x, y, z) (z ^ (x & (y ^ z))) -#define Maj(x, y, z) (((x | y) & z) | (x & y)) -#define S(x, n) RORc((x), (n)) -#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) -#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) -#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) -#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) -#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) -#ifndef MIN -#define MIN(x, y) (((x) < (y)) ? (x) : (y)) -#endif int omac1_aes_128(u8 *key, u8 *data, size_t data_len, u8 *mac); void rtw_secmicsetkey(struct mic_data *pmicdata, u8 *key); void rtw_secmicappendbyte(struct mic_data *pmicdata, u8 b); diff --git a/drivers/staging/rtl8723bs/include/rtw_xmit.h b/drivers/staging/rtl8723bs/include/rtw_xmit.h index e45753d17313..676ead0372fa 100644 --- a/drivers/staging/rtl8723bs/include/rtw_xmit.h +++ b/drivers/staging/rtl8723bs/include/rtw_xmit.h @@ -234,7 +234,7 @@ enum { void rtw_sctx_init(struct submit_ctx *sctx, int timeout_ms); -int rtw_sctx_wait(struct submit_ctx *sctx, const char *msg); +int rtw_sctx_wait(struct submit_ctx *sctx); void rtw_sctx_done_err(struct submit_ctx **sctx, int status); void rtw_sctx_done(struct submit_ctx **sctx); diff --git a/drivers/staging/rtl8723bs/include/sdio_ops_linux.h b/drivers/staging/rtl8723bs/include/sdio_ops_linux.h index 16a03adbc2cf..18830dd18372 100644 --- a/drivers/staging/rtl8723bs/include/sdio_ops_linux.h +++ b/drivers/staging/rtl8723bs/include/sdio_ops_linux.h @@ -11,8 +11,6 @@ #define SDIO_ERR_VAL16 0xEAEA #define SDIO_ERR_VAL32 0xEAEAEAEA -u8 sd_f0_read8(struct intf_hdl *pintfhdl, u32 addr, s32 *err); - s32 _sd_cmd52_read(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pdata); s32 _sd_cmd52_write(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pdata); s32 sd_cmd52_read(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pdata); diff --git a/drivers/staging/rtl8723bs/include/wifi.h b/drivers/staging/rtl8723bs/include/wifi.h index 036cf57c65a9..0bd7b662b972 100644 --- a/drivers/staging/rtl8723bs/include/wifi.h +++ b/drivers/staging/rtl8723bs/include/wifi.h @@ -234,7 +234,7 @@ static inline int IS_MCAST(unsigned char *da) return false; } -static inline unsigned char *get_ra(unsigned char *pframe) +static inline unsigned char *rtl8723bs_get_ra(unsigned char *pframe) { unsigned char *ra; ra = GetAddr1Ptr(pframe); @@ -336,7 +336,6 @@ static inline int IsFrameTypeCtrl(unsigned char *pframe) #define _PRE_ALLOCICVHDR_ 5 #define _PRE_ALLOCMICHDR_ 6 -#define _SIFSTIME_ ((priv->pmib->dot11BssType.net_work_type&WIRELESS_11A)?16:10) #define _ACKCTSLNG_ 14 /* 14 bytes long, including crclng */ #define _CRCLNG_ 4 diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c index 437859228371..fd747c8d920e 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c @@ -77,7 +77,6 @@ static struct ieee80211_rate rtw_rates[] = { #define RTW_G_RATES_NUM 12 #define RTW_2G_CHANNELS_NUM 14 -#define RTW_5G_CHANNELS_NUM 37 static struct ieee80211_channel rtw_2ghz_channels[] = { CHAN2G(1, 2412, 0), @@ -203,8 +202,6 @@ rtw_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { static int rtw_ieee80211_channel_to_frequency(int chan, int band) { - /* see 802.11 17.3.8.3.2 and Annex J - * there are overlapping channel numbers in 5GHz and 2GHz bands */ if (band == NL80211_BAND_2GHZ) { if (chan == 14) return 2484; @@ -229,7 +226,6 @@ struct cfg80211_bss *rtw_cfg80211_inform_bss(struct adapter *padapter, struct wl size_t len, bssinf_len = 0; struct ieee80211_hdr *pwlanhdr; __le16 *fctrl; - u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; struct wireless_dev *wdev = padapter->rtw_wdev; struct wiphy *wiphy = wdev->wiphy; @@ -310,7 +306,7 @@ struct cfg80211_bss *rtw_cfg80211_inform_bss(struct adapter *padapter, struct wl /* pmlmeext->mgnt_seq++; */ if (pnetwork->network.Reserved[0] == 1) { /* WIFI_BEACON */ - memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); + eth_broadcast_addr(pwlanhdr->addr1); SetFrameSubType(pbuf, WIFI_BEACON); } else { memcpy(pwlanhdr->addr1, myid(&(padapter->eeprompriv)), ETH_ALEN); @@ -960,7 +956,7 @@ static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev, memset(param, 0, param_len); param->cmd = IEEE_CMD_SET_ENCRYPTION; - memset(param->sta_addr, 0xff, ETH_ALEN); + eth_broadcast_addr(param->sta_addr); switch (params->cipher) { case IW_AUTH_CIPHER_NONE: @@ -1265,18 +1261,12 @@ void rtw_cfg80211_surveydone_event_callback(struct adapter *padapter) spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); phead = get_list_head(queue); - plist = get_next(phead); - - while (1) + list_for_each(plist, phead) { - if (phead == plist) - break; - - pnetwork = container_of(plist, struct wlan_network, list); + pnetwork = list_entry(plist, struct wlan_network, list); /* report network only if the current channel set contains the channel to which this network belongs */ if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0 - && rtw_mlme_band_check(padapter, pnetwork->network.Configuration.DSConfig) == true && true == rtw_validate_ssid(&(pnetwork->network.Ssid)) ) { @@ -1284,8 +1274,6 @@ void rtw_cfg80211_surveydone_event_callback(struct adapter *padapter) rtw_cfg80211_inform_bss(padapter, pnetwork); } - plist = get_next(plist); - } spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); @@ -2460,7 +2448,7 @@ static int cfg80211_rtw_del_station(struct wiphy *wiphy, struct net_device *ndev struct station_del_parameters *params) { int ret = 0; - struct list_head *phead, *plist; + struct list_head *phead, *plist, *tmp; u8 updated = false; struct sta_info *psta = NULL; struct adapter *padapter = rtw_netdev_priv(ndev); @@ -2489,13 +2477,9 @@ static int cfg80211_rtw_del_station(struct wiphy *wiphy, struct net_device *ndev spin_lock_bh(&pstapriv->asoc_list_lock); phead = &pstapriv->asoc_list; - plist = get_next(phead); - /* check asoc_queue */ - while (phead != plist) { - psta = container_of(plist, struct sta_info, asoc_list); - - plist = get_next(plist); + list_for_each_safe(plist, tmp, phead) { + psta = list_entry(plist, struct sta_info, asoc_list); if (!memcmp((u8 *)mac, psta->hwaddr, ETH_ALEN)) { if (psta->dot8021xalg != 1 || psta->bpairwise_key_installed) { @@ -2598,7 +2582,7 @@ static int _cfg80211_rtw_mgmt_tx(struct adapter *padapter, u8 tx_ch, const u8 *b struct pkt_attrib *pattrib; unsigned char *pframe; int ret = _FAIL; - bool ack = true; + bool __maybe_unused ack = true; struct ieee80211_hdr *pwlanhdr; struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c index 5088c3731b6d..f95000df8942 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c @@ -420,8 +420,10 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, wep_key_len = wep_key_len <= 5 ? 5 : 13; wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial); pwep = kzalloc(wep_total_len, GFP_KERNEL); - if (!pwep) + if (!pwep) { + ret = -ENOMEM; goto exit; + } pwep->KeyLength = wep_key_len; pwep->Length = wep_total_len; @@ -1052,15 +1054,9 @@ static int rtw_wx_set_wap(struct net_device *dev, authmode = padapter->securitypriv.ndisauthtype; spin_lock_bh(&queue->lock); phead = get_list_head(queue); - pmlmepriv->pscanned = get_next(phead); - - while (1) { - if (phead == pmlmepriv->pscanned) - break; - - pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list); - - pmlmepriv->pscanned = get_next(pmlmepriv->pscanned); + list_for_each(pmlmepriv->pscanned, phead) { + pnetwork = list_entry(pmlmepriv->pscanned, + struct wlan_network, list); dst_bssid = pnetwork->network.MacAddress; @@ -1299,29 +1295,21 @@ static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a, spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); phead = get_list_head(queue); - plist = get_next(phead); - - while (1) { - if (phead == plist) - break; - + list_for_each(plist, phead) { if ((stop - ev) < SCAN_ITEM_SIZE) { ret = -E2BIG; break; } - pnetwork = container_of(plist, struct wlan_network, list); + pnetwork = list_entry(plist, struct wlan_network, list); /* report network only if the current channel set contains the channel to which this network belongs */ if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0 - && rtw_mlme_band_check(padapter, pnetwork->network.Configuration.DSConfig) == true && true == rtw_validate_ssid(&(pnetwork->network.Ssid))) { ev = translate_scan(padapter, a, pnetwork, ev, stop); } - plist = get_next(plist); - } spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); @@ -1387,15 +1375,9 @@ static int rtw_wx_set_essid(struct net_device *dev, spin_lock_bh(&queue->lock); phead = get_list_head(queue); - pmlmepriv->pscanned = get_next(phead); - - while (1) { - if (phead == pmlmepriv->pscanned) - break; - - pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list); - - pmlmepriv->pscanned = get_next(pmlmepriv->pscanned); + list_for_each(pmlmepriv->pscanned, phead) { + pnetwork = list_entry(pmlmepriv->pscanned, + struct wlan_network, list); dst_ssid = pnetwork->network.Ssid.Ssid; @@ -1934,7 +1916,7 @@ static int rtw_wx_set_enc_ext(struct net_device *dev, return -1; param->cmd = IEEE_CMD_SET_ENCRYPTION; - memset(param->sta_addr, 0xff, ETH_ALEN); + eth_broadcast_addr(param->sta_addr); switch (pext->alg) { @@ -2252,14 +2234,8 @@ static int rtw_get_ap_info(struct net_device *dev, spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); phead = get_list_head(queue); - plist = get_next(phead); - - while (1) { - if (phead == plist) - break; - - - pnetwork = container_of(plist, struct wlan_network, list); + list_for_each(plist, phead) { + pnetwork = list_entry(plist, struct wlan_network, list); if (!mac_pton(data, bssid)) { spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); @@ -2282,8 +2258,6 @@ static int rtw_get_ap_info(struct net_device *dev, } } - plist = get_next(plist); - } spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); @@ -2600,10 +2574,9 @@ static int rtw_dbg_port(struct net_device *dev, case 0x12: /* set rx_stbc */ { struct registry_priv *pregpriv = &padapter->registrypriv; - /* 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, 0x3: enable both 2.4g and 5g */ - /* default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */ - if (extra_arg == 0 || extra_arg == 1 || - extra_arg == 2 || extra_arg == 3) + /* 0: disable, bit(0):enable 2.4g */ + /* default is set to enable 2.4GHZ */ + if (extra_arg == 0 || extra_arg == 1) pregpriv->rx_stbc = extra_arg; } break; @@ -2734,11 +2707,11 @@ static int rtw_dbg_port(struct net_device *dev, case 0xdd:/* registers dump , 0 for mac reg, 1 for bb reg, 2 for rf reg */ { if (extra_arg == 0) - mac_reg_dump(RTW_DBGDUMP, padapter); + mac_reg_dump(padapter); else if (extra_arg == 1) - bb_reg_dump(RTW_DBGDUMP, padapter); + bb_reg_dump(padapter); else if (extra_arg == 2) - rf_reg_dump(RTW_DBGDUMP, padapter); + rf_reg_dump(padapter); } break; diff --git a/drivers/staging/rtl8723bs/os_dep/mlme_linux.c b/drivers/staging/rtl8723bs/os_dep/mlme_linux.c index 0a16752f805b..a4560ba22db1 100644 --- a/drivers/staging/rtl8723bs/os_dep/mlme_linux.c +++ b/drivers/staging/rtl8723bs/os_dep/mlme_linux.c @@ -4,10 +4,6 @@ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. * ******************************************************************************/ - - -#define _MLME_OSDEP_C_ - #include <drv_types.h> #include <rtw_debug.h> diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c index 160f624612c7..648456b992bb 100644 --- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c +++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c @@ -4,8 +4,6 @@ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. * ******************************************************************************/ -#define _OS_INTFS_C_ - #include <drv_types.h> #include <rtw_debug.h> #include <hal_data.h> @@ -24,7 +22,7 @@ static int rtw_lbkmode;/* RTL8712_AIR_TRX; */ static int rtw_network_mode = Ndis802_11IBSS;/* Ndis802_11Infrastructure;infra, ad-hoc, auto */ /* struct ndis_802_11_ssid ssid; */ static int rtw_channel = 1;/* ad-hoc support requirement */ -static int rtw_wireless_mode = WIRELESS_MODE_MAX; +static int rtw_wireless_mode = WIRELESS_11BG_24N; static int rtw_vrtl_carrier_sense = AUTO_VCS; static int rtw_vcs_type = RTS_CTS;/* */ static int rtw_rts_thresh = 2347;/* */ @@ -67,10 +65,12 @@ static int rtw_uapsd_acvi_en; static int rtw_uapsd_acvo_en; int rtw_ht_enable = 1; -/* 0: 20 MHz, 1: 40 MHz, 2: 80 MHz, 3: 160MHz, 4: 80+80MHz */ -/* 2.4G use bit 0 ~ 3, 5G use bit 4 ~ 7 */ -/* 0x21 means enable 2.4G 40MHz & 5G 80MHz */ -static int rtw_bw_mode = 0x21; +/* + * 0: 20 MHz, 1: 40 MHz + * 2.4G use bit 0 ~ 3 + * 0x01 means enable 2.4G 40MHz + */ +static int rtw_bw_mode = 0x01; static int rtw_ampdu_enable = 1;/* for enable tx_ampdu ,0: disable, 0x1:enable (but wifi_spec should be 0), 0x2: force enable (don't care wifi_spec) */ static int rtw_rx_stbc = 1;/* 0: disable, 1:enable 2.4g */ static int rtw_ampdu_amsdu;/* 0: disabled, 1:enabled, 2:auto . There is an IOT issu with DLINK DIR-629 when the flag turn on */ @@ -289,7 +289,6 @@ static void loadparam(struct adapter *padapter, struct net_device *pnetdev) registry_par->RegPowerBase = 14; registry_par->TxBBSwing_2G = 0xFF; - registry_par->TxBBSwing_5G = 0xFF; registry_par->bEn_RFE = 1; registry_par->RFE_Type = 64; @@ -1152,14 +1151,13 @@ static void rtw_suspend_normal(struct adapter *padapter) padapter->intf_deinit(adapter_to_dvobj(padapter)); } -int rtw_suspend_common(struct adapter *padapter) +void rtw_suspend_common(struct adapter *padapter) { struct dvobj_priv *psdpriv = padapter->dvobj; struct debug_priv *pdbgpriv = &psdpriv->drv_dbg; struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(psdpriv); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int ret = 0; unsigned long start_time = jiffies; netdev_dbg(padapter->pnetdev, " suspend start\n"); @@ -1190,19 +1188,14 @@ int rtw_suspend_common(struct adapter *padapter) rtw_ps_deny_cancel(padapter, PS_DENY_SUSPEND); - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) - rtw_suspend_normal(padapter); - else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - rtw_suspend_normal(padapter); - else - rtw_suspend_normal(padapter); + rtw_suspend_normal(padapter); netdev_dbg(padapter->pnetdev, "rtw suspend success in %d ms\n", jiffies_to_msecs(jiffies - start_time)); exit: - return ret; + return; } static int rtw_resume_process_normal(struct adapter *padapter) @@ -1269,17 +1262,10 @@ int rtw_resume_common(struct adapter *padapter) int ret = 0; unsigned long start_time = jiffies; struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; netdev_dbg(padapter->pnetdev, "resume start\n"); - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - rtw_resume_process_normal(padapter); - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - rtw_resume_process_normal(padapter); - } else { - rtw_resume_process_normal(padapter); - } + rtw_resume_process_normal(padapter); hal_btcoex_SuspendNotify(padapter, 0); diff --git a/drivers/staging/rtl8723bs/os_dep/osdep_service.c b/drivers/staging/rtl8723bs/os_dep/osdep_service.c index 9c6b1666df13..c58555a4012f 100644 --- a/drivers/staging/rtl8723bs/os_dep/osdep_service.c +++ b/drivers/staging/rtl8723bs/os_dep/osdep_service.c @@ -4,10 +4,6 @@ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. * ******************************************************************************/ - - -#define _OSDEP_SERVICE_C_ - #include <drv_types.h> #include <rtw_debug.h> diff --git a/drivers/staging/rtl8723bs/os_dep/recv_linux.c b/drivers/staging/rtl8723bs/os_dep/recv_linux.c index cd51430d4618..88a69c7ca8f2 100644 --- a/drivers/staging/rtl8723bs/os_dep/recv_linux.c +++ b/drivers/staging/rtl8723bs/os_dep/recv_linux.c @@ -4,8 +4,6 @@ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. * ******************************************************************************/ -#define _RECV_OSDEP_C_ - #include <drv_types.h> #include <rtw_debug.h> #include <linux/jiffies.h> diff --git a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c index d2bf444117b8..490431484524 100644 --- a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c +++ b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c @@ -4,8 +4,6 @@ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. * ******************************************************************************/ -#define _HCI_INTF_C_ - #include <drv_types.h> #include <rtw_debug.h> #include <hal_btcoex.h> @@ -449,7 +447,9 @@ static int rtw_sdio_suspend(struct device *dev) return 0; } - return rtw_suspend_common(padapter); + rtw_suspend_common(padapter); + + return 0; } static int rtw_resume_process(struct adapter *padapter) diff --git a/drivers/staging/rtl8723bs/os_dep/sdio_ops_linux.c b/drivers/staging/rtl8723bs/os_dep/sdio_ops_linux.c index 5cedf775b6ef..bed930760656 100644 --- a/drivers/staging/rtl8723bs/os_dep/sdio_ops_linux.c +++ b/drivers/staging/rtl8723bs/os_dep/sdio_ops_linux.c @@ -26,34 +26,6 @@ inline void rtw_sdio_set_irq_thd(struct dvobj_priv *dvobj, void *thd_hdl) sdio_data->sys_sdio_irq_thd = thd_hdl; } -u8 sd_f0_read8(struct intf_hdl *pintfhdl, u32 addr, s32 *err) -{ - struct adapter *padapter; - struct dvobj_priv *psdiodev; - struct sdio_data *psdio; - - u8 v = 0; - struct sdio_func *func; - bool claim_needed; - - padapter = pintfhdl->padapter; - psdiodev = pintfhdl->pintf_dev; - psdio = &psdiodev->intf_data; - - if (padapter->bSurpriseRemoved) - return v; - - func = psdio->func; - claim_needed = rtw_sdio_claim_host_needed(func); - - if (claim_needed) - sdio_claim_host(func); - v = sdio_f0_readb(func, addr, err); - if (claim_needed) - sdio_release_host(func); - return v; -} - /* * Return: *0 Success diff --git a/drivers/staging/rtl8723bs/os_dep/wifi_regd.c b/drivers/staging/rtl8723bs/os_dep/wifi_regd.c index 0084589499b9..5eef1d68c6f0 100644 --- a/drivers/staging/rtl8723bs/os_dep/wifi_regd.c +++ b/drivers/staging/rtl8723bs/os_dep/wifi_regd.c @@ -44,10 +44,6 @@ static const struct ieee80211_regdomain rtw_regdom_rd = { static int rtw_ieee80211_channel_to_frequency(int chan, int band) { - /* see 802.11 17.3.8.3.2 and Annex J - * there are overlapping channel numbers in 5GHz and 2GHz bands - */ - /* NL80211_BAND_2GHZ */ if (chan == 14) return 2484; diff --git a/drivers/staging/rtl8723bs/os_dep/xmit_linux.c b/drivers/staging/rtl8723bs/os_dep/xmit_linux.c index 639408eaf4df..530e7a6c67c5 100644 --- a/drivers/staging/rtl8723bs/os_dep/xmit_linux.c +++ b/drivers/staging/rtl8723bs/os_dep/xmit_linux.c @@ -4,8 +4,6 @@ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. * ******************************************************************************/ -#define _XMIT_OSDEP_C_ - #include <drv_types.h> #include <rtw_debug.h> @@ -139,13 +137,11 @@ static int rtw_mlcst2unicst(struct adapter *padapter, struct sk_buff *skb) spin_lock_bh(&pstapriv->asoc_list_lock); phead = &pstapriv->asoc_list; - plist = get_next(phead); - /* free sta asoc_queue */ - while (phead != plist) { + list_for_each(plist, phead) { int stainfo_offset; - psta = container_of(plist, struct sta_info, asoc_list); - plist = get_next(plist); + + psta = list_entry(plist, struct sta_info, asoc_list); stainfo_offset = rtw_stainfo_offset(pstapriv, psta); if (stainfo_offset_valid(stainfo_offset)) { diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index 9001570a8c94..c6ad34a7fa33 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -2406,7 +2406,6 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) (void)ms_arbitrate_l2p(chip, phy_blk, log_blk - ms_start_idx[seg_no], us1, us2); - continue; } segment->build_flag = 1; diff --git a/drivers/staging/sm750fb/sm750_accel.c b/drivers/staging/sm750fb/sm750_accel.c index 8faa601c700b..24b9077a634a 100644 --- a/drivers/staging/sm750fb/sm750_accel.c +++ b/drivers/staging/sm750fb/sm750_accel.c @@ -131,7 +131,8 @@ int sm750_hw_fillrect(struct lynx_accel *accel, } /** - * sm750_hm_copyarea + * sm750_hw_copyarea + * @accel: Acceleration device data * @sBase: Address of source: offset in frame buffer * @sPitch: Pitch value of source surface in BYTE * @sx: Starting x coordinate of source surface @@ -298,6 +299,7 @@ static unsigned int deGetTransparency(struct lynx_accel *accel) /** * sm750_hw_imageblit + * @accel: Acceleration device data * @pSrcbuf: pointer to start of source buffer in system memory * @srcDelta: Pitch value (in bytes) of the source buffer, +ive means top down * and -ive mean button up diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c index 4455d26f7c96..41f8a72a2a95 100644 --- a/drivers/staging/unisys/visorhba/visorhba_main.c +++ b/drivers/staging/unisys/visorhba/visorhba_main.c @@ -6,10 +6,10 @@ #include <linux/debugfs.h> #include <linux/kthread.h> -#include <linux/idr.h> #include <linux/module.h> #include <linux/seq_file.h> #include <linux/visorbus.h> +#include <linux/xarray.h> #include <scsi/scsi.h> #include <scsi/scsi_host.h> #include <scsi/scsi_cmnd.h> @@ -82,8 +82,7 @@ struct visorhba_devdata { * allows us to pass int handles back-and-forth between us and * iovm, instead of raw pointers */ - struct idr idr; - + struct xarray xa; struct dentry *debugfs_dir; struct dentry *debugfs_info; }; @@ -183,70 +182,47 @@ static struct uiscmdrsp *get_scsipending_cmdrsp(struct visorhba_devdata *ddata, } /* - * simple_idr_get - Associate a provided pointer with an int value - * 1 <= value <= INT_MAX, and return this int value; - * the pointer value can be obtained later by passing - * this int value to idr_find() - * @idrtable: The data object maintaining the pointer<-->int mappings - * @p: The pointer value to be remembered - * @lock: A spinlock used when exclusive access to idrtable is needed - * - * Return: The id number mapped to pointer 'p', 0 on failure - */ -static unsigned int simple_idr_get(struct idr *idrtable, void *p, - spinlock_t *lock) -{ - int id; - unsigned long flags; - - idr_preload(GFP_KERNEL); - spin_lock_irqsave(lock, flags); - id = idr_alloc(idrtable, p, 1, INT_MAX, GFP_NOWAIT); - spin_unlock_irqrestore(lock, flags); - idr_preload_end(); - /* failure */ - if (id < 0) - return 0; - /* idr_alloc() guarantees > 0 */ - return (unsigned int)(id); -} - -/* * setup_scsitaskmgmt_handles - Stash the necessary handles so that the * completion processing logic for a taskmgmt * cmd will be able to find who to wake up * and where to stash the result - * @idrtable: The data object maintaining the pointer<-->int mappings - * @lock: A spinlock used when exclusive access to idrtable is needed + * @xa: The data object maintaining the pointer<-->int mappings * @cmdrsp: Response from the IOVM * @event: The event handle to associate with an id * @result: The location to place the result of the event handle into */ -static void setup_scsitaskmgmt_handles(struct idr *idrtable, spinlock_t *lock, - struct uiscmdrsp *cmdrsp, +static int setup_scsitaskmgmt_handles(struct xarray *xa, struct uiscmdrsp *cmdrsp, wait_queue_head_t *event, int *result) { - /* specify the event that has to be triggered when this */ - /* cmd is complete */ - cmdrsp->scsitaskmgmt.notify_handle = - simple_idr_get(idrtable, event, lock); - cmdrsp->scsitaskmgmt.notifyresult_handle = - simple_idr_get(idrtable, result, lock); + int ret; + u32 id; + + /* specify the event that has to be triggered when this cmd is complete */ + ret = xa_alloc_irq(xa, &id, event, xa_limit_32b, GFP_KERNEL); + if (ret) + return ret; + cmdrsp->scsitaskmgmt.notify_handle = id; + ret = xa_alloc_irq(xa, &id, result, xa_limit_32b, GFP_KERNEL); + if (ret) { + xa_erase_irq(xa, cmdrsp->scsitaskmgmt.notify_handle); + return ret; + } + cmdrsp->scsitaskmgmt.notifyresult_handle = id; + + return 0; } /* * cleanup_scsitaskmgmt_handles - Forget handles created by * setup_scsitaskmgmt_handles() - * @idrtable: The data object maintaining the pointer<-->int mappings + * @xa: The data object maintaining the pointer<-->int mappings * @cmdrsp: Response from the IOVM */ -static void cleanup_scsitaskmgmt_handles(struct idr *idrtable, +static void cleanup_scsitaskmgmt_handles(struct xarray *xa, struct uiscmdrsp *cmdrsp) { - if (cmdrsp->scsitaskmgmt.notify_handle) - idr_remove(idrtable, cmdrsp->scsitaskmgmt.notify_handle); - if (cmdrsp->scsitaskmgmt.notifyresult_handle) - idr_remove(idrtable, cmdrsp->scsitaskmgmt.notifyresult_handle); + xa_erase_irq(xa, cmdrsp->scsitaskmgmt.notify_handle); + xa_erase_irq(xa, cmdrsp->scsitaskmgmt.notifyresult_handle); } /* @@ -269,6 +245,7 @@ static int forward_taskmgmt_command(enum task_mgmt_types tasktype, int notifyresult = 0xffff; wait_queue_head_t notifyevent; int scsicmd_id; + int ret; if (devdata->serverdown || devdata->serverchangingstate) return FAILED; @@ -284,8 +261,14 @@ static int forward_taskmgmt_command(enum task_mgmt_types tasktype, /* issue TASK_MGMT_ABORT_TASK */ cmdrsp->cmdtype = CMD_SCSITASKMGMT_TYPE; - setup_scsitaskmgmt_handles(&devdata->idr, &devdata->privlock, cmdrsp, - ¬ifyevent, ¬ifyresult); + + ret = setup_scsitaskmgmt_handles(&devdata->xa, cmdrsp, + ¬ifyevent, ¬ifyresult); + if (ret) { + dev_dbg(&scsidev->sdev_gendev, + "visorhba: setup_scsitaskmgmt_handles returned %d\n", ret); + return FAILED; + } /* save destination */ cmdrsp->scsitaskmgmt.tasktype = tasktype; @@ -311,14 +294,14 @@ static int forward_taskmgmt_command(enum task_mgmt_types tasktype, dev_dbg(&scsidev->sdev_gendev, "visorhba: taskmgmt type=%d success; result=0x%x\n", tasktype, notifyresult); - cleanup_scsitaskmgmt_handles(&devdata->idr, cmdrsp); + cleanup_scsitaskmgmt_handles(&devdata->xa, cmdrsp); return SUCCESS; err_del_scsipending_ent: dev_dbg(&scsidev->sdev_gendev, "visorhba: taskmgmt type=%d not executed\n", tasktype); del_scsipending_ent(devdata, scsicmd_id); - cleanup_scsitaskmgmt_handles(&devdata->idr, cmdrsp); + cleanup_scsitaskmgmt_handles(&devdata->xa, cmdrsp); return FAILED; } @@ -654,13 +637,13 @@ DEFINE_SHOW_ATTRIBUTE(info_debugfs); * Service Partition returned the result of the task management * command. Wake up anyone waiting for it. */ -static void complete_taskmgmt_command(struct idr *idrtable, +static void complete_taskmgmt_command(struct xarray *xa, struct uiscmdrsp *cmdrsp, int result) { wait_queue_head_t *wq = - idr_find(idrtable, cmdrsp->scsitaskmgmt.notify_handle); + xa_load(xa, cmdrsp->scsitaskmgmt.notify_handle); int *scsi_result_ptr = - idr_find(idrtable, cmdrsp->scsitaskmgmt.notifyresult_handle); + xa_load(xa, cmdrsp->scsitaskmgmt.notifyresult_handle); if (unlikely(!(wq && scsi_result_ptr))) { pr_err("visorhba: no completion context; cmd will time out\n"); return; @@ -708,7 +691,7 @@ static void visorhba_serverdown_complete(struct visorhba_devdata *devdata) break; case CMD_SCSITASKMGMT_TYPE: cmdrsp = pendingdel->sent; - complete_taskmgmt_command(&devdata->idr, cmdrsp, + complete_taskmgmt_command(&devdata->xa, cmdrsp, TASK_MGMT_FAILED); break; default: @@ -905,7 +888,7 @@ static void drain_queue(struct uiscmdrsp *cmdrsp, if (!del_scsipending_ent(devdata, cmdrsp->scsitaskmgmt.handle)) break; - complete_taskmgmt_command(&devdata->idr, cmdrsp, + complete_taskmgmt_command(&devdata->xa, cmdrsp, cmdrsp->scsitaskmgmt.result); } else if (cmdrsp->cmdtype == CMD_NOTIFYGUEST_TYPE) dev_err_once(&devdata->dev->device, @@ -1053,7 +1036,7 @@ static int visorhba_probe(struct visor_device *dev) if (err) goto err_debugfs_info; - idr_init(&devdata->idr); + xa_init(&devdata->xa); devdata->cmdrsp = kmalloc(sizeof(*devdata->cmdrsp), GFP_ATOMIC); visorbus_enable_channel_interrupts(dev); @@ -1096,8 +1079,6 @@ static void visorhba_remove(struct visor_device *dev) scsi_remove_host(scsihost); scsi_host_put(scsihost); - idr_destroy(&devdata->idr); - dev_set_drvdata(&dev->device, NULL); debugfs_remove(devdata->debugfs_info); debugfs_remove_recursive(devdata->debugfs_dir); diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c index 6d202cba8575..426deab22d62 100644 --- a/drivers/staging/unisys/visorinput/visorinput.c +++ b/drivers/staging/unisys/visorinput/visorinput.c @@ -556,7 +556,6 @@ static void handle_locking_key(struct input_dev *visorinput_dev, int keycode, led = LED_NUML; break; default: - led = -1; return; } if (test_bit(led, visorinput_dev->led) != desired_state) { diff --git a/drivers/staging/vc04_services/Makefile b/drivers/staging/vc04_services/Makefile index 7546d70116a0..e21e73ae3cc6 100644 --- a/drivers/staging/vc04_services/Makefile +++ b/drivers/staging/vc04_services/Makefile @@ -12,5 +12,5 @@ obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/ obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-camera/ obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/ -ccflags-y += -I $(srctree)/$(src)/include -D__VCCOREVER__=0x04000000 +ccflags-y += -I $(srctree)/$(src)/include diff --git a/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h b/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h index fefc664eefcf..81db7fb76d6d 100644 --- a/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h +++ b/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h @@ -104,7 +104,7 @@ extern enum vchiq_status vchiq_bulk_receive(unsigned int service, enum vchiq_bulk_mode mode); extern void *vchiq_get_service_userdata(unsigned int service); extern enum vchiq_status vchiq_get_peer_version(unsigned int handle, - short *peer_version); + short *peer_version); extern struct vchiq_header *vchiq_msg_hold(unsigned int handle); #endif /* VCHIQ_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c index 8782ebe0b39a..30d6f1a404ba 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -29,6 +29,8 @@ #define BELL0 0x00 #define BELL2 0x08 +#define ARM_DS_ACTIVE BIT(2) + struct vchiq_2835_state { int inited; struct vchiq_arm_state arm_state; @@ -132,8 +134,9 @@ int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state) *(char **)&g_fragments_base[i * g_fragments_size] = NULL; sema_init(&g_free_fragments_sema, MAX_FRAGMENTS); - if (vchiq_init_state(state, vchiq_slot_zero) != VCHIQ_SUCCESS) - return -EINVAL; + err = vchiq_init_state(state, vchiq_slot_zero); + if (err) + return err; g_regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(g_regs)) @@ -169,25 +172,21 @@ int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state) return 0; } -enum vchiq_status +int vchiq_platform_init_state(struct vchiq_state *state) { - enum vchiq_status status = VCHIQ_SUCCESS; struct vchiq_2835_state *platform_state; state->platform_state = kzalloc(sizeof(*platform_state), GFP_KERNEL); if (!state->platform_state) - return VCHIQ_ERROR; + return -ENOMEM; platform_state = (struct vchiq_2835_state *)state->platform_state; platform_state->inited = 1; - status = vchiq_arm_init_state(state, &platform_state->arm_state); + vchiq_arm_init_state(state, &platform_state->arm_state); - if (status != VCHIQ_SUCCESS) - platform_state->inited = 0; - - return status; + return 0; } struct vchiq_arm_state* @@ -215,7 +214,7 @@ remote_event_signal(struct remote_event *event) writel(0, g_regs + BELL2); /* trigger vc interrupt */ } -enum vchiq_status +int vchiq_prepare_bulk_data(struct vchiq_bulk *bulk, void *offset, void __user *uoffset, int size, int dir) { @@ -227,7 +226,7 @@ vchiq_prepare_bulk_data(struct vchiq_bulk *bulk, void *offset, : PAGELIST_WRITE); if (!pagelistinfo) - return VCHIQ_ERROR; + return -ENOMEM; bulk->data = pagelistinfo->dma_addr; @@ -237,7 +236,7 @@ vchiq_prepare_bulk_data(struct vchiq_bulk *bulk, void *offset, */ bulk->remote_data = pagelistinfo; - return VCHIQ_SUCCESS; + return 0; } void @@ -272,7 +271,7 @@ vchiq_doorbell_irq(int irq, void *dev_id) /* Read (and clear) the doorbell */ status = readl(g_regs + BELL0); - if (status & 0x4) { /* Was the doorbell rung? */ + if (status & ARM_DS_ACTIVE) { /* Was the doorbell rung? */ remote_event_pollall(state); ret = IRQ_HANDLED; } diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index e39897c38e6a..b5aac862a298 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -139,22 +139,18 @@ static const char *const ioctl_names[] = { "CLOSE_DELIVERED" }; -vchiq_static_assert(ARRAY_SIZE(ioctl_names) == - (VCHIQ_IOC_MAX + 1)); +static_assert(ARRAY_SIZE(ioctl_names) == (VCHIQ_IOC_MAX + 1)); static enum vchiq_status vchiq_blocking_bulk_transfer(unsigned int handle, void *data, unsigned int size, enum vchiq_bulk_dir dir); #define VCHIQ_INIT_RETRIES 10 -enum vchiq_status vchiq_initialise(struct vchiq_instance **instance_out) +int vchiq_initialise(struct vchiq_instance **instance_out) { - enum vchiq_status status = VCHIQ_ERROR; struct vchiq_state *state; struct vchiq_instance *instance = NULL; - int i; - - vchiq_log_trace(vchiq_core_log_level, "%s called", __func__); + int i, ret; /* * VideoCore may not be ready due to boot up timing. @@ -170,6 +166,7 @@ enum vchiq_status vchiq_initialise(struct vchiq_instance **instance_out) if (i == VCHIQ_INIT_RETRIES) { vchiq_log_error(vchiq_core_log_level, "%s: videocore not initialized\n", __func__); + ret = -ENOTCONN; goto failed; } else if (i > 0) { vchiq_log_warning(vchiq_core_log_level, @@ -181,6 +178,7 @@ enum vchiq_status vchiq_initialise(struct vchiq_instance **instance_out) if (!instance) { vchiq_log_error(vchiq_core_log_level, "%s: error allocating vchiq instance\n", __func__); + ret = -ENOMEM; goto failed; } @@ -191,48 +189,48 @@ enum vchiq_status vchiq_initialise(struct vchiq_instance **instance_out) *instance_out = instance; - status = VCHIQ_SUCCESS; + ret = 0; failed: vchiq_log_trace(vchiq_core_log_level, - "%s(%p): returning %d", __func__, instance, status); + "%s(%p): returning %d", __func__, instance, ret); - return status; + return ret; } EXPORT_SYMBOL(vchiq_initialise); +static void free_bulk_waiter(struct vchiq_instance *instance) +{ + struct bulk_waiter_node *waiter, *next; + + list_for_each_entry_safe(waiter, next, + &instance->bulk_waiter_list, list) { + list_del(&waiter->list); + vchiq_log_info(vchiq_arm_log_level, + "bulk_waiter - cleaned up %pK for pid %d", + waiter, waiter->pid); + kfree(waiter); + } +} + enum vchiq_status vchiq_shutdown(struct vchiq_instance *instance) { - enum vchiq_status status; + enum vchiq_status status = VCHIQ_SUCCESS; struct vchiq_state *state = instance->state; - vchiq_log_trace(vchiq_core_log_level, - "%s(%p) called", __func__, instance); - if (mutex_lock_killable(&state->mutex)) return VCHIQ_RETRY; /* Remove all services */ - status = vchiq_shutdown_internal(state, instance); + vchiq_shutdown_internal(state, instance); mutex_unlock(&state->mutex); vchiq_log_trace(vchiq_core_log_level, "%s(%p): returning %d", __func__, instance, status); - if (status == VCHIQ_SUCCESS) { - struct bulk_waiter_node *waiter, *next; - - list_for_each_entry_safe(waiter, next, - &instance->bulk_waiter_list, list) { - list_del(&waiter->list); - vchiq_log_info(vchiq_arm_log_level, - "bulk_waiter - cleaned up %pK for pid %d", - waiter, waiter->pid); - kfree(waiter); - } - kfree(instance); - } + free_bulk_waiter(instance); + kfree(instance); return status; } @@ -248,9 +246,6 @@ enum vchiq_status vchiq_connect(struct vchiq_instance *instance) enum vchiq_status status; struct vchiq_state *state = instance->state; - vchiq_log_trace(vchiq_core_log_level, - "%s(%p) called", __func__, instance); - if (mutex_lock_killable(&state->mutex)) { vchiq_log_trace(vchiq_core_log_level, "%s: call to mutex_lock failed", __func__); @@ -272,19 +267,16 @@ failed: } EXPORT_SYMBOL(vchiq_connect); -static enum vchiq_status vchiq_add_service( - struct vchiq_instance *instance, - const struct vchiq_service_params_kernel *params, - unsigned int *phandle) +static enum vchiq_status +vchiq_add_service(struct vchiq_instance *instance, + const struct vchiq_service_params_kernel *params, + unsigned int *phandle) { enum vchiq_status status; struct vchiq_state *state = instance->state; struct vchiq_service *service = NULL; int srvstate; - vchiq_log_trace(vchiq_core_log_level, - "%s(%p) called", __func__, instance); - *phandle = VCHIQ_SERVICE_HANDLE_INVALID; srvstate = vchiq_is_connected(instance) @@ -301,8 +293,9 @@ static enum vchiq_status vchiq_add_service( if (service) { *phandle = service->handle; status = VCHIQ_SUCCESS; - } else + } else { status = VCHIQ_ERROR; + } vchiq_log_trace(vchiq_core_log_level, "%s(%p): returning %d", __func__, instance, status); @@ -310,18 +303,15 @@ static enum vchiq_status vchiq_add_service( return status; } -enum vchiq_status vchiq_open_service( - struct vchiq_instance *instance, - const struct vchiq_service_params_kernel *params, - unsigned int *phandle) +enum vchiq_status +vchiq_open_service(struct vchiq_instance *instance, + const struct vchiq_service_params_kernel *params, + unsigned int *phandle) { enum vchiq_status status = VCHIQ_ERROR; struct vchiq_state *state = instance->state; struct vchiq_service *service = NULL; - vchiq_log_trace(vchiq_core_log_level, - "%s(%p) called", __func__, instance); - *phandle = VCHIQ_SERVICE_HANDLE_INVALID; if (!vchiq_is_connected(instance)) @@ -351,8 +341,8 @@ failed: EXPORT_SYMBOL(vchiq_open_service); enum vchiq_status -vchiq_bulk_transmit(unsigned int handle, const void *data, - unsigned int size, void *userdata, enum vchiq_bulk_mode mode) +vchiq_bulk_transmit(unsigned int handle, const void *data, unsigned int size, + void *userdata, enum vchiq_bulk_mode mode) { enum vchiq_status status; @@ -426,8 +416,8 @@ enum vchiq_status vchiq_bulk_receive(unsigned int handle, void *data, EXPORT_SYMBOL(vchiq_bulk_receive); static enum vchiq_status -vchiq_blocking_bulk_transfer(unsigned int handle, void *data, - unsigned int size, enum vchiq_bulk_dir dir) +vchiq_blocking_bulk_transfer(unsigned int handle, void *data, unsigned int size, + enum vchiq_bulk_dir dir) { struct vchiq_instance *instance; struct vchiq_service *service; @@ -441,7 +431,7 @@ vchiq_blocking_bulk_transfer(unsigned int handle, void *data, instance = service->instance; - unlock_service(service); + vchiq_service_put(service); mutex_lock(&instance->bulk_waiter_list_mutex); list_for_each_entry(waiter, &instance->bulk_waiter_list, list) { @@ -471,7 +461,7 @@ vchiq_blocking_bulk_transfer(unsigned int handle, void *data, } } } else { - waiter = kzalloc(sizeof(struct bulk_waiter_node), GFP_KERNEL); + waiter = kzalloc(sizeof(*waiter), GFP_KERNEL); if (!waiter) { vchiq_log_error(vchiq_core_log_level, "%s - out of memory", __func__); @@ -505,11 +495,6 @@ vchiq_blocking_bulk_transfer(unsigned int handle, void *data, return status; } -/**************************************************************************** - * - * add_completion - * - ***************************************************************************/ static enum vchiq_status add_completion(struct vchiq_instance *instance, enum vchiq_reason reason, @@ -554,7 +539,7 @@ add_completion(struct vchiq_instance *instance, enum vchiq_reason reason, * Take an extra reference, to be held until * this CLOSED notification is delivered. */ - lock_service(user_service->service); + vchiq_service_get(user_service->service); if (instance->use_close_delivered) user_service->close_pending = 1; } @@ -576,12 +561,6 @@ add_completion(struct vchiq_instance *instance, enum vchiq_reason reason, return VCHIQ_SUCCESS; } -/**************************************************************************** - * - * service_callback - * - ***************************************************************************/ - static enum vchiq_status service_callback(enum vchiq_reason reason, struct vchiq_header *header, unsigned int handle, void *bulk_userdata) @@ -602,7 +581,9 @@ service_callback(enum vchiq_reason reason, struct vchiq_header *header, DEBUG_TRACE(SERVICE_CALLBACK_LINE); service = handle_to_service(handle); - BUG_ON(!service); + if (WARN_ON(!service)) + return VCHIQ_SUCCESS; + user_service = (struct user_service *)service->base.userdata; instance = user_service->instance; @@ -691,22 +672,12 @@ service_callback(enum vchiq_reason reason, struct vchiq_header *header, bulk_userdata); } -/**************************************************************************** - * - * user_service_free - * - ***************************************************************************/ static void user_service_free(void *userdata) { kfree(userdata); } -/**************************************************************************** - * - * close_delivered - * - ***************************************************************************/ static void close_delivered(struct user_service *user_service) { vchiq_log_info(vchiq_arm_log_level, @@ -715,7 +686,7 @@ static void close_delivered(struct user_service *user_service) if (user_service->close_pending) { /* Allow the underlying service to be culled */ - unlock_service(user_service->service); + vchiq_service_put(user_service->service); /* Wake the user-thread blocked in close_ or remove_service */ complete(&user_service->close_event); @@ -769,14 +740,8 @@ static ssize_t vchiq_ioc_copy_element_data(void *context, void *dest, return maxsize; } -/************************************************************************** - * - * vchiq_ioc_queue_message - * - **************************************************************************/ static int -vchiq_ioc_queue_message(unsigned int handle, - struct vchiq_element *elements, +vchiq_ioc_queue_message(unsigned int handle, struct vchiq_element *elements, unsigned long count) { struct vchiq_io_copy_callback_context context; @@ -911,15 +876,18 @@ static int vchiq_ioc_dequeue_message(struct vchiq_instance *instance, break; } spin_lock(&msg_queue_spinlock); - } while (user_service->msg_remove == - user_service->msg_insert); + } while (user_service->msg_remove == user_service->msg_insert); if (ret) goto out; } - BUG_ON((int)(user_service->msg_insert - - user_service->msg_remove) < 0); + if (WARN_ON_ONCE((int)(user_service->msg_insert - + user_service->msg_remove) < 0)) { + spin_unlock(&msg_queue_spinlock); + ret = -EINVAL; + goto out; + } header = user_service->msg_queue[user_service->msg_remove & (MSG_QUEUE_SIZE - 1)]; @@ -935,8 +903,9 @@ static int vchiq_ioc_dequeue_message(struct vchiq_instance *instance, header->data, header->size) == 0)) { ret = header->size; vchiq_release_message(service->handle, header); - } else + } else { ret = -EFAULT; + } } else { vchiq_log_error(vchiq_arm_log_level, "header %pK: bufsize %x < size %x", @@ -946,7 +915,7 @@ static int vchiq_ioc_dequeue_message(struct vchiq_instance *instance, } DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); out: - unlock_service(service); + vchiq_service_put(service); return ret; } @@ -967,8 +936,7 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance, return -EINVAL; if (args->mode == VCHIQ_BULK_MODE_BLOCKING) { - waiter = kzalloc(sizeof(struct bulk_waiter_node), - GFP_KERNEL); + waiter = kzalloc(sizeof(*waiter), GFP_KERNEL); if (!waiter) { ret = -ENOMEM; goto out; @@ -1033,7 +1001,7 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance, ret = put_user(mode_waiting, mode); } out: - unlock_service(service); + vchiq_service_put(service); if (ret) return ret; else if (status == VCHIQ_ERROR) @@ -1051,6 +1019,7 @@ static inline int vchiq_get_user_ptr(void __user **buf, void __user *ubuf, int i if (in_compat_syscall()) { compat_uptr_t ptr32; compat_uptr_t __user *uptr = ubuf; + ret = get_user(ptr32, uptr + index); if (ret) return ret; @@ -1058,6 +1027,7 @@ static inline int vchiq_get_user_ptr(void __user **buf, void __user *ubuf, int i *buf = compat_ptr(ptr32); } else { uintptr_t ptr, __user *uptr = ubuf; + ret = get_user(ptr, uptr + index); if (ret) @@ -1117,8 +1087,7 @@ static int vchiq_ioc_await_completion(struct vchiq_instance *instance, mutex_lock(&instance->completion_mutex); DEBUG_TRACE(AWAIT_COMPLETION_LINE); - while ((instance->completion_remove == - instance->completion_insert) + while ((instance->completion_remove == instance->completion_insert) && !instance->closing) { int rc; @@ -1212,7 +1181,7 @@ static int vchiq_ioc_await_completion(struct vchiq_instance *instance, if ((completion->reason == VCHIQ_SERVICE_CLOSED) && !instance->use_close_delivered) - unlock_service(service); + vchiq_service_put(service); /* * FIXME: address space mismatch, does bulk_userdata @@ -1248,11 +1217,6 @@ out: return ret; } -/**************************************************************************** - * - * vchiq_ioctl - * - ***************************************************************************/ static long vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -1279,7 +1243,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) while ((service = next_service_by_instance(instance->state, instance, &i))) { status = vchiq_remove_service(service->handle); - unlock_service(service); + vchiq_service_put(service); if (status != VCHIQ_SUCCESS) break; } @@ -1379,24 +1343,24 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) service = find_service_for_instance(instance, handle); if (service) { - status = (cmd == VCHIQ_IOC_USE_SERVICE) ? + ret = (cmd == VCHIQ_IOC_USE_SERVICE) ? vchiq_use_service_internal(service) : vchiq_release_service_internal(service); - if (status != VCHIQ_SUCCESS) { + if (ret) { vchiq_log_error(vchiq_susp_log_level, - "%s: cmd %s returned error %d for service %c%c%c%c:%03d", + "%s: cmd %s returned error %ld for service %c%c%c%c:%03d", __func__, (cmd == VCHIQ_IOC_USE_SERVICE) ? "VCHIQ_IOC_USE_SERVICE" : "VCHIQ_IOC_RELEASE_SERVICE", - status, + ret, VCHIQ_FOURCC_AS_4CHARS( service->base.fourcc), service->client_id); - ret = -EINVAL; } - } else + } else { ret = -EINVAL; + } } break; case VCHIQ_IOC_QUEUE_MESSAGE: { @@ -1512,8 +1476,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; } - status = vchiq_set_service_option( - args.handle, args.option, args.value); + ret = vchiq_set_service_option(args.handle, args.option, + args.value); } break; case VCHIQ_IOC_LIB_VERSION: { @@ -1533,8 +1497,9 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct user_service *user_service = (struct user_service *)service->base.userdata; close_delivered(user_service); - } else + } else { ret = -EINVAL; + } } break; default: @@ -1543,7 +1508,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } if (service) - unlock_service(service); + vchiq_service_put(service); if (ret == 0) { if (status == VCHIQ_ERROR) @@ -1594,10 +1559,8 @@ struct vchiq_create_service32 { _IOWR(VCHIQ_IOC_MAGIC, 2, struct vchiq_create_service32) static long -vchiq_compat_ioctl_create_service( - struct file *file, - unsigned int cmd, - struct vchiq_create_service32 __user *ptrargs32) +vchiq_compat_ioctl_create_service(struct file *file, unsigned int cmd, + struct vchiq_create_service32 __user *ptrargs32) { struct vchiq_create_service args; struct vchiq_create_service32 args32; @@ -1678,7 +1641,7 @@ vchiq_compat_ioctl_queue_message(struct file *file, if (copy_from_user(&element32, args.elements, sizeof(element32))) { - unlock_service(service); + vchiq_service_put(service); return -EFAULT; } @@ -1692,7 +1655,7 @@ vchiq_compat_ioctl_queue_message(struct file *file, } else { ret = -EINVAL; } - unlock_service(service); + vchiq_service_put(service); return ret; } @@ -1834,6 +1797,7 @@ static long vchiq_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = compat_ptr(arg); + switch (cmd) { case VCHIQ_IOC_CREATE_SERVICE32: return vchiq_compat_ioctl_create_service(file, cmd, argp); @@ -1927,7 +1891,7 @@ static int vchiq_release(struct inode *inode, struct file *file) complete(&user_service->remove_event); vchiq_terminate_service_internal(service); - unlock_service(service); + vchiq_service_put(service); } /* ...and wait for them to die */ @@ -1937,7 +1901,10 @@ static int vchiq_release(struct inode *inode, struct file *file) wait_for_completion(&service->remove_event); - BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE); + if (WARN_ON(service->srvstate != VCHIQ_SRVSTATE_FREE)) { + vchiq_service_put(service); + break; + } spin_lock(&msg_queue_spinlock); @@ -1956,12 +1923,11 @@ static int vchiq_release(struct inode *inode, struct file *file) spin_unlock(&msg_queue_spinlock); - unlock_service(service); + vchiq_service_put(service); } /* Release any closed services */ - while (instance->completion_remove != - instance->completion_insert) { + while (instance->completion_remove != instance->completion_insert) { struct vchiq_completion_data_kernel *completion; struct vchiq_service *service; @@ -1975,7 +1941,7 @@ static int vchiq_release(struct inode *inode, struct file *file) /* Wake any blocked user-thread */ if (instance->use_close_delivered) complete(&user_service->close_event); - unlock_service(service); + vchiq_service_put(service); } instance->completion_remove++; } @@ -1983,18 +1949,7 @@ static int vchiq_release(struct inode *inode, struct file *file) /* Release the PEER service count. */ vchiq_release_internal(instance->state, NULL); - { - struct bulk_waiter_node *waiter, *next; - - list_for_each_entry_safe(waiter, next, - &instance->bulk_waiter_list, list) { - list_del(&waiter->list); - vchiq_log_info(vchiq_arm_log_level, - "bulk_waiter - cleaned up %pK for pid %d", - waiter, waiter->pid); - kfree(waiter); - } - } + free_bulk_waiter(instance); vchiq_debugfs_remove_instance(instance); @@ -2005,12 +1960,6 @@ out: return ret; } -/**************************************************************************** - * - * vchiq_dump - * - ***************************************************************************/ - int vchiq_dump(void *dump_context, const char *str, int len) { struct dump_context *context = (struct dump_context *)dump_context; @@ -2052,12 +2001,6 @@ int vchiq_dump(void *dump_context, const char *str, int len) return 0; } -/**************************************************************************** - * - * vchiq_dump_platform_instance_state - * - ***************************************************************************/ - int vchiq_dump_platform_instances(void *dump_context) { struct vchiq_state *state = vchiq_get_state(); @@ -2120,12 +2063,6 @@ int vchiq_dump_platform_instances(void *dump_context) return 0; } -/**************************************************************************** - * - * vchiq_dump_platform_service_state - * - ***************************************************************************/ - int vchiq_dump_platform_service_state(void *dump_context, struct vchiq_service *service) { @@ -2151,15 +2088,8 @@ int vchiq_dump_platform_service_state(void *dump_context, return vchiq_dump(dump_context, buf, len + 1); } -/**************************************************************************** - * - * vchiq_read - * - ***************************************************************************/ - static ssize_t -vchiq_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) +vchiq_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct dump_context context; int err; @@ -2183,10 +2113,10 @@ vchiq_get_state(void) { if (!g_state.remote) - printk(KERN_ERR "%s: g_state.remote == NULL\n", __func__); + pr_err("%s: g_state.remote == NULL\n", __func__); else if (g_state.remote->initialised != 1) - printk(KERN_NOTICE "%s: g_state.remote->initialised != 1 (%d)\n", - __func__, g_state.remote->initialised); + pr_notice("%s: g_state.remote->initialised != 1 (%d)\n", + __func__, g_state.remote->initialised); return (g_state.remote && (g_state.remote->initialised == 1)) ? &g_state : NULL; @@ -2210,9 +2140,8 @@ vchiq_fops = { static enum vchiq_status vchiq_keepalive_vchiq_callback(enum vchiq_reason reason, - struct vchiq_header *header, - unsigned int service_user, - void *bulk_user) + struct vchiq_header *header, + unsigned int service_user, void *bulk_user) { vchiq_log_error(vchiq_susp_log_level, "%s callback reason %d", __func__, reason); @@ -2228,6 +2157,7 @@ vchiq_keepalive_thread_func(void *v) enum vchiq_status status; struct vchiq_instance *instance; unsigned int ka_handle; + int ret; struct vchiq_service_params_kernel params = { .fourcc = VCHIQ_MAKE_FOURCC('K', 'E', 'E', 'P'), @@ -2236,10 +2166,10 @@ vchiq_keepalive_thread_func(void *v) .version_min = KEEPALIVE_VER_MIN }; - status = vchiq_initialise(&instance); - if (status != VCHIQ_SUCCESS) { + ret = vchiq_initialise(&instance); + if (ret) { vchiq_log_error(vchiq_susp_log_level, - "%s vchiq_initialise failed %d", __func__, status); + "%s vchiq_initialise failed %d", __func__, ret); goto exit; } @@ -2303,7 +2233,7 @@ exit: return 0; } -enum vchiq_status +void vchiq_arm_init_state(struct vchiq_state *state, struct vchiq_arm_state *arm_state) { @@ -2319,26 +2249,23 @@ vchiq_arm_init_state(struct vchiq_state *state, arm_state->first_connect = 0; } - return VCHIQ_SUCCESS; } -enum vchiq_status +int vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service, enum USE_TYPE_E use_type) { struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); - enum vchiq_status ret = VCHIQ_SUCCESS; + int ret = 0; char entity[16]; int *entity_uc; int local_uc; if (!arm_state) { - ret = VCHIQ_ERROR; + ret = -EINVAL; goto out; } - vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); - if (use_type == USE_TYPE_VCHIQ) { sprintf(entity, "VCHIQ: "); entity_uc = &arm_state->peer_use_count; @@ -2349,7 +2276,7 @@ vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service, entity_uc = &service->service_use_count; } else { vchiq_log_error(vchiq_susp_log_level, "%s null service ptr", __func__); - ret = VCHIQ_ERROR; + ret = -EINVAL; goto out; } @@ -2363,7 +2290,7 @@ vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service, write_unlock_bh(&arm_state->susp_res_lock); - if (ret == VCHIQ_SUCCESS) { + if (!ret) { enum vchiq_status status = VCHIQ_SUCCESS; long ack_cnt = atomic_xchg(&arm_state->ka_use_ack_count, 0); @@ -2383,21 +2310,19 @@ out: return ret; } -enum vchiq_status +int vchiq_release_internal(struct vchiq_state *state, struct vchiq_service *service) { struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); - enum vchiq_status ret = VCHIQ_SUCCESS; + int ret = 0; char entity[16]; int *entity_uc; if (!arm_state) { - ret = VCHIQ_ERROR; + ret = -EINVAL; goto out; } - vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); - if (service) { sprintf(entity, "%c%c%c%c:%03d", VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), @@ -2413,7 +2338,7 @@ vchiq_release_internal(struct vchiq_state *state, struct vchiq_service *service) /* Don't use BUG_ON - don't allow user thread to crash kernel */ WARN_ON(!arm_state->videocore_use_count); WARN_ON(!(*entity_uc)); - ret = VCHIQ_ERROR; + ret = -EINVAL; goto unlock; } --arm_state->videocore_use_count; @@ -2437,7 +2362,6 @@ vchiq_on_remote_use(struct vchiq_state *state) { struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); - vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); atomic_inc(&arm_state->ka_use_count); complete(&arm_state->ka_evt); } @@ -2447,18 +2371,17 @@ vchiq_on_remote_release(struct vchiq_state *state) { struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); - vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); atomic_inc(&arm_state->ka_release_count); complete(&arm_state->ka_evt); } -enum vchiq_status +int vchiq_use_service_internal(struct vchiq_service *service) { return vchiq_use_internal(service->state, service, USE_TYPE_SERVICE); } -enum vchiq_status +int vchiq_release_service_internal(struct vchiq_service *service) { return vchiq_release_internal(service->state, service); @@ -2521,7 +2444,7 @@ vchiq_use_service(unsigned int handle) if (service) { ret = vchiq_use_internal(service->state, service, USE_TYPE_SERVICE); - unlock_service(service); + vchiq_service_put(service); } return ret; } @@ -2535,7 +2458,7 @@ vchiq_release_service(unsigned int handle) if (service) { ret = vchiq_release_internal(service->state, service); - unlock_service(service); + vchiq_service_put(service); } return ret; } @@ -2634,8 +2557,6 @@ vchiq_check_service(struct vchiq_service *service) if (!service || !service->state) goto out; - vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); - arm_state = vchiq_platform_get_arm_state(service->state); read_lock_bh(&arm_state->susp_res_lock); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h index 24c331c94354..c7d2cf1f2e68 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h @@ -67,7 +67,7 @@ int vchiq_platform_init(struct platform_device *pdev, extern struct vchiq_state * vchiq_get_state(void); -extern enum vchiq_status +extern void vchiq_arm_init_state(struct vchiq_state *state, struct vchiq_arm_state *arm_state); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.c index 3023fa9fdc64..0ee96d1d0481 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.c @@ -52,6 +52,7 @@ void vchiq_add_connected_callback(VCHIQ_CONNECTED_CALLBACK_T callback) } mutex_unlock(&g_connected_mutex); } +EXPORT_SYMBOL(vchiq_add_connected_callback); /* * This function is called by the vchiq stack once it has been connected to @@ -73,4 +74,3 @@ void vchiq_call_connected_callbacks(void) g_connected = 1; mutex_unlock(&g_connected_mutex); } -EXPORT_SYMBOL(vchiq_add_connected_callback); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.h index ec5d2b716e7a..95c18670e839 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.h @@ -4,16 +4,8 @@ #ifndef VCHIQ_CONNECTED_H #define VCHIQ_CONNECTED_H -/* ---- Include Files ----------------------------------------------------- */ - -/* ---- Constants and Types ---------------------------------------------- */ - typedef void (*VCHIQ_CONNECTED_CALLBACK_T)(void); -/* ---- Variable Externs ------------------------------------------------- */ - -/* ---- Function Prototypes ---------------------------------------------- */ - void vchiq_add_connected_callback(VCHIQ_CONNECTED_CALLBACK_T callback); void vchiq_call_connected_callbacks(void); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c index 517a8c9b41ed..4f43e4213bfe 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -17,6 +17,75 @@ #define VCHIQ_SLOT_HANDLER_STACK 8192 +#define VCHIQ_MSG_PADDING 0 /* - */ +#define VCHIQ_MSG_CONNECT 1 /* - */ +#define VCHIQ_MSG_OPEN 2 /* + (srcport, -), fourcc, client_id */ +#define VCHIQ_MSG_OPENACK 3 /* + (srcport, dstport) */ +#define VCHIQ_MSG_CLOSE 4 /* + (srcport, dstport) */ +#define VCHIQ_MSG_DATA 5 /* + (srcport, dstport) */ +#define VCHIQ_MSG_BULK_RX 6 /* + (srcport, dstport), data, size */ +#define VCHIQ_MSG_BULK_TX 7 /* + (srcport, dstport), data, size */ +#define VCHIQ_MSG_BULK_RX_DONE 8 /* + (srcport, dstport), actual */ +#define VCHIQ_MSG_BULK_TX_DONE 9 /* + (srcport, dstport), actual */ +#define VCHIQ_MSG_PAUSE 10 /* - */ +#define VCHIQ_MSG_RESUME 11 /* - */ +#define VCHIQ_MSG_REMOTE_USE 12 /* - */ +#define VCHIQ_MSG_REMOTE_RELEASE 13 /* - */ +#define VCHIQ_MSG_REMOTE_USE_ACTIVE 14 /* - */ + +#define TYPE_SHIFT 24 + +#define VCHIQ_PORT_MAX (VCHIQ_MAX_SERVICES - 1) +#define VCHIQ_PORT_FREE 0x1000 +#define VCHIQ_PORT_IS_VALID(port) ((port) < VCHIQ_PORT_FREE) +#define VCHIQ_MAKE_MSG(type, srcport, dstport) \ + (((type) << TYPE_SHIFT) | ((srcport) << 12) | ((dstport) << 0)) +#define VCHIQ_MSG_TYPE(msgid) ((unsigned int)(msgid) >> TYPE_SHIFT) +#define VCHIQ_MSG_SRCPORT(msgid) \ + (unsigned short)(((unsigned int)(msgid) >> 12) & 0xfff) +#define VCHIQ_MSG_DSTPORT(msgid) \ + ((unsigned short)(msgid) & 0xfff) + +#define MAKE_CONNECT (VCHIQ_MSG_CONNECT << TYPE_SHIFT) +#define MAKE_OPEN(srcport) \ + ((VCHIQ_MSG_OPEN << TYPE_SHIFT) | ((srcport) << 12)) +#define MAKE_OPENACK(srcport, dstport) \ + ((VCHIQ_MSG_OPENACK << TYPE_SHIFT) | ((srcport) << 12) | ((dstport) << 0)) +#define MAKE_CLOSE(srcport, dstport) \ + ((VCHIQ_MSG_CLOSE << TYPE_SHIFT) | ((srcport) << 12) | ((dstport) << 0)) +#define MAKE_DATA(srcport, dstport) \ + ((VCHIQ_MSG_DATA << TYPE_SHIFT) | ((srcport) << 12) | ((dstport) << 0)) +#define MAKE_PAUSE (VCHIQ_MSG_PAUSE << TYPE_SHIFT) +#define MAKE_RESUME (VCHIQ_MSG_RESUME << TYPE_SHIFT) +#define MAKE_REMOTE_USE (VCHIQ_MSG_REMOTE_USE << TYPE_SHIFT) +#define MAKE_REMOTE_USE_ACTIVE (VCHIQ_MSG_REMOTE_USE_ACTIVE << TYPE_SHIFT) + +/* Ensure the fields are wide enough */ +static_assert(VCHIQ_MSG_SRCPORT(VCHIQ_MAKE_MSG(0, 0, VCHIQ_PORT_MAX)) + == 0); +static_assert(VCHIQ_MSG_TYPE(VCHIQ_MAKE_MSG(0, VCHIQ_PORT_MAX, 0)) == 0); +static_assert((unsigned int)VCHIQ_PORT_MAX < + (unsigned int)VCHIQ_PORT_FREE); + +#define VCHIQ_MSGID_PADDING VCHIQ_MAKE_MSG(VCHIQ_MSG_PADDING, 0, 0) +#define VCHIQ_MSGID_CLAIMED 0x40000000 + +#define VCHIQ_FOURCC_INVALID 0x00000000 +#define VCHIQ_FOURCC_IS_LEGAL(fourcc) ((fourcc) != VCHIQ_FOURCC_INVALID) + +#define VCHIQ_BULK_ACTUAL_ABORTED -1 + +#if VCHIQ_ENABLE_STATS +#define VCHIQ_STATS_INC(state, stat) (state->stats. stat++) +#define VCHIQ_SERVICE_STATS_INC(service, stat) (service->stats. stat++) +#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) \ + (service->stats. stat += addend) +#else +#define VCHIQ_STATS_INC(state, stat) ((void)0) +#define VCHIQ_SERVICE_STATS_INC(service, stat) ((void)0) +#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) ((void)0) +#endif + #define HANDLE_STATE_SHIFT 12 #define SLOT_INFO_FROM_INDEX(state, index) (state->slot_info + (index)) @@ -31,13 +100,19 @@ #define SLOT_QUEUE_INDEX_FROM_POS_MASKED(pos) \ (SLOT_QUEUE_INDEX_FROM_POS(pos) & VCHIQ_SLOT_QUEUE_MASK) -#define BULK_INDEX(x) (x & (VCHIQ_NUM_SERVICE_BULKS - 1)) +#define BULK_INDEX(x) ((x) & (VCHIQ_NUM_SERVICE_BULKS - 1)) #define SRVTRACE_LEVEL(srv) \ (((srv) && (srv)->trace) ? VCHIQ_LOG_TRACE : vchiq_core_msg_log_level) #define SRVTRACE_ENABLED(srv, lev) \ (((srv) && (srv)->trace) || (vchiq_core_msg_log_level >= (lev))) +#define NO_CLOSE_RECVD 0 +#define CLOSE_RECVD 1 + +#define NO_RETRY_POLL 0 +#define RETRY_POLL 1 + struct vchiq_open_payload { int fourcc; int client_id; @@ -55,13 +130,28 @@ enum { QMFLAGS_NO_MUTEX_UNLOCK = BIT(2) }; +enum { + VCHIQ_POLL_TERMINATE, + VCHIQ_POLL_REMOVE, + VCHIQ_POLL_TXNOTIFY, + VCHIQ_POLL_RXNOTIFY, + VCHIQ_POLL_COUNT +}; + /* we require this for consistency between endpoints */ -vchiq_static_assert(sizeof(struct vchiq_header) == 8); -vchiq_static_assert(IS_POW2(sizeof(struct vchiq_header))); -vchiq_static_assert(IS_POW2(VCHIQ_NUM_CURRENT_BULKS)); -vchiq_static_assert(IS_POW2(VCHIQ_NUM_SERVICE_BULKS)); -vchiq_static_assert(IS_POW2(VCHIQ_MAX_SERVICES)); -vchiq_static_assert(VCHIQ_VERSION >= VCHIQ_VERSION_MIN); +static_assert(sizeof(struct vchiq_header) == 8); +static_assert(VCHIQ_VERSION >= VCHIQ_VERSION_MIN); + +static inline void check_sizes(void) +{ + BUILD_BUG_ON_NOT_POWER_OF_2(VCHIQ_SLOT_SIZE); + BUILD_BUG_ON_NOT_POWER_OF_2(VCHIQ_MAX_SLOTS); + BUILD_BUG_ON_NOT_POWER_OF_2(VCHIQ_MAX_SLOTS_PER_SIDE); + BUILD_BUG_ON_NOT_POWER_OF_2(sizeof(struct vchiq_header)); + BUILD_BUG_ON_NOT_POWER_OF_2(VCHIQ_NUM_CURRENT_BULKS); + BUILD_BUG_ON_NOT_POWER_OF_2(VCHIQ_NUM_SERVICE_BULKS); + BUILD_BUG_ON_NOT_POWER_OF_2(VCHIQ_MAX_SERVICES); +} /* Run time control of log level, based on KERN_XXX level. */ int vchiq_core_log_level = VCHIQ_LOG_DEFAULT; @@ -243,7 +333,8 @@ __next_service_by_instance(struct vchiq_state *state, while (idx < state->unused_service) { struct vchiq_service *srv; - srv = rcu_dereference(state->services[idx++]); + srv = rcu_dereference(state->services[idx]); + idx++; if (srv && srv->srvstate != VCHIQ_SRVSTATE_FREE && srv->instance == instance) { service = srv; @@ -277,7 +368,7 @@ next_service_by_instance(struct vchiq_state *state, } void -lock_service(struct vchiq_service *service) +vchiq_service_get(struct vchiq_service *service) { if (!service) { WARN(1, "%s service is NULL\n", __func__); @@ -300,7 +391,7 @@ static void service_release(struct kref *kref) } void -unlock_service(struct vchiq_service *service) +vchiq_service_put(struct vchiq_service *service) { if (!service) { WARN(1, "%s: service is NULL\n", __func__); @@ -626,6 +717,68 @@ reserve_space(struct vchiq_state *state, size_t space, int is_blocking) (tx_pos & VCHIQ_SLOT_MASK)); } +static void +process_free_data_message(struct vchiq_state *state, BITSET_T *service_found, + struct vchiq_header *header) +{ + int msgid = header->msgid; + int port = VCHIQ_MSG_SRCPORT(msgid); + struct vchiq_service_quota *quota = &state->service_quotas[port]; + int count; + + spin_lock("a_spinlock); + count = quota->message_use_count; + if (count > 0) + quota->message_use_count = count - 1; + spin_unlock("a_spinlock); + + if (count == quota->message_quota) { + /* + * Signal the service that it + * has dropped below its quota + */ + complete("a->quota_event); + } else if (count == 0) { + vchiq_log_error(vchiq_core_log_level, + "service %d message_use_count=%d (header %pK, msgid %x, header->msgid %x, header->size %x)", + port, + quota->message_use_count, + header, msgid, header->msgid, + header->size); + WARN(1, "invalid message use count\n"); + } + if (!BITSET_IS_SET(service_found, port)) { + /* Set the found bit for this service */ + BITSET_SET(service_found, port); + + spin_lock("a_spinlock); + count = quota->slot_use_count; + if (count > 0) + quota->slot_use_count = count - 1; + spin_unlock("a_spinlock); + + if (count > 0) { + /* + * Signal the service in case + * it has dropped below its quota + */ + complete("a->quota_event); + vchiq_log_trace(vchiq_core_log_level, + "%d: pfq:%d %x@%pK - slot_use->%d", + state->id, port, + header->size, header, + count - 1); + } else { + vchiq_log_error(vchiq_core_log_level, + "service %d slot_use_count=%d (header %pK, msgid %x, header->msgid %x, header->size %x)", + port, count, header, + msgid, header->msgid, + header->size); + WARN(1, "bad slot use count\n"); + } + } +} + /* Called by the recycle thread. */ static void process_free_queue(struct vchiq_state *state, BITSET_T *service_found, @@ -649,11 +802,12 @@ process_free_queue(struct vchiq_state *state, BITSET_T *service_found, while (slot_queue_available != local->slot_queue_recycle) { unsigned int pos; - int slot_index = local->slot_queue[slot_queue_available++ & + int slot_index = local->slot_queue[slot_queue_available & VCHIQ_SLOT_QUEUE_MASK]; char *data = (char *)SLOT_DATA_FROM_INDEX(state, slot_index); int data_found = 0; + slot_queue_available++; /* * Beware of the address dependency - data is calculated * using an index written by the other side. @@ -675,67 +829,8 @@ process_free_queue(struct vchiq_state *state, BITSET_T *service_found, int msgid = header->msgid; if (VCHIQ_MSG_TYPE(msgid) == VCHIQ_MSG_DATA) { - int port = VCHIQ_MSG_SRCPORT(msgid); - struct vchiq_service_quota *quota = - &state->service_quotas[port]; - int count; - - spin_lock("a_spinlock); - count = quota->message_use_count; - if (count > 0) - quota->message_use_count = - count - 1; - spin_unlock("a_spinlock); - - if (count == quota->message_quota) - /* - * Signal the service that it - * has dropped below its quota - */ - complete("a->quota_event); - else if (count == 0) { - vchiq_log_error(vchiq_core_log_level, - "service %d message_use_count=%d (header %pK, msgid %x, header->msgid %x, header->size %x)", - port, - quota->message_use_count, - header, msgid, header->msgid, - header->size); - WARN(1, "invalid message use count\n"); - } - if (!BITSET_IS_SET(service_found, port)) { - /* Set the found bit for this service */ - BITSET_SET(service_found, port); - - spin_lock("a_spinlock); - count = quota->slot_use_count; - if (count > 0) - quota->slot_use_count = - count - 1; - spin_unlock("a_spinlock); - - if (count > 0) { - /* - * Signal the service in case - * it has dropped below its quota - */ - complete("a->quota_event); - vchiq_log_trace( - vchiq_core_log_level, - "%d: pfq:%d %x@%pK - slot_use->%d", - state->id, port, - header->size, header, - count - 1); - } else { - vchiq_log_error( - vchiq_core_log_level, - "service %d slot_use_count=%d (header %pK, msgid %x, header->msgid %x, header->size %x)", - port, count, header, - msgid, header->msgid, - header->size); - WARN(1, "bad slot use count\n"); - } - } - + process_free_data_message(state, service_found, + header); data_found = 1; } @@ -755,8 +850,7 @@ process_free_queue(struct vchiq_state *state, BITSET_T *service_found, spin_lock("a_spinlock); count = state->data_use_count; if (count > 0) - state->data_use_count = - count - 1; + state->data_use_count = count - 1; spin_unlock("a_spinlock); if (count == state->data_quota) complete(&state->data_quota_event); @@ -834,7 +928,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service, stride = calc_stride(size); - WARN_ON(!(stride <= VCHIQ_SLOT_SIZE)); + WARN_ON(stride > VCHIQ_SLOT_SIZE); if (!(flags & QMFLAGS_NO_MUTEX_LOCK) && mutex_lock_killable(&state->slot_mutex)) @@ -897,8 +991,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service, while ((quota->message_use_count == quota->message_quota) || ((tx_end_index != quota->previous_tx_index) && - (quota->slot_use_count == - quota->slot_quota))) { + (quota->slot_use_count == quota->slot_quota))) { spin_unlock("a_spinlock); vchiq_log_trace(vchiq_core_log_level, "%d: qm:%d %s,%zx - quota stall (msg %d, slot %d)", @@ -1175,8 +1268,6 @@ static void release_slot(struct vchiq_state *state, struct vchiq_slot_info *slot_info, struct vchiq_header *header, struct vchiq_service *service) { - int release_count; - mutex_lock(&state->recycle_mutex); if (header) { @@ -1192,10 +1283,9 @@ release_slot(struct vchiq_state *state, struct vchiq_slot_info *slot_info, header->msgid = msgid & ~VCHIQ_MSGID_CLAIMED; } - release_count = slot_info->release_count; - slot_info->release_count = ++release_count; + slot_info->release_count++; - if (release_count == slot_info->use_count) { + if (slot_info->release_count == slot_info->use_count) { int slot_queue_recycle; /* Add to the freed queue */ @@ -1226,6 +1316,22 @@ release_slot(struct vchiq_state *state, struct vchiq_slot_info *slot_info, mutex_unlock(&state->recycle_mutex); } +static inline enum vchiq_reason +get_bulk_reason(struct vchiq_bulk *bulk) +{ + if (bulk->dir == VCHIQ_BULK_TRANSMIT) { + if (bulk->actual == VCHIQ_BULK_ACTUAL_ABORTED) + return VCHIQ_BULK_TRANSMIT_ABORTED; + + return VCHIQ_BULK_TRANSMIT_DONE; + } + + if (bulk->actual == VCHIQ_BULK_ACTUAL_ABORTED) + return VCHIQ_BULK_RECEIVE_ABORTED; + + return VCHIQ_BULK_RECEIVE_DONE; +} + /* Called by the slot handler - don't hold the bulk mutex */ static enum vchiq_status notify_bulks(struct vchiq_service *service, struct vchiq_bulk_queue *queue, @@ -1241,69 +1347,58 @@ notify_bulks(struct vchiq_service *service, struct vchiq_bulk_queue *queue, queue->remote_notify = queue->process; - if (status == VCHIQ_SUCCESS) { - while (queue->remove != queue->remote_notify) { - struct vchiq_bulk *bulk = - &queue->bulks[BULK_INDEX(queue->remove)]; + while (queue->remove != queue->remote_notify) { + struct vchiq_bulk *bulk = + &queue->bulks[BULK_INDEX(queue->remove)]; - /* - * Only generate callbacks for non-dummy bulk - * requests, and non-terminated services - */ - if (bulk->data && service->instance) { - if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED) { - if (bulk->dir == VCHIQ_BULK_TRANSMIT) { - VCHIQ_SERVICE_STATS_INC(service, - bulk_tx_count); - VCHIQ_SERVICE_STATS_ADD(service, - bulk_tx_bytes, - bulk->actual); - } else { - VCHIQ_SERVICE_STATS_INC(service, - bulk_rx_count); - VCHIQ_SERVICE_STATS_ADD(service, - bulk_rx_bytes, - bulk->actual); - } + /* + * Only generate callbacks for non-dummy bulk + * requests, and non-terminated services + */ + if (bulk->data && service->instance) { + if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED) { + if (bulk->dir == VCHIQ_BULK_TRANSMIT) { + VCHIQ_SERVICE_STATS_INC(service, + bulk_tx_count); + VCHIQ_SERVICE_STATS_ADD(service, + bulk_tx_bytes, + bulk->actual); } else { VCHIQ_SERVICE_STATS_INC(service, - bulk_aborted_count); + bulk_rx_count); + VCHIQ_SERVICE_STATS_ADD(service, + bulk_rx_bytes, + bulk->actual); } - if (bulk->mode == VCHIQ_BULK_MODE_BLOCKING) { - struct bulk_waiter *waiter; - - spin_lock(&bulk_waiter_spinlock); - waiter = bulk->userdata; - if (waiter) { - waiter->actual = bulk->actual; - complete(&waiter->event); - } - spin_unlock(&bulk_waiter_spinlock); - } else if (bulk->mode == - VCHIQ_BULK_MODE_CALLBACK) { - enum vchiq_reason reason = (bulk->dir == - VCHIQ_BULK_TRANSMIT) ? - ((bulk->actual == - VCHIQ_BULK_ACTUAL_ABORTED) ? - VCHIQ_BULK_TRANSMIT_ABORTED : - VCHIQ_BULK_TRANSMIT_DONE) : - ((bulk->actual == - VCHIQ_BULK_ACTUAL_ABORTED) ? - VCHIQ_BULK_RECEIVE_ABORTED : - VCHIQ_BULK_RECEIVE_DONE); - status = make_service_callback(service, - reason, NULL, bulk->userdata); - if (status == VCHIQ_RETRY) - break; + } else { + VCHIQ_SERVICE_STATS_INC(service, + bulk_aborted_count); + } + if (bulk->mode == VCHIQ_BULK_MODE_BLOCKING) { + struct bulk_waiter *waiter; + + spin_lock(&bulk_waiter_spinlock); + waiter = bulk->userdata; + if (waiter) { + waiter->actual = bulk->actual; + complete(&waiter->event); } + spin_unlock(&bulk_waiter_spinlock); + } else if (bulk->mode == VCHIQ_BULK_MODE_CALLBACK) { + enum vchiq_reason reason = + get_bulk_reason(bulk); + status = make_service_callback(service, + reason, NULL, bulk->userdata); + if (status == VCHIQ_RETRY) + break; } - - queue->remove++; - complete(&service->bulk_remove_event); } - if (!retry_poll) - status = VCHIQ_SUCCESS; + + queue->remove++; + complete(&service->bulk_remove_event); } + if (!retry_poll) + status = VCHIQ_SUCCESS; if (status == VCHIQ_RETRY) request_poll(service->state, service, @@ -1313,74 +1408,70 @@ notify_bulks(struct vchiq_service *service, struct vchiq_bulk_queue *queue, return status; } -/* Called by the slot handler thread */ static void -poll_services(struct vchiq_state *state) +poll_services_of_group(struct vchiq_state *state, int group) { - int group, i; - - for (group = 0; group < BITSET_SIZE(state->unused_service); group++) { - u32 flags; - - flags = atomic_xchg(&state->poll_services[group], 0); - for (i = 0; flags; i++) { - if (flags & BIT(i)) { - struct vchiq_service *service = - find_service_by_port(state, - (group<<5) + i); - u32 service_flags; - - flags &= ~BIT(i); - if (!service) - continue; - service_flags = - atomic_xchg(&service->poll_flags, 0); - if (service_flags & - BIT(VCHIQ_POLL_REMOVE)) { - vchiq_log_info(vchiq_core_log_level, - "%d: ps - remove %d<->%d", - state->id, service->localport, - service->remoteport); - - /* - * Make it look like a client, because - * it must be removed and not left in - * the LISTENING state. - */ - service->public_fourcc = - VCHIQ_FOURCC_INVALID; - - if (vchiq_close_service_internal( - service, 0/*!close_recvd*/) != - VCHIQ_SUCCESS) - request_poll(state, service, - VCHIQ_POLL_REMOVE); - } else if (service_flags & - BIT(VCHIQ_POLL_TERMINATE)) { - vchiq_log_info(vchiq_core_log_level, - "%d: ps - terminate %d<->%d", - state->id, service->localport, - service->remoteport); - if (vchiq_close_service_internal( - service, 0/*!close_recvd*/) != - VCHIQ_SUCCESS) - request_poll(state, service, - VCHIQ_POLL_TERMINATE); - } - if (service_flags & BIT(VCHIQ_POLL_TXNOTIFY)) - notify_bulks(service, - &service->bulk_tx, - 1/*retry_poll*/); - if (service_flags & BIT(VCHIQ_POLL_RXNOTIFY)) - notify_bulks(service, - &service->bulk_rx, - 1/*retry_poll*/); - unlock_service(service); - } + u32 flags = atomic_xchg(&state->poll_services[group], 0); + int i; + + for (i = 0; flags; i++) { + struct vchiq_service *service; + u32 service_flags; + + if ((flags & BIT(i)) == 0) + continue; + + service = find_service_by_port(state, (group << 5) + i); + flags &= ~BIT(i); + + if (!service) + continue; + + service_flags = atomic_xchg(&service->poll_flags, 0); + if (service_flags & BIT(VCHIQ_POLL_REMOVE)) { + vchiq_log_info(vchiq_core_log_level, "%d: ps - remove %d<->%d", + state->id, service->localport, + service->remoteport); + + /* + * Make it look like a client, because + * it must be removed and not left in + * the LISTENING state. + */ + service->public_fourcc = VCHIQ_FOURCC_INVALID; + + if (vchiq_close_service_internal(service, NO_CLOSE_RECVD) != + VCHIQ_SUCCESS) + request_poll(state, service, VCHIQ_POLL_REMOVE); + } else if (service_flags & BIT(VCHIQ_POLL_TERMINATE)) { + vchiq_log_info(vchiq_core_log_level, + "%d: ps - terminate %d<->%d", + state->id, service->localport, + service->remoteport); + if (vchiq_close_service_internal( + service, NO_CLOSE_RECVD) != + VCHIQ_SUCCESS) + request_poll(state, service, + VCHIQ_POLL_TERMINATE); } + if (service_flags & BIT(VCHIQ_POLL_TXNOTIFY)) + notify_bulks(service, &service->bulk_tx, RETRY_POLL); + if (service_flags & BIT(VCHIQ_POLL_RXNOTIFY)) + notify_bulks(service, &service->bulk_rx, RETRY_POLL); + vchiq_service_put(service); } } +/* Called by the slot handler thread */ +static void +poll_services(struct vchiq_state *state) +{ + int group; + + for (group = 0; group < BITSET_SIZE(state->unused_service); group++) + poll_services_of_group(state, group); +} + /* Called with the bulk_mutex held */ static void abort_outstanding_bulks(struct vchiq_service *service, @@ -1393,8 +1484,8 @@ abort_outstanding_bulks(struct vchiq_service *service, service->state->id, service->localport, is_tx ? 't' : 'r', queue->local_insert, queue->remote_insert, queue->process); - WARN_ON(!((int)(queue->local_insert - queue->process) >= 0)); - WARN_ON(!((int)(queue->remote_insert - queue->process) >= 0)); + WARN_ON((int)(queue->local_insert - queue->process) < 0); + WARN_ON((int)(queue->remote_insert - queue->process) < 0); while ((queue->process != queue->local_insert) || (queue->process != queue->remote_insert)) { @@ -1435,103 +1526,92 @@ abort_outstanding_bulks(struct vchiq_service *service, static int parse_open(struct vchiq_state *state, struct vchiq_header *header) { + const struct vchiq_open_payload *payload; struct vchiq_service *service = NULL; int msgid, size; - unsigned int localport, remoteport; + unsigned int localport, remoteport, fourcc; + short version, version_min; msgid = header->msgid; size = header->size; localport = VCHIQ_MSG_DSTPORT(msgid); remoteport = VCHIQ_MSG_SRCPORT(msgid); - if (size >= sizeof(struct vchiq_open_payload)) { - const struct vchiq_open_payload *payload = - (struct vchiq_open_payload *)header->data; - unsigned int fourcc; - - fourcc = payload->fourcc; - vchiq_log_info(vchiq_core_log_level, - "%d: prs OPEN@%pK (%d->'%c%c%c%c')", - state->id, header, localport, - VCHIQ_FOURCC_AS_4CHARS(fourcc)); - - service = get_listening_service(state, fourcc); + if (size < sizeof(struct vchiq_open_payload)) + goto fail_open; - if (service) { - /* A matching service exists */ - short version = payload->version; - short version_min = payload->version_min; - - if ((service->version < version_min) || - (version < service->version_min)) { - /* Version mismatch */ - vchiq_loud_error_header(); - vchiq_loud_error("%d: service %d (%c%c%c%c) " - "version mismatch - local (%d, min %d)" - " vs. remote (%d, min %d)", - state->id, service->localport, - VCHIQ_FOURCC_AS_4CHARS(fourcc), - service->version, service->version_min, - version, version_min); - vchiq_loud_error_footer(); - unlock_service(service); - service = NULL; - goto fail_open; - } - service->peer_version = version; + payload = (struct vchiq_open_payload *)header->data; + fourcc = payload->fourcc; + vchiq_log_info(vchiq_core_log_level, + "%d: prs OPEN@%pK (%d->'%c%c%c%c')", + state->id, header, localport, + VCHIQ_FOURCC_AS_4CHARS(fourcc)); - if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) { - struct vchiq_openack_payload ack_payload = { - service->version - }; - - if (state->version_common < - VCHIQ_VERSION_SYNCHRONOUS_MODE) - service->sync = 0; - - /* Acknowledge the OPEN */ - if (service->sync) { - if (queue_message_sync( - state, - NULL, - VCHIQ_MAKE_MSG( - VCHIQ_MSG_OPENACK, - service->localport, - remoteport), - memcpy_copy_callback, - &ack_payload, - sizeof(ack_payload), - 0) == VCHIQ_RETRY) - goto bail_not_ready; - } else { - if (queue_message(state, - NULL, - VCHIQ_MAKE_MSG( - VCHIQ_MSG_OPENACK, - service->localport, - remoteport), - memcpy_copy_callback, - &ack_payload, - sizeof(ack_payload), - 0) == VCHIQ_RETRY) - goto bail_not_ready; - } + service = get_listening_service(state, fourcc); + if (!service) + goto fail_open; - /* The service is now open */ - vchiq_set_service_state(service, - service->sync ? VCHIQ_SRVSTATE_OPENSYNC - : VCHIQ_SRVSTATE_OPEN); - } + /* A matching service exists */ + version = payload->version; + version_min = payload->version_min; - /* Success - the message has been dealt with */ - unlock_service(service); - return 1; + if ((service->version < version_min) || + (version < service->version_min)) { + /* Version mismatch */ + vchiq_loud_error_header(); + vchiq_loud_error("%d: service %d (%c%c%c%c) " + "version mismatch - local (%d, min %d)" + " vs. remote (%d, min %d)", + state->id, service->localport, + VCHIQ_FOURCC_AS_4CHARS(fourcc), + service->version, service->version_min, + version, version_min); + vchiq_loud_error_footer(); + vchiq_service_put(service); + service = NULL; + goto fail_open; + } + service->peer_version = version; + + if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) { + struct vchiq_openack_payload ack_payload = { + service->version + }; + int openack_id = MAKE_OPENACK(service->localport, remoteport); + + if (state->version_common < + VCHIQ_VERSION_SYNCHRONOUS_MODE) + service->sync = 0; + + /* Acknowledge the OPEN */ + if (service->sync) { + if (queue_message_sync(state, NULL, openack_id, + memcpy_copy_callback, + &ack_payload, + sizeof(ack_payload), + 0) == VCHIQ_RETRY) + goto bail_not_ready; + } else { + if (queue_message(state, NULL, openack_id, + memcpy_copy_callback, + &ack_payload, + sizeof(ack_payload), + 0) == VCHIQ_RETRY) + goto bail_not_ready; } + + /* The service is now open */ + vchiq_set_service_state(service, + service->sync ? VCHIQ_SRVSTATE_OPENSYNC + : VCHIQ_SRVSTATE_OPEN); } + /* Success - the message has been dealt with */ + vchiq_service_put(service); + return 1; + fail_open: /* No available service, or an invalid request - send a CLOSE */ - if (queue_message(state, NULL, - VCHIQ_MAKE_MSG(VCHIQ_MSG_CLOSE, 0, VCHIQ_MSG_SRCPORT(msgid)), + if (queue_message(state, NULL, MAKE_CLOSE(0, VCHIQ_MSG_SRCPORT(msgid)), NULL, NULL, 0, 0) == VCHIQ_RETRY) goto bail_not_ready; @@ -1539,339 +1619,364 @@ fail_open: bail_not_ready: if (service) - unlock_service(service); + vchiq_service_put(service); return 0; } -/* Called by the slot handler thread */ -static void -parse_rx_slots(struct vchiq_state *state) +/** + * parse_message() - parses a single message from the rx slot + * @state: vchiq state struct + * @header: message header + * + * Context: Process context + * + * Return: + * * >= 0 - size of the parsed message payload (without header) + * * -EINVAL - fatal error occurred, bail out is required + */ +static int +parse_message(struct vchiq_state *state, struct vchiq_header *header) { - struct vchiq_shared_state *remote = state->remote; struct vchiq_service *service = NULL; - int tx_pos; + unsigned int localport, remoteport; + int msgid, size, type, ret = -EINVAL; DEBUG_INITIALISE(state->local) - tx_pos = remote->tx_pos; - - while (state->rx_pos != tx_pos) { - struct vchiq_header *header; - int msgid, size; - int type; - unsigned int localport, remoteport; - - DEBUG_TRACE(PARSE_LINE); - if (!state->rx_data) { - int rx_index; - - WARN_ON(!((state->rx_pos & VCHIQ_SLOT_MASK) == 0)); - rx_index = remote->slot_queue[ - SLOT_QUEUE_INDEX_FROM_POS_MASKED(state->rx_pos)]; - state->rx_data = (char *)SLOT_DATA_FROM_INDEX(state, - rx_index); - state->rx_info = SLOT_INFO_FROM_INDEX(state, rx_index); + DEBUG_VALUE(PARSE_HEADER, (int)(long)header); + msgid = header->msgid; + DEBUG_VALUE(PARSE_MSGID, msgid); + size = header->size; + type = VCHIQ_MSG_TYPE(msgid); + localport = VCHIQ_MSG_DSTPORT(msgid); + remoteport = VCHIQ_MSG_SRCPORT(msgid); + if (type != VCHIQ_MSG_DATA) + VCHIQ_STATS_INC(state, ctrl_rx_count); + + switch (type) { + case VCHIQ_MSG_OPENACK: + case VCHIQ_MSG_CLOSE: + case VCHIQ_MSG_DATA: + case VCHIQ_MSG_BULK_RX: + case VCHIQ_MSG_BULK_TX: + case VCHIQ_MSG_BULK_RX_DONE: + case VCHIQ_MSG_BULK_TX_DONE: + service = find_service_by_port(state, localport); + if ((!service || + ((service->remoteport != remoteport) && + (service->remoteport != VCHIQ_PORT_FREE))) && + (localport == 0) && + (type == VCHIQ_MSG_CLOSE)) { /* - * Initialise use_count to one, and increment - * release_count at the end of the slot to avoid - * releasing the slot prematurely. + * This could be a CLOSE from a client which + * hadn't yet received the OPENACK - look for + * the connected service */ - state->rx_info->use_count = 1; - state->rx_info->release_count = 0; + if (service) + vchiq_service_put(service); + service = get_connected_service(state, + remoteport); + if (service) + vchiq_log_warning(vchiq_core_log_level, + "%d: prs %s@%pK (%d->%d) - found connected service %d", + state->id, msg_type_str(type), + header, remoteport, localport, + service->localport); } - header = (struct vchiq_header *)(state->rx_data + - (state->rx_pos & VCHIQ_SLOT_MASK)); - DEBUG_VALUE(PARSE_HEADER, (int)(long)header); - msgid = header->msgid; - DEBUG_VALUE(PARSE_MSGID, msgid); - size = header->size; - type = VCHIQ_MSG_TYPE(msgid); - localport = VCHIQ_MSG_DSTPORT(msgid); - remoteport = VCHIQ_MSG_SRCPORT(msgid); - - if (type != VCHIQ_MSG_DATA) - VCHIQ_STATS_INC(state, ctrl_rx_count); + if (!service) { + vchiq_log_error(vchiq_core_log_level, + "%d: prs %s@%pK (%d->%d) - invalid/closed service %d", + state->id, msg_type_str(type), + header, remoteport, localport, + localport); + goto skip_message; + } + break; + default: + break; + } - switch (type) { - case VCHIQ_MSG_OPENACK: - case VCHIQ_MSG_CLOSE: - case VCHIQ_MSG_DATA: - case VCHIQ_MSG_BULK_RX: - case VCHIQ_MSG_BULK_TX: - case VCHIQ_MSG_BULK_RX_DONE: - case VCHIQ_MSG_BULK_TX_DONE: - service = find_service_by_port(state, localport); - if ((!service || - ((service->remoteport != remoteport) && - (service->remoteport != VCHIQ_PORT_FREE))) && - (localport == 0) && - (type == VCHIQ_MSG_CLOSE)) { - /* - * This could be a CLOSE from a client which - * hadn't yet received the OPENACK - look for - * the connected service - */ - if (service) - unlock_service(service); - service = get_connected_service(state, - remoteport); - if (service) - vchiq_log_warning(vchiq_core_log_level, - "%d: prs %s@%pK (%d->%d) - found connected service %d", - state->id, msg_type_str(type), - header, remoteport, localport, - service->localport); - } + if (SRVTRACE_ENABLED(service, VCHIQ_LOG_INFO)) { + int svc_fourcc; - if (!service) { - vchiq_log_error(vchiq_core_log_level, - "%d: prs %s@%pK (%d->%d) - invalid/closed service %d", - state->id, msg_type_str(type), - header, remoteport, localport, - localport); - goto skip_message; - } - break; - default: - break; - } + svc_fourcc = service + ? service->base.fourcc + : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); + vchiq_log_info(SRVTRACE_LEVEL(service), + "Rcvd Msg %s(%u) from %c%c%c%c s:%d d:%d len:%d", + msg_type_str(type), type, + VCHIQ_FOURCC_AS_4CHARS(svc_fourcc), + remoteport, localport, size); + if (size > 0) + vchiq_log_dump_mem("Rcvd", 0, header->data, + min(16, size)); + } - if (SRVTRACE_ENABLED(service, VCHIQ_LOG_INFO)) { - int svc_fourcc; + if (((unsigned long)header & VCHIQ_SLOT_MASK) + + calc_stride(size) > VCHIQ_SLOT_SIZE) { + vchiq_log_error(vchiq_core_log_level, + "header %pK (msgid %x) - size %x too big for slot", + header, (unsigned int)msgid, + (unsigned int)size); + WARN(1, "oversized for slot\n"); + } - svc_fourcc = service - ? service->base.fourcc - : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); - vchiq_log_info(SRVTRACE_LEVEL(service), - "Rcvd Msg %s(%u) from %c%c%c%c s:%d d:%d len:%d", - msg_type_str(type), type, - VCHIQ_FOURCC_AS_4CHARS(svc_fourcc), - remoteport, localport, size); - if (size > 0) - vchiq_log_dump_mem("Rcvd", 0, header->data, - min(16, size)); + switch (type) { + case VCHIQ_MSG_OPEN: + WARN_ON(VCHIQ_MSG_DSTPORT(msgid)); + if (!parse_open(state, header)) + goto bail_not_ready; + break; + case VCHIQ_MSG_OPENACK: + if (size >= sizeof(struct vchiq_openack_payload)) { + const struct vchiq_openack_payload *payload = + (struct vchiq_openack_payload *) + header->data; + service->peer_version = payload->version; } - - if (((unsigned long)header & VCHIQ_SLOT_MASK) + - calc_stride(size) > VCHIQ_SLOT_SIZE) { + vchiq_log_info(vchiq_core_log_level, + "%d: prs OPENACK@%pK,%x (%d->%d) v:%d", + state->id, header, size, remoteport, localport, + service->peer_version); + if (service->srvstate == VCHIQ_SRVSTATE_OPENING) { + service->remoteport = remoteport; + vchiq_set_service_state(service, + VCHIQ_SRVSTATE_OPEN); + complete(&service->remove_event); + } else { vchiq_log_error(vchiq_core_log_level, - "header %pK (msgid %x) - size %x too big for slot", - header, (unsigned int)msgid, - (unsigned int)size); - WARN(1, "oversized for slot\n"); + "OPENACK received in state %s", + srvstate_names[service->srvstate]); } + break; + case VCHIQ_MSG_CLOSE: + WARN_ON(size); /* There should be no data */ - switch (type) { - case VCHIQ_MSG_OPEN: - WARN_ON(!(VCHIQ_MSG_DSTPORT(msgid) == 0)); - if (!parse_open(state, header)) - goto bail_not_ready; - break; - case VCHIQ_MSG_OPENACK: - if (size >= sizeof(struct vchiq_openack_payload)) { - const struct vchiq_openack_payload *payload = - (struct vchiq_openack_payload *) - header->data; - service->peer_version = payload->version; - } - vchiq_log_info(vchiq_core_log_level, - "%d: prs OPENACK@%pK,%x (%d->%d) v:%d", - state->id, header, size, remoteport, localport, - service->peer_version); - if (service->srvstate == VCHIQ_SRVSTATE_OPENING) { - service->remoteport = remoteport; - vchiq_set_service_state(service, - VCHIQ_SRVSTATE_OPEN); - complete(&service->remove_event); - } else - vchiq_log_error(vchiq_core_log_level, - "OPENACK received in state %s", - srvstate_names[service->srvstate]); - break; - case VCHIQ_MSG_CLOSE: - WARN_ON(size != 0); /* There should be no data */ - - vchiq_log_info(vchiq_core_log_level, - "%d: prs CLOSE@%pK (%d->%d)", - state->id, header, remoteport, localport); + vchiq_log_info(vchiq_core_log_level, + "%d: prs CLOSE@%pK (%d->%d)", + state->id, header, remoteport, localport); - mark_service_closing_internal(service, 1); + mark_service_closing_internal(service, 1); - if (vchiq_close_service_internal(service, - 1/*close_recvd*/) == VCHIQ_RETRY) - goto bail_not_ready; + if (vchiq_close_service_internal(service, + CLOSE_RECVD) == VCHIQ_RETRY) + goto bail_not_ready; - vchiq_log_info(vchiq_core_log_level, - "Close Service %c%c%c%c s:%u d:%d", - VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), - service->localport, - service->remoteport); - break; - case VCHIQ_MSG_DATA: - vchiq_log_info(vchiq_core_log_level, - "%d: prs DATA@%pK,%x (%d->%d)", - state->id, header, size, remoteport, localport); - - if ((service->remoteport == remoteport) && - (service->srvstate == VCHIQ_SRVSTATE_OPEN)) { - header->msgid = msgid | VCHIQ_MSGID_CLAIMED; - claim_slot(state->rx_info); + vchiq_log_info(vchiq_core_log_level, + "Close Service %c%c%c%c s:%u d:%d", + VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), + service->localport, + service->remoteport); + break; + case VCHIQ_MSG_DATA: + vchiq_log_info(vchiq_core_log_level, + "%d: prs DATA@%pK,%x (%d->%d)", + state->id, header, size, remoteport, localport); + + if ((service->remoteport == remoteport) && + (service->srvstate == VCHIQ_SRVSTATE_OPEN)) { + header->msgid = msgid | VCHIQ_MSGID_CLAIMED; + claim_slot(state->rx_info); + DEBUG_TRACE(PARSE_LINE); + if (make_service_callback(service, + VCHIQ_MESSAGE_AVAILABLE, header, + NULL) == VCHIQ_RETRY) { DEBUG_TRACE(PARSE_LINE); - if (make_service_callback(service, - VCHIQ_MESSAGE_AVAILABLE, header, - NULL) == VCHIQ_RETRY) { - DEBUG_TRACE(PARSE_LINE); - goto bail_not_ready; - } - VCHIQ_SERVICE_STATS_INC(service, ctrl_rx_count); - VCHIQ_SERVICE_STATS_ADD(service, ctrl_rx_bytes, - size); - } else { - VCHIQ_STATS_INC(state, error_count); + goto bail_not_ready; } - break; - case VCHIQ_MSG_CONNECT: - vchiq_log_info(vchiq_core_log_level, - "%d: prs CONNECT@%pK", state->id, header); - state->version_common = ((struct vchiq_slot_zero *) - state->slot_data)->version; - complete(&state->connect); - break; - case VCHIQ_MSG_BULK_RX: - case VCHIQ_MSG_BULK_TX: - /* - * We should never receive a bulk request from the - * other side since we're not setup to perform as the - * master. - */ - WARN_ON(1); - break; - case VCHIQ_MSG_BULK_RX_DONE: - case VCHIQ_MSG_BULK_TX_DONE: - if ((service->remoteport == remoteport) && - (service->srvstate != VCHIQ_SRVSTATE_FREE)) { - struct vchiq_bulk_queue *queue; - struct vchiq_bulk *bulk; + VCHIQ_SERVICE_STATS_INC(service, ctrl_rx_count); + VCHIQ_SERVICE_STATS_ADD(service, ctrl_rx_bytes, + size); + } else { + VCHIQ_STATS_INC(state, error_count); + } + break; + case VCHIQ_MSG_CONNECT: + vchiq_log_info(vchiq_core_log_level, + "%d: prs CONNECT@%pK", state->id, header); + state->version_common = ((struct vchiq_slot_zero *) + state->slot_data)->version; + complete(&state->connect); + break; + case VCHIQ_MSG_BULK_RX: + case VCHIQ_MSG_BULK_TX: + /* + * We should never receive a bulk request from the + * other side since we're not setup to perform as the + * master. + */ + WARN_ON(1); + break; + case VCHIQ_MSG_BULK_RX_DONE: + case VCHIQ_MSG_BULK_TX_DONE: + if ((service->remoteport == remoteport) && + (service->srvstate != VCHIQ_SRVSTATE_FREE)) { + struct vchiq_bulk_queue *queue; + struct vchiq_bulk *bulk; - queue = (type == VCHIQ_MSG_BULK_RX_DONE) ? - &service->bulk_rx : &service->bulk_tx; + queue = (type == VCHIQ_MSG_BULK_RX_DONE) ? + &service->bulk_rx : &service->bulk_tx; + DEBUG_TRACE(PARSE_LINE); + if (mutex_lock_killable(&service->bulk_mutex)) { DEBUG_TRACE(PARSE_LINE); - if (mutex_lock_killable(&service->bulk_mutex)) { - DEBUG_TRACE(PARSE_LINE); - goto bail_not_ready; - } - if ((int)(queue->remote_insert - - queue->local_insert) >= 0) { - vchiq_log_error(vchiq_core_log_level, - "%d: prs %s@%pK (%d->%d) unexpected (ri=%d,li=%d)", - state->id, msg_type_str(type), - header, remoteport, localport, - queue->remote_insert, - queue->local_insert); - mutex_unlock(&service->bulk_mutex); - break; - } - if (queue->process != queue->remote_insert) { - pr_err("%s: p %x != ri %x\n", - __func__, - queue->process, - queue->remote_insert); - mutex_unlock(&service->bulk_mutex); - goto bail_not_ready; - } - - bulk = &queue->bulks[ - BULK_INDEX(queue->remote_insert)]; - bulk->actual = *(int *)header->data; - queue->remote_insert++; - - vchiq_log_info(vchiq_core_log_level, - "%d: prs %s@%pK (%d->%d) %x@%pad", + goto bail_not_ready; + } + if ((int)(queue->remote_insert - + queue->local_insert) >= 0) { + vchiq_log_error(vchiq_core_log_level, + "%d: prs %s@%pK (%d->%d) unexpected (ri=%d,li=%d)", state->id, msg_type_str(type), header, remoteport, localport, - bulk->actual, &bulk->data); - - vchiq_log_trace(vchiq_core_log_level, - "%d: prs:%d %cx li=%x ri=%x p=%x", - state->id, localport, - (type == VCHIQ_MSG_BULK_RX_DONE) ? - 'r' : 't', - queue->local_insert, - queue->remote_insert, queue->process); - - DEBUG_TRACE(PARSE_LINE); - WARN_ON(queue->process == queue->local_insert); - vchiq_complete_bulk(bulk); - queue->process++; + queue->remote_insert, + queue->local_insert); mutex_unlock(&service->bulk_mutex); - DEBUG_TRACE(PARSE_LINE); - notify_bulks(service, queue, 1/*retry_poll*/); - DEBUG_TRACE(PARSE_LINE); - } - break; - case VCHIQ_MSG_PADDING: - vchiq_log_trace(vchiq_core_log_level, - "%d: prs PADDING@%pK,%x", - state->id, header, size); - break; - case VCHIQ_MSG_PAUSE: - /* If initiated, signal the application thread */ - vchiq_log_trace(vchiq_core_log_level, - "%d: prs PAUSE@%pK,%x", - state->id, header, size); - if (state->conn_state == VCHIQ_CONNSTATE_PAUSED) { - vchiq_log_error(vchiq_core_log_level, - "%d: PAUSE received in state PAUSED", - state->id); break; } - if (state->conn_state != VCHIQ_CONNSTATE_PAUSE_SENT) { - /* Send a PAUSE in response */ - if (queue_message(state, NULL, - VCHIQ_MAKE_MSG(VCHIQ_MSG_PAUSE, 0, 0), - NULL, NULL, 0, QMFLAGS_NO_MUTEX_UNLOCK) - == VCHIQ_RETRY) - goto bail_not_ready; + if (queue->process != queue->remote_insert) { + pr_err("%s: p %x != ri %x\n", + __func__, + queue->process, + queue->remote_insert); + mutex_unlock(&service->bulk_mutex); + goto bail_not_ready; } - /* At this point slot_mutex is held */ - vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSED); - break; - case VCHIQ_MSG_RESUME: - vchiq_log_trace(vchiq_core_log_level, - "%d: prs RESUME@%pK,%x", - state->id, header, size); - /* Release the slot mutex */ - mutex_unlock(&state->slot_mutex); - vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); - break; - case VCHIQ_MSG_REMOTE_USE: - vchiq_on_remote_use(state); - break; - case VCHIQ_MSG_REMOTE_RELEASE: - vchiq_on_remote_release(state); - break; - case VCHIQ_MSG_REMOTE_USE_ACTIVE: - break; + bulk = &queue->bulks[ + BULK_INDEX(queue->remote_insert)]; + bulk->actual = *(int *)header->data; + queue->remote_insert++; - default: + vchiq_log_info(vchiq_core_log_level, + "%d: prs %s@%pK (%d->%d) %x@%pad", + state->id, msg_type_str(type), + header, remoteport, localport, + bulk->actual, &bulk->data); + + vchiq_log_trace(vchiq_core_log_level, + "%d: prs:%d %cx li=%x ri=%x p=%x", + state->id, localport, + (type == VCHIQ_MSG_BULK_RX_DONE) ? + 'r' : 't', + queue->local_insert, + queue->remote_insert, queue->process); + + DEBUG_TRACE(PARSE_LINE); + WARN_ON(queue->process == queue->local_insert); + vchiq_complete_bulk(bulk); + queue->process++; + mutex_unlock(&service->bulk_mutex); + DEBUG_TRACE(PARSE_LINE); + notify_bulks(service, queue, RETRY_POLL); + DEBUG_TRACE(PARSE_LINE); + } + break; + case VCHIQ_MSG_PADDING: + vchiq_log_trace(vchiq_core_log_level, + "%d: prs PADDING@%pK,%x", + state->id, header, size); + break; + case VCHIQ_MSG_PAUSE: + /* If initiated, signal the application thread */ + vchiq_log_trace(vchiq_core_log_level, + "%d: prs PAUSE@%pK,%x", + state->id, header, size); + if (state->conn_state == VCHIQ_CONNSTATE_PAUSED) { vchiq_log_error(vchiq_core_log_level, - "%d: prs invalid msgid %x@%pK,%x", - state->id, msgid, header, size); - WARN(1, "invalid message\n"); + "%d: PAUSE received in state PAUSED", + state->id); break; } + if (state->conn_state != VCHIQ_CONNSTATE_PAUSE_SENT) { + /* Send a PAUSE in response */ + if (queue_message(state, NULL, MAKE_PAUSE, + NULL, NULL, 0, QMFLAGS_NO_MUTEX_UNLOCK) + == VCHIQ_RETRY) + goto bail_not_ready; + } + /* At this point slot_mutex is held */ + vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSED); + break; + case VCHIQ_MSG_RESUME: + vchiq_log_trace(vchiq_core_log_level, + "%d: prs RESUME@%pK,%x", + state->id, header, size); + /* Release the slot mutex */ + mutex_unlock(&state->slot_mutex); + vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); + break; + + case VCHIQ_MSG_REMOTE_USE: + vchiq_on_remote_use(state); + break; + case VCHIQ_MSG_REMOTE_RELEASE: + vchiq_on_remote_release(state); + break; + case VCHIQ_MSG_REMOTE_USE_ACTIVE: + break; + + default: + vchiq_log_error(vchiq_core_log_level, + "%d: prs invalid msgid %x@%pK,%x", + state->id, msgid, header, size); + WARN(1, "invalid message\n"); + break; + } skip_message: - if (service) { - unlock_service(service); - service = NULL; + ret = size; + +bail_not_ready: + if (service) + vchiq_service_put(service); + + return ret; +} + +/* Called by the slot handler thread */ +static void +parse_rx_slots(struct vchiq_state *state) +{ + struct vchiq_shared_state *remote = state->remote; + int tx_pos; + + DEBUG_INITIALISE(state->local) + + tx_pos = remote->tx_pos; + + while (state->rx_pos != tx_pos) { + struct vchiq_header *header; + int size; + + DEBUG_TRACE(PARSE_LINE); + if (!state->rx_data) { + int rx_index; + + WARN_ON(state->rx_pos & VCHIQ_SLOT_MASK); + rx_index = remote->slot_queue[ + SLOT_QUEUE_INDEX_FROM_POS_MASKED(state->rx_pos)]; + state->rx_data = (char *)SLOT_DATA_FROM_INDEX(state, + rx_index); + state->rx_info = SLOT_INFO_FROM_INDEX(state, rx_index); + + /* + * Initialise use_count to one, and increment + * release_count at the end of the slot to avoid + * releasing the slot prematurely. + */ + state->rx_info->use_count = 1; + state->rx_info->release_count = 0; } + header = (struct vchiq_header *)(state->rx_data + + (state->rx_pos & VCHIQ_SLOT_MASK)); + size = parse_message(state, header); + if (size < 0) + return; + state->rx_pos += calc_stride(size); DEBUG_TRACE(PARSE_LINE); @@ -1885,10 +1990,56 @@ skip_message: state->rx_data = NULL; } } +} -bail_not_ready: - if (service) - unlock_service(service); +/** + * handle_poll() - handle service polling and other rare conditions + * @state: vchiq state struct + * + * Context: Process context + * + * Return: + * * 0 - poll handled successful + * * -EAGAIN - retry later + */ +static int +handle_poll(struct vchiq_state *state) +{ + switch (state->conn_state) { + case VCHIQ_CONNSTATE_CONNECTED: + /* Poll the services as requested */ + poll_services(state); + break; + + case VCHIQ_CONNSTATE_PAUSING: + if (queue_message(state, NULL, MAKE_PAUSE, NULL, NULL, 0, + QMFLAGS_NO_MUTEX_UNLOCK) != VCHIQ_RETRY) { + vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSE_SENT); + } else { + /* Retry later */ + return -EAGAIN; + } + break; + + case VCHIQ_CONNSTATE_RESUMING: + if (queue_message(state, NULL, MAKE_RESUME, NULL, NULL, 0, + QMFLAGS_NO_MUTEX_LOCK) != VCHIQ_RETRY) { + vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); + } else { + /* + * This should really be impossible, + * since the PAUSE should have flushed + * through outstanding messages. + */ + vchiq_log_error(vchiq_core_log_level, + "Failed to send RESUME message"); + } + break; + default: + break; + } + + return 0; } /* Called by the slot handler thread */ @@ -1909,54 +2060,14 @@ slot_handler_func(void *v) DEBUG_TRACE(SLOT_HANDLER_LINE); if (state->poll_needed) { - state->poll_needed = 0; /* * Handle service polling and other rare conditions here * out of the mainline code */ - switch (state->conn_state) { - case VCHIQ_CONNSTATE_CONNECTED: - /* Poll the services as requested */ - poll_services(state); - break; - - case VCHIQ_CONNSTATE_PAUSING: - if (queue_message(state, NULL, - VCHIQ_MAKE_MSG(VCHIQ_MSG_PAUSE, 0, 0), - NULL, NULL, 0, - QMFLAGS_NO_MUTEX_UNLOCK) - != VCHIQ_RETRY) { - vchiq_set_conn_state(state, - VCHIQ_CONNSTATE_PAUSE_SENT); - } else { - /* Retry later */ - state->poll_needed = 1; - } - break; - - case VCHIQ_CONNSTATE_RESUMING: - if (queue_message(state, NULL, - VCHIQ_MAKE_MSG(VCHIQ_MSG_RESUME, 0, 0), - NULL, NULL, 0, QMFLAGS_NO_MUTEX_LOCK) - != VCHIQ_RETRY) { - vchiq_set_conn_state(state, - VCHIQ_CONNSTATE_CONNECTED); - } else { - /* - * This should really be impossible, - * since the PAUSE should have flushed - * through outstanding messages. - */ - vchiq_log_error(vchiq_core_log_level, - "Failed to send RESUME message"); - } - break; - default: - break; - } - + if (handle_poll(state) == -EAGAIN) + state->poll_needed = 1; } DEBUG_TRACE(SLOT_HANDLER_LINE); @@ -2070,8 +2181,7 @@ sync_func(void *v) state->id, header, size, remoteport, localport); if ((service->remoteport == remoteport) && - (service->srvstate == - VCHIQ_SRVSTATE_OPENSYNC)) { + (service->srvstate == VCHIQ_SRVSTATE_OPENSYNC)) { if (make_service_callback(service, VCHIQ_MESSAGE_AVAILABLE, header, NULL) == VCHIQ_RETRY) @@ -2089,7 +2199,7 @@ sync_func(void *v) break; } - unlock_service(service); + vchiq_service_put(service); } return 0; @@ -2118,9 +2228,11 @@ vchiq_init_slots(void *mem_base, int mem_size) (int)((VCHIQ_SLOT_SIZE - (long)mem_base) & VCHIQ_SLOT_MASK); struct vchiq_slot_zero *slot_zero = (struct vchiq_slot_zero *)(mem_base + mem_align); - int num_slots = (mem_size - mem_align)/VCHIQ_SLOT_SIZE; + int num_slots = (mem_size - mem_align) / VCHIQ_SLOT_SIZE; int first_data_slot = VCHIQ_SLOT_ZERO_SLOTS; + check_sizes(); + /* Ensure there is enough memory to run an absolutely minimum system */ num_slots -= first_data_slot; @@ -2143,26 +2255,25 @@ vchiq_init_slots(void *mem_base, int mem_size) slot_zero->master.slot_sync = first_data_slot; slot_zero->master.slot_first = first_data_slot + 1; - slot_zero->master.slot_last = first_data_slot + (num_slots/2) - 1; - slot_zero->slave.slot_sync = first_data_slot + (num_slots/2); - slot_zero->slave.slot_first = first_data_slot + (num_slots/2) + 1; + slot_zero->master.slot_last = first_data_slot + (num_slots / 2) - 1; + slot_zero->slave.slot_sync = first_data_slot + (num_slots / 2); + slot_zero->slave.slot_first = first_data_slot + (num_slots / 2) + 1; slot_zero->slave.slot_last = first_data_slot + num_slots - 1; return slot_zero; } -enum vchiq_status +int vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero) { struct vchiq_shared_state *local; struct vchiq_shared_state *remote; - enum vchiq_status status; char threadname[16]; - int i; + int i, ret; if (vchiq_states[0]) { pr_err("%s: VCHIQ state already initialized\n", __func__); - return VCHIQ_ERROR; + return -EINVAL; } local = &slot_zero->slave; @@ -2175,7 +2286,7 @@ vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero) else vchiq_loud_error("master/slave mismatch two slaves"); vchiq_loud_error_footer(); - return VCHIQ_ERROR; + return -EINVAL; } memset(state, 0, sizeof(struct vchiq_state)); @@ -2206,17 +2317,17 @@ vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero) state->slot_queue_available = 0; for (i = 0; i < VCHIQ_MAX_SERVICES; i++) { - struct vchiq_service_quota *quota = - &state->service_quotas[i]; + struct vchiq_service_quota *quota = &state->service_quotas[i]; init_completion("a->quota_event); } for (i = local->slot_first; i <= local->slot_last; i++) { - local->slot_queue[state->slot_queue_available++] = i; + local->slot_queue[state->slot_queue_available] = i; + state->slot_queue_available++; complete(&state->slot_available_event); } - state->default_slot_quota = state->slot_queue_available/2; + state->default_slot_quota = state->slot_queue_available / 2; state->default_message_quota = min((unsigned short)(state->default_slot_quota * 256), (unsigned short)~0); @@ -2240,9 +2351,9 @@ vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero) local->debug[DEBUG_ENTRIES] = DEBUG_MAX; - status = vchiq_platform_init_state(state); - if (status != VCHIQ_SUCCESS) - return VCHIQ_ERROR; + ret = vchiq_platform_init_state(state); + if (ret) + return ret; /* * bring up slot handler thread @@ -2256,7 +2367,7 @@ vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero) vchiq_loud_error_header(); vchiq_loud_error("couldn't create thread %s", threadname); vchiq_loud_error_footer(); - return VCHIQ_ERROR; + return PTR_ERR(state->slot_handler_thread); } set_user_nice(state->slot_handler_thread, -19); @@ -2268,6 +2379,7 @@ vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero) vchiq_loud_error_header(); vchiq_loud_error("couldn't create thread %s", threadname); vchiq_loud_error_footer(); + ret = PTR_ERR(state->recycle_thread); goto fail_free_handler_thread; } set_user_nice(state->recycle_thread, -19); @@ -2280,6 +2392,7 @@ vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero) vchiq_loud_error_header(); vchiq_loud_error("couldn't create thread %s", threadname); vchiq_loud_error_footer(); + ret = PTR_ERR(state->sync_thread); goto fail_free_recycle_thread; } set_user_nice(state->sync_thread, -20); @@ -2293,14 +2406,14 @@ vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero) /* Indicate readiness to the other side */ local->initialised = 1; - return status; + return 0; fail_free_recycle_thread: kthread_stop(state->recycle_thread); fail_free_handler_thread: kthread_stop(state->slot_handler_thread); - return VCHIQ_ERROR; + return ret; } void vchiq_msg_queue_push(unsigned int handle, struct vchiq_header *header) @@ -2314,7 +2427,8 @@ void vchiq_msg_queue_push(unsigned int handle, struct vchiq_header *header) flush_signals(current); } - pos = service->msg_queue_write++ & (VCHIQ_MAX_SLOTS - 1); + pos = service->msg_queue_write & (VCHIQ_MAX_SLOTS - 1); + service->msg_queue_write++; service->msg_queue[pos] = header; complete(&service->msg_queue_push); @@ -2335,7 +2449,8 @@ struct vchiq_header *vchiq_msg_hold(unsigned int handle) flush_signals(current); } - pos = service->msg_queue_read++ & (VCHIQ_MAX_SLOTS - 1); + pos = service->msg_queue_read & (VCHIQ_MAX_SLOTS - 1); + service->msg_queue_read++; header = service->msg_queue[pos]; complete(&service->msg_queue_pop); @@ -2440,11 +2555,11 @@ vchiq_add_service_internal(struct vchiq_state *state, struct vchiq_service *srv; srv = rcu_dereference(state->services[i]); - if (!srv) + if (!srv) { pservice = &state->services[i]; - else if ((srv->public_fourcc == params->fourcc) && - ((srv->instance != instance) || - (srv->base.callback != params->callback))) { + } else if ((srv->public_fourcc == params->fourcc) && + ((srv->instance != instance) || + (srv->base.callback != params->callback))) { /* * There is another server using this * fourcc which doesn't match. @@ -2514,10 +2629,7 @@ vchiq_open_service_internal(struct vchiq_service *service, int client_id) service->client_id = client_id; vchiq_use_service_internal(service); status = queue_message(service->state, - NULL, - VCHIQ_MAKE_MSG(VCHIQ_MSG_OPEN, - service->localport, - 0), + NULL, MAKE_OPEN(service->localport), memcpy_copy_callback, &payload, sizeof(payload), @@ -2568,42 +2680,43 @@ release_service_messages(struct vchiq_service *service) for (i = state->remote->slot_first; i <= slot_last; i++) { struct vchiq_slot_info *slot_info = SLOT_INFO_FROM_INDEX(state, i); - if (slot_info->release_count != slot_info->use_count) { - char *data = - (char *)SLOT_DATA_FROM_INDEX(state, i); - unsigned int pos, end; + unsigned int pos, end; + char *data; - end = VCHIQ_SLOT_SIZE; - if (data == state->rx_data) - /* - * This buffer is still being read from - stop - * at the current read position - */ - end = state->rx_pos & VCHIQ_SLOT_MASK; - - pos = 0; - - while (pos < end) { - struct vchiq_header *header = - (struct vchiq_header *)(data + pos); - int msgid = header->msgid; - int port = VCHIQ_MSG_DSTPORT(msgid); - - if ((port == service->localport) && - (msgid & VCHIQ_MSGID_CLAIMED)) { - vchiq_log_info(vchiq_core_log_level, - " fsi - hdr %pK", header); - release_slot(state, slot_info, header, - NULL); - } - pos += calc_stride(header->size); - if (pos > VCHIQ_SLOT_SIZE) { - vchiq_log_error(vchiq_core_log_level, - "fsi - pos %x: header %pK, msgid %x, header->msgid %x, header->size %x", - pos, header, msgid, - header->msgid, header->size); - WARN(1, "invalid slot position\n"); - } + if (slot_info->release_count == slot_info->use_count) + continue; + + data = (char *)SLOT_DATA_FROM_INDEX(state, i); + end = VCHIQ_SLOT_SIZE; + if (data == state->rx_data) + /* + * This buffer is still being read from - stop + * at the current read position + */ + end = state->rx_pos & VCHIQ_SLOT_MASK; + + pos = 0; + + while (pos < end) { + struct vchiq_header *header = + (struct vchiq_header *)(data + pos); + int msgid = header->msgid; + int port = VCHIQ_MSG_DSTPORT(msgid); + + if ((port == service->localport) && + (msgid & VCHIQ_MSGID_CLAIMED)) { + vchiq_log_info(vchiq_core_log_level, + " fsi - hdr %pK", header); + release_slot(state, slot_info, header, + NULL); + } + pos += calc_stride(header->size); + if (pos > VCHIQ_SLOT_SIZE) { + vchiq_log_error(vchiq_core_log_level, + "fsi - pos %x: header %pK, msgid %x, header->msgid %x, header->size %x", + pos, header, msgid, + header->msgid, header->size); + WARN(1, "invalid slot position\n"); } } } @@ -2621,10 +2734,11 @@ do_abort_bulks(struct vchiq_service *service) abort_outstanding_bulks(service, &service->bulk_rx); mutex_unlock(&service->bulk_mutex); - status = notify_bulks(service, &service->bulk_tx, 0/*!retry_poll*/); - if (status == VCHIQ_SUCCESS) - status = notify_bulks(service, &service->bulk_rx, - 0/*!retry_poll*/); + status = notify_bulks(service, &service->bulk_tx, NO_RETRY_POLL); + if (status != VCHIQ_SUCCESS) + return 0; + + status = notify_bulks(service, &service->bulk_rx, NO_RETRY_POLL); return (status == VCHIQ_SUCCESS); } @@ -2644,10 +2758,12 @@ close_service_complete(struct vchiq_service *service, int failstate) service->client_id = 0; service->remoteport = VCHIQ_PORT_FREE; newstate = VCHIQ_SRVSTATE_LISTENING; - } else + } else { newstate = VCHIQ_SRVSTATE_CLOSEWAIT; - } else + } + } else { newstate = VCHIQ_SRVSTATE_CLOSED; + } vchiq_set_service_state(service, newstate); break; case VCHIQ_SRVSTATE_LISTENING: @@ -2677,16 +2793,17 @@ close_service_complete(struct vchiq_service *service, int failstate) service->client_id = 0; service->remoteport = VCHIQ_PORT_FREE; - if (service->srvstate == VCHIQ_SRVSTATE_CLOSED) + if (service->srvstate == VCHIQ_SRVSTATE_CLOSED) { vchiq_free_service_internal(service); - else if (service->srvstate != VCHIQ_SRVSTATE_CLOSEWAIT) { + } else if (service->srvstate != VCHIQ_SRVSTATE_CLOSEWAIT) { if (is_server) service->closing = 0; complete(&service->remove_event); } - } else + } else { vchiq_set_service_state(service, failstate); + } return status; } @@ -2698,6 +2815,8 @@ vchiq_close_service_internal(struct vchiq_service *service, int close_recvd) struct vchiq_state *state = service->state; enum vchiq_status status = VCHIQ_SUCCESS; int is_server = (service->public_fourcc != VCHIQ_FOURCC_INVALID); + int close_id = MAKE_CLOSE(service->localport, + VCHIQ_MSG_DSTPORT(service->remoteport)); vchiq_log_info(vchiq_core_log_level, "%d: csi:%d,%d (%s)", service->state->id, service->localport, close_recvd, @@ -2708,11 +2827,11 @@ vchiq_close_service_internal(struct vchiq_service *service, int close_recvd) case VCHIQ_SRVSTATE_HIDDEN: case VCHIQ_SRVSTATE_LISTENING: case VCHIQ_SRVSTATE_CLOSEWAIT: - if (close_recvd) + if (close_recvd) { vchiq_log_error(vchiq_core_log_level, "%s(1) called in state %s", __func__, srvstate_names[service->srvstate]); - else if (is_server) { + } else if (is_server) { if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) { status = VCHIQ_ERROR; } else { @@ -2724,8 +2843,9 @@ vchiq_close_service_internal(struct vchiq_service *service, int close_recvd) VCHIQ_SRVSTATE_LISTENING); } complete(&service->remove_event); - } else + } else { vchiq_free_service_internal(service); + } break; case VCHIQ_SRVSTATE_OPENING: if (close_recvd) { @@ -2735,11 +2855,7 @@ vchiq_close_service_internal(struct vchiq_service *service, int close_recvd) complete(&service->remove_event); } else { /* Shutdown mid-open - let the other side know */ - status = queue_message(state, service, - VCHIQ_MAKE_MSG - (VCHIQ_MSG_CLOSE, - service->localport, - VCHIQ_MSG_DSTPORT(service->remoteport)), + status = queue_message(state, service, close_id, NULL, NULL, 0, 0); } break; @@ -2756,28 +2872,24 @@ vchiq_close_service_internal(struct vchiq_service *service, int close_recvd) release_service_messages(service); if (status == VCHIQ_SUCCESS) - status = queue_message(state, service, - VCHIQ_MAKE_MSG - (VCHIQ_MSG_CLOSE, - service->localport, - VCHIQ_MSG_DSTPORT(service->remoteport)), + status = queue_message(state, service, close_id, NULL, NULL, 0, QMFLAGS_NO_MUTEX_UNLOCK); - if (status == VCHIQ_SUCCESS) { - if (!close_recvd) { - /* Change the state while the mutex is still held */ - vchiq_set_service_state(service, - VCHIQ_SRVSTATE_CLOSESENT); - mutex_unlock(&state->slot_mutex); - if (service->sync) - mutex_unlock(&state->sync_mutex); - break; - } - } else if (service->srvstate == VCHIQ_SRVSTATE_OPENSYNC) { - mutex_unlock(&state->sync_mutex); + if (status != VCHIQ_SUCCESS) { + if (service->srvstate == VCHIQ_SRVSTATE_OPENSYNC) + mutex_unlock(&state->sync_mutex); break; - } else + } + + if (!close_recvd) { + /* Change the state while the mutex is still held */ + vchiq_set_service_state(service, + VCHIQ_SRVSTATE_CLOSESENT); + mutex_unlock(&state->slot_mutex); + if (service->sync) + mutex_unlock(&state->sync_mutex); break; + } /* Change the state while the mutex is still held */ vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSERECVD); @@ -2867,7 +2979,7 @@ vchiq_free_service_internal(struct vchiq_service *service) complete(&service->remove_event); /* Release the initial lock */ - unlock_service(service); + vchiq_service_put(service); } enum vchiq_status @@ -2883,12 +2995,11 @@ vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instanc if (service->srvstate == VCHIQ_SRVSTATE_HIDDEN) vchiq_set_service_state(service, VCHIQ_SRVSTATE_LISTENING); - unlock_service(service); + vchiq_service_put(service); } if (state->conn_state == VCHIQ_CONNSTATE_DISCONNECTED) { - if (queue_message(state, NULL, - VCHIQ_MAKE_MSG(VCHIQ_MSG_CONNECT, 0, 0), NULL, NULL, + if (queue_message(state, NULL, MAKE_CONNECT, NULL, NULL, 0, QMFLAGS_IS_BLOCKING) == VCHIQ_RETRY) return VCHIQ_RETRY; @@ -2906,21 +3017,19 @@ vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instanc return VCHIQ_SUCCESS; } -enum vchiq_status +void vchiq_shutdown_internal(struct vchiq_state *state, struct vchiq_instance *instance) { struct vchiq_service *service; int i; - /* Find all services registered to this client and enable them. */ + /* Find all services registered to this client and remove them. */ i = 0; while ((service = next_service_by_instance(state, instance, &i)) != NULL) { (void)vchiq_remove_service(service->handle); - unlock_service(service); + vchiq_service_put(service); } - - return VCHIQ_SUCCESS; } enum vchiq_status @@ -2940,15 +3049,14 @@ vchiq_close_service(unsigned int handle) if ((service->srvstate == VCHIQ_SRVSTATE_FREE) || (service->srvstate == VCHIQ_SRVSTATE_LISTENING) || (service->srvstate == VCHIQ_SRVSTATE_HIDDEN)) { - unlock_service(service); + vchiq_service_put(service); return VCHIQ_ERROR; } mark_service_closing(service); if (current == service->state->slot_handler_thread) { - status = vchiq_close_service_internal(service, - 0/*!close_recvd*/); + status = vchiq_close_service_internal(service, NO_CLOSE_RECVD); WARN_ON(status == VCHIQ_RETRY); } else { /* Mark the service for termination by the slot handler */ @@ -2977,7 +3085,7 @@ vchiq_close_service(unsigned int handle) (service->srvstate != VCHIQ_SRVSTATE_LISTENING)) status = VCHIQ_ERROR; - unlock_service(service); + vchiq_service_put(service); return status; } @@ -2998,7 +3106,7 @@ vchiq_remove_service(unsigned int handle) service->state->id, service->localport); if (service->srvstate == VCHIQ_SRVSTATE_FREE) { - unlock_service(service); + vchiq_service_put(service); return VCHIQ_ERROR; } @@ -3012,8 +3120,7 @@ vchiq_remove_service(unsigned int handle) */ service->public_fourcc = VCHIQ_FOURCC_INVALID; - status = vchiq_close_service_internal(service, - 0/*!close_recvd*/); + status = vchiq_close_service_internal(service, NO_CLOSE_RECVD); WARN_ON(status == VCHIQ_RETRY); } else { /* Mark the service for removal by the slot handler */ @@ -3039,7 +3146,7 @@ vchiq_remove_service(unsigned int handle) (service->srvstate != VCHIQ_SRVSTATE_FREE)) status = VCHIQ_ERROR; - unlock_service(service); + vchiq_service_put(service); return status; } @@ -3134,8 +3241,7 @@ enum vchiq_status vchiq_bulk_transfer(unsigned int handle, bulk->size = size; bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED; - if (vchiq_prepare_bulk_data(bulk, offset, uoffset, size, dir) - != VCHIQ_SUCCESS) + if (vchiq_prepare_bulk_data(bulk, offset, uoffset, size, dir)) goto unlock_error_exit; wmb(); @@ -3185,7 +3291,7 @@ enum vchiq_status vchiq_bulk_transfer(unsigned int handle, queue->local_insert, queue->remote_insert, queue->process); waiting: - unlock_service(service); + vchiq_service_put(service); status = VCHIQ_SUCCESS; @@ -3208,7 +3314,7 @@ unlock_error_exit: error_exit: if (service) - unlock_service(service); + vchiq_service_put(service); return status; } @@ -3221,6 +3327,7 @@ vchiq_queue_message(unsigned int handle, { struct vchiq_service *service = find_service_by_handle(handle); enum vchiq_status status = VCHIQ_ERROR; + int data_id; if (!service) goto error_exit; @@ -3239,19 +3346,15 @@ vchiq_queue_message(unsigned int handle, goto error_exit; } + data_id = MAKE_DATA(service->localport, service->remoteport); + switch (service->srvstate) { case VCHIQ_SRVSTATE_OPEN: - status = queue_message(service->state, service, - VCHIQ_MAKE_MSG(VCHIQ_MSG_DATA, - service->localport, - service->remoteport), + status = queue_message(service->state, service, data_id, copy_callback, context, size, 1); break; case VCHIQ_SRVSTATE_OPENSYNC: - status = queue_message_sync(service->state, service, - VCHIQ_MAKE_MSG(VCHIQ_MSG_DATA, - service->localport, - service->remoteport), + status = queue_message_sync(service->state, service, data_id, copy_callback, context, size, 1); break; default: @@ -3261,7 +3364,7 @@ vchiq_queue_message(unsigned int handle, error_exit: if (service) - unlock_service(service); + vchiq_service_put(service); return status; } @@ -3316,10 +3419,11 @@ vchiq_release_message(unsigned int handle, release_slot(state, slot_info, header, service); } - } else if (slot_index == remote->slot_sync) + } else if (slot_index == remote->slot_sync) { release_message_sync(state, header); + } - unlock_service(service); + vchiq_service_put(service); } EXPORT_SYMBOL(vchiq_release_message); @@ -3350,7 +3454,7 @@ vchiq_get_peer_version(unsigned int handle, short *peer_version) exit: if (service) - unlock_service(service); + vchiq_service_put(service); return status; } EXPORT_SYMBOL(vchiq_get_peer_version); @@ -3365,21 +3469,21 @@ void vchiq_get_config(struct vchiq_config *config) config->version_min = VCHIQ_VERSION_MIN; } -enum vchiq_status +int vchiq_set_service_option(unsigned int handle, enum vchiq_service_option option, int value) { struct vchiq_service *service = find_service_by_handle(handle); - enum vchiq_status status = VCHIQ_ERROR; struct vchiq_service_quota *quota; + int ret = -EINVAL; if (!service) - return VCHIQ_ERROR; + return -EINVAL; switch (option) { case VCHIQ_SERVICE_OPTION_AUTOCLOSE: service->auto_close = value; - status = VCHIQ_SUCCESS; + ret = 0; break; case VCHIQ_SERVICE_OPTION_SLOT_QUOTA: @@ -3396,7 +3500,7 @@ vchiq_set_service_option(unsigned int handle, * dropped below its quota */ complete("a->quota_event); - status = VCHIQ_SUCCESS; + ret = 0; } break; @@ -3414,7 +3518,7 @@ vchiq_set_service_option(unsigned int handle, * dropped below its quota */ complete("a->quota_event); - status = VCHIQ_SUCCESS; + ret = 0; } break; @@ -3422,21 +3526,21 @@ vchiq_set_service_option(unsigned int handle, if ((service->srvstate == VCHIQ_SRVSTATE_HIDDEN) || (service->srvstate == VCHIQ_SRVSTATE_LISTENING)) { service->sync = value; - status = VCHIQ_SUCCESS; + ret = 0; } break; case VCHIQ_SERVICE_OPTION_TRACE: service->trace = value; - status = VCHIQ_SUCCESS; + ret = 0; break; default: break; } - unlock_service(service); + vchiq_service_put(service); - return status; + return ret; } static int @@ -3575,7 +3679,7 @@ int vchiq_dump_state(void *dump_context, struct vchiq_state *state) if (service) { err = vchiq_dump_service_state(dump_context, service); - unlock_service(service); + vchiq_service_put(service); if (err) return err; } @@ -3611,8 +3715,9 @@ int vchiq_dump_service_state(void *dump_context, struct vchiq_service *service) scnprintf(remoteport + len2, sizeof(remoteport) - len2, " (client %x)", service->client_id); - } else + } else { strcpy(remoteport, "n/a"); + } len += scnprintf(buf + len, sizeof(buf) - len, " '%c%c%c%c' remote %s (msg use %d/%d, slot use %d/%d)", @@ -3711,9 +3816,7 @@ enum vchiq_status vchiq_send_remote_use(struct vchiq_state *state) if (state->conn_state == VCHIQ_CONNSTATE_DISCONNECTED) return VCHIQ_RETRY; - return queue_message(state, NULL, - VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_USE, 0, 0), - NULL, NULL, 0, 0); + return queue_message(state, NULL, MAKE_REMOTE_USE, NULL, NULL, 0, 0); } enum vchiq_status vchiq_send_remote_use_active(struct vchiq_state *state) @@ -3721,8 +3824,7 @@ enum vchiq_status vchiq_send_remote_use_active(struct vchiq_state *state) if (state->conn_state == VCHIQ_CONNSTATE_DISCONNECTED) return VCHIQ_RETRY; - return queue_message(state, NULL, - VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_USE_ACTIVE, 0, 0), + return queue_message(state, NULL, MAKE_REMOTE_USE_ACTIVE, NULL, NULL, 0, 0); } diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h index b817097651fa..957fea1f574f 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h @@ -64,74 +64,20 @@ #define vchiq_loud_error(...) \ vchiq_log_error(vchiq_core_log_level, "===== " __VA_ARGS__) -#ifndef vchiq_static_assert -#define vchiq_static_assert(cond) __attribute__((unused)) \ - extern int vchiq_static_assert[(cond) ? 1 : -1] -#endif - -#define IS_POW2(x) (x && ((x & (x - 1)) == 0)) - -/* Ensure that the slot size and maximum number of slots are powers of 2 */ -vchiq_static_assert(IS_POW2(VCHIQ_SLOT_SIZE)); -vchiq_static_assert(IS_POW2(VCHIQ_MAX_SLOTS)); -vchiq_static_assert(IS_POW2(VCHIQ_MAX_SLOTS_PER_SIDE)); - #define VCHIQ_SLOT_MASK (VCHIQ_SLOT_SIZE - 1) #define VCHIQ_SLOT_QUEUE_MASK (VCHIQ_MAX_SLOTS_PER_SIDE - 1) #define VCHIQ_SLOT_ZERO_SLOTS DIV_ROUND_UP(sizeof(struct vchiq_slot_zero), \ VCHIQ_SLOT_SIZE) -#define VCHIQ_MSG_PADDING 0 /* - */ -#define VCHIQ_MSG_CONNECT 1 /* - */ -#define VCHIQ_MSG_OPEN 2 /* + (srcport, -), fourcc, client_id */ -#define VCHIQ_MSG_OPENACK 3 /* + (srcport, dstport) */ -#define VCHIQ_MSG_CLOSE 4 /* + (srcport, dstport) */ -#define VCHIQ_MSG_DATA 5 /* + (srcport, dstport) */ -#define VCHIQ_MSG_BULK_RX 6 /* + (srcport, dstport), data, size */ -#define VCHIQ_MSG_BULK_TX 7 /* + (srcport, dstport), data, size */ -#define VCHIQ_MSG_BULK_RX_DONE 8 /* + (srcport, dstport), actual */ -#define VCHIQ_MSG_BULK_TX_DONE 9 /* + (srcport, dstport), actual */ -#define VCHIQ_MSG_PAUSE 10 /* - */ -#define VCHIQ_MSG_RESUME 11 /* - */ -#define VCHIQ_MSG_REMOTE_USE 12 /* - */ -#define VCHIQ_MSG_REMOTE_RELEASE 13 /* - */ -#define VCHIQ_MSG_REMOTE_USE_ACTIVE 14 /* - */ - -#define VCHIQ_PORT_MAX (VCHIQ_MAX_SERVICES - 1) -#define VCHIQ_PORT_FREE 0x1000 -#define VCHIQ_PORT_IS_VALID(port) (port < VCHIQ_PORT_FREE) -#define VCHIQ_MAKE_MSG(type, srcport, dstport) \ - ((type<<24) | (srcport<<12) | (dstport<<0)) -#define VCHIQ_MSG_TYPE(msgid) ((unsigned int)msgid >> 24) -#define VCHIQ_MSG_SRCPORT(msgid) \ - (unsigned short)(((unsigned int)msgid >> 12) & 0xfff) -#define VCHIQ_MSG_DSTPORT(msgid) \ - ((unsigned short)msgid & 0xfff) - #define VCHIQ_FOURCC_AS_4CHARS(fourcc) \ ((fourcc) >> 24) & 0xff, \ ((fourcc) >> 16) & 0xff, \ ((fourcc) >> 8) & 0xff, \ (fourcc) & 0xff -/* Ensure the fields are wide enough */ -vchiq_static_assert(VCHIQ_MSG_SRCPORT(VCHIQ_MAKE_MSG(0, 0, VCHIQ_PORT_MAX)) - == 0); -vchiq_static_assert(VCHIQ_MSG_TYPE(VCHIQ_MAKE_MSG(0, VCHIQ_PORT_MAX, 0)) == 0); -vchiq_static_assert((unsigned int)VCHIQ_PORT_MAX < - (unsigned int)VCHIQ_PORT_FREE); - -#define VCHIQ_MSGID_PADDING VCHIQ_MAKE_MSG(VCHIQ_MSG_PADDING, 0, 0) -#define VCHIQ_MSGID_CLAIMED 0x40000000 - -#define VCHIQ_FOURCC_INVALID 0x00000000 -#define VCHIQ_FOURCC_IS_LEGAL(fourcc) (fourcc != VCHIQ_FOURCC_INVALID) - -#define VCHIQ_BULK_ACTUAL_ABORTED -1 - typedef uint32_t BITSET_T; -vchiq_static_assert((sizeof(BITSET_T) * 8) == 32); +static_assert((sizeof(BITSET_T) * 8) == 32); #define BITSET_SIZE(b) ((b + 31) >> 5) #define BITSET_WORD(b) (b >> 5) @@ -140,17 +86,6 @@ vchiq_static_assert((sizeof(BITSET_T) * 8) == 32); #define BITSET_SET(bs, b) (bs[BITSET_WORD(b)] |= BITSET_BIT(b)) #define BITSET_CLR(bs, b) (bs[BITSET_WORD(b)] &= ~BITSET_BIT(b)) -#if VCHIQ_ENABLE_STATS -#define VCHIQ_STATS_INC(state, stat) (state->stats. stat++) -#define VCHIQ_SERVICE_STATS_INC(service, stat) (service->stats. stat++) -#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) \ - (service->stats. stat += addend) -#else -#define VCHIQ_STATS_INC(state, stat) ((void)0) -#define VCHIQ_SERVICE_STATS_INC(service, stat) ((void)0) -#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) ((void)0) -#endif - enum { DEBUG_ENTRIES, #if VCHIQ_ENABLE_DEBUG @@ -212,14 +147,6 @@ enum { VCHIQ_SRVSTATE_CLOSED }; -enum { - VCHIQ_POLL_TERMINATE, - VCHIQ_POLL_REMOVE, - VCHIQ_POLL_TXNOTIFY, - VCHIQ_POLL_RXNOTIFY, - VCHIQ_POLL_COUNT -}; - enum vchiq_bulk_dir { VCHIQ_BULK_TRANSMIT, VCHIQ_BULK_RECEIVE @@ -539,7 +466,7 @@ get_conn_state_name(enum vchiq_connstate conn_state); extern struct vchiq_slot_zero * vchiq_init_slots(void *mem_base, int mem_size); -extern enum vchiq_status +extern int vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero); extern enum vchiq_status @@ -563,7 +490,7 @@ vchiq_terminate_service_internal(struct vchiq_service *service); extern void vchiq_free_service_internal(struct vchiq_service *service); -extern enum vchiq_status +extern void vchiq_shutdown_internal(struct vchiq_state *state, struct vchiq_instance *instance); extern void @@ -627,10 +554,10 @@ next_service_by_instance(struct vchiq_state *state, int *pidx); extern void -lock_service(struct vchiq_service *service); +vchiq_service_get(struct vchiq_service *service); extern void -unlock_service(struct vchiq_service *service); +vchiq_service_put(struct vchiq_service *service); extern enum vchiq_status vchiq_queue_message(unsigned int handle, @@ -644,7 +571,7 @@ vchiq_queue_message(unsigned int handle, * implementations must be provided. */ -extern enum vchiq_status +extern int vchiq_prepare_bulk_data(struct vchiq_bulk *bulk, void *offset, void __user *uoffset, int size, int dir); @@ -667,10 +594,10 @@ extern int vchiq_dump_platform_service_state(void *dump_context, struct vchiq_service *service); -extern enum vchiq_status +extern int vchiq_use_service_internal(struct vchiq_service *service); -extern enum vchiq_status +extern int vchiq_release_service_internal(struct vchiq_service *service); extern void @@ -679,7 +606,7 @@ vchiq_on_remote_use(struct vchiq_state *state); extern void vchiq_on_remote_release(struct vchiq_state *state); -extern enum vchiq_status +extern int vchiq_platform_init_state(struct vchiq_state *state); extern enum vchiq_status @@ -712,7 +639,7 @@ extern int vchiq_get_client_id(unsigned int service); extern void vchiq_get_config(struct vchiq_config *config); -extern enum vchiq_status +extern int vchiq_set_service_option(unsigned int service, enum vchiq_service_option option, int value); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c index a39757b4e759..8f3d9cb2d562 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c @@ -11,11 +11,6 @@ #ifdef CONFIG_DEBUG_FS -/**************************************************************************** - * - * log category entries - * - ***************************************************************************/ #define DEBUGFS_WRITE_BUF_SIZE 256 #define VCHIQ_LOG_ERROR_STR "error" @@ -40,6 +35,7 @@ static struct vchiq_debugfs_log_entry vchiq_debugfs_log_entries[] = { { "susp", &vchiq_susp_log_level }, { "arm", &vchiq_arm_log_level }, }; + static int n_log_entries = ARRAY_SIZE(vchiq_debugfs_log_entries); static int debugfs_log_show(struct seq_file *f, void *offset) diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c index 06bca7be5203..76d3f0399964 100644 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c +++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c @@ -1862,7 +1862,7 @@ int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance) int status; int err = -ENODEV; struct vchiq_mmal_instance *instance; - static struct vchiq_instance *vchiq_instance; + struct vchiq_instance *vchiq_instance; struct vchiq_service_params_kernel params = { .version = VC_MMAL_VER, .version_min = VC_MMAL_MIN_VER, diff --git a/drivers/staging/vt6655/upc.h b/drivers/staging/vt6655/upc.h index e086ec6e77f7..8608693ae9c3 100644 --- a/drivers/staging/vt6655/upc.h +++ b/drivers/staging/vt6655/upc.h @@ -42,7 +42,7 @@ #define PCAvDelayByIO(uDelayUnit) \ do { \ - unsigned char byData; \ + unsigned char __maybe_unused byData; \ unsigned long ii; \ \ if (uDelayUnit <= 50) { \ diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 759e475e303c..7951bd63816f 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -276,7 +276,7 @@ static int prism2_scan(struct wiphy *wiphy, struct prism2_wiphy_private *priv = wiphy_priv(wiphy); struct wlandevice *wlandev; struct p80211msg_dot11req_scan msg1; - struct p80211msg_dot11req_scan_results msg2; + struct p80211msg_dot11req_scan_results *msg2; struct cfg80211_bss *bss; struct cfg80211_scan_info info = {}; @@ -301,6 +301,10 @@ static int prism2_scan(struct wiphy *wiphy, return -EOPNOTSUPP; } + msg2 = kzalloc(sizeof(*msg2), GFP_KERNEL); + if (!msg2) + return -ENOMEM; + priv->scan_request = request; memset(&msg1, 0x00, sizeof(msg1)); @@ -342,31 +346,30 @@ static int prism2_scan(struct wiphy *wiphy, for (i = 0; i < numbss; i++) { int freq; - memset(&msg2, 0, sizeof(msg2)); - msg2.msgcode = DIDMSG_DOT11REQ_SCAN_RESULTS; - msg2.bssindex.data = i; + msg2->msgcode = DIDMSG_DOT11REQ_SCAN_RESULTS; + msg2->bssindex.data = i; result = p80211req_dorequest(wlandev, (u8 *)&msg2); if ((result != 0) || - (msg2.resultcode.data != P80211ENUM_resultcode_success)) { + (msg2->resultcode.data != P80211ENUM_resultcode_success)) { break; } ie_buf[0] = WLAN_EID_SSID; - ie_buf[1] = msg2.ssid.data.len; + ie_buf[1] = msg2->ssid.data.len; ie_len = ie_buf[1] + 2; - memcpy(&ie_buf[2], &msg2.ssid.data.data, msg2.ssid.data.len); - freq = ieee80211_channel_to_frequency(msg2.dschannel.data, + memcpy(&ie_buf[2], &msg2->ssid.data.data, msg2->ssid.data.len); + freq = ieee80211_channel_to_frequency(msg2->dschannel.data, NL80211_BAND_2GHZ); bss = cfg80211_inform_bss(wiphy, ieee80211_get_channel(wiphy, freq), CFG80211_BSS_FTYPE_UNKNOWN, - (const u8 *)&msg2.bssid.data.data, - msg2.timestamp.data, msg2.capinfo.data, - msg2.beaconperiod.data, + (const u8 *)&msg2->bssid.data.data, + msg2->timestamp.data, msg2->capinfo.data, + msg2->beaconperiod.data, ie_buf, ie_len, - (msg2.signal.data - 65536) * 100, /* Conversion to signed type */ + (msg2->signal.data - 65536) * 100, /* Conversion to signed type */ GFP_KERNEL); if (!bss) { @@ -378,12 +381,13 @@ static int prism2_scan(struct wiphy *wiphy, } if (result) - err = prism2_result2err(msg2.resultcode.data); + err = prism2_result2err(msg2->resultcode.data); exit: info.aborted = !!(err); cfg80211_scan_done(request, &info); priv->scan_request = NULL; + kfree(msg2); return err; } diff --git a/drivers/staging/wlan-ng/p80211ioctl.h b/drivers/staging/wlan-ng/p80211ioctl.h index ed65ac57adbe..77e8d2913b76 100644 --- a/drivers/staging/wlan-ng/p80211ioctl.h +++ b/drivers/staging/wlan-ng/p80211ioctl.h @@ -81,7 +81,7 @@ struct p80211ioctl_req { char name[WLAN_DEVNAMELEN_MAX]; - caddr_t data; + char __user *data; u32 magic; u16 len; u32 result; diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 70570e8a5ad2..6f470e7ba647 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -325,7 +325,7 @@ static netdev_tx_t p80211knetdev_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) { int result = 0; - int txresult = -1; + int txresult; struct wlandevice *wlandev = netdev->ml_priv; union p80211_hdr p80211_hdr; struct p80211_metawep p80211_wep; @@ -569,7 +569,7 @@ static int p80211knetdev_do_ioctl(struct net_device *dev, goto bail; } - msgbuf = memdup_user((void __user *)req->data, req->len); + msgbuf = memdup_user(req->data, req->len); if (IS_ERR(msgbuf)) { result = PTR_ERR(msgbuf); goto bail; @@ -579,7 +579,7 @@ static int p80211knetdev_do_ioctl(struct net_device *dev, if (result == 0) { if (copy_to_user - ((void __user *)req->data, msgbuf, req->len)) { + (req->data, msgbuf, req->len)) { result = -EFAULT; } } diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 1646ba8eda11..2629d2ef3970 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -982,7 +982,7 @@ pscsi_execute_cmd(struct se_cmd *cmd) req = blk_get_request(pdv->pdv_sd->request_queue, cmd->data_direction == DMA_TO_DEVICE ? - REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, 0); + REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0); if (IS_ERR(req)) { pr_err("PSCSI: blk_get_request() failed\n"); ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index 7aa48f6c41d9..da19d7987d00 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -2,7 +2,7 @@ obj-${CONFIG_USB4} := thunderbolt.o thunderbolt-objs := nhi.o nhi_ops.o ctl.o tb.o switch.o cap.o path.o tunnel.o eeprom.o thunderbolt-objs += domain.o dma_port.o icm.o property.o xdomain.o lc.o tmu.o usb4.o -thunderbolt-objs += nvm.o retimer.o quirks.o +thunderbolt-objs += usb4_port.o nvm.o retimer.o quirks.o thunderbolt-${CONFIG_ACPI} += acpi.o thunderbolt-$(CONFIG_DEBUG_FS) += debugfs.o diff --git a/drivers/thunderbolt/acpi.c b/drivers/thunderbolt/acpi.c index 35fa17f7e599..b67e72d5644b 100644 --- a/drivers/thunderbolt/acpi.c +++ b/drivers/thunderbolt/acpi.c @@ -180,3 +180,209 @@ bool tb_acpi_is_xdomain_allowed(void) return osc_sb_native_usb4_control & OSC_USB_XDOMAIN; return true; } + +/* UUID for retimer _DSM: e0053122-795b-4122-8a5e-57be1d26acb3 */ +static const guid_t retimer_dsm_guid = + GUID_INIT(0xe0053122, 0x795b, 0x4122, + 0x8a, 0x5e, 0x57, 0xbe, 0x1d, 0x26, 0xac, 0xb3); + +#define RETIMER_DSM_QUERY_ONLINE_STATE 1 +#define RETIMER_DSM_SET_ONLINE_STATE 2 + +static int tb_acpi_retimer_set_power(struct tb_port *port, bool power) +{ + struct usb4_port *usb4 = port->usb4; + union acpi_object argv4[2]; + struct acpi_device *adev; + union acpi_object *obj; + int ret; + + if (!usb4->can_offline) + return 0; + + adev = ACPI_COMPANION(&usb4->dev); + if (WARN_ON(!adev)) + return 0; + + /* Check if we are already powered on (and in correct mode) */ + obj = acpi_evaluate_dsm_typed(adev->handle, &retimer_dsm_guid, 1, + RETIMER_DSM_QUERY_ONLINE_STATE, NULL, + ACPI_TYPE_INTEGER); + if (!obj) { + tb_port_warn(port, "ACPI: query online _DSM failed\n"); + return -EIO; + } + + ret = obj->integer.value; + ACPI_FREE(obj); + + if (power == ret) + return 0; + + tb_port_dbg(port, "ACPI: calling _DSM to power %s retimers\n", + power ? "on" : "off"); + + argv4[0].type = ACPI_TYPE_PACKAGE; + argv4[0].package.count = 1; + argv4[0].package.elements = &argv4[1]; + argv4[1].integer.type = ACPI_TYPE_INTEGER; + argv4[1].integer.value = power; + + obj = acpi_evaluate_dsm_typed(adev->handle, &retimer_dsm_guid, 1, + RETIMER_DSM_SET_ONLINE_STATE, argv4, + ACPI_TYPE_INTEGER); + if (!obj) { + tb_port_warn(port, + "ACPI: set online state _DSM evaluation failed\n"); + return -EIO; + } + + ret = obj->integer.value; + ACPI_FREE(obj); + + if (ret >= 0) { + if (power) + return ret == 1 ? 0 : -EBUSY; + return 0; + } + + tb_port_warn(port, "ACPI: set online state _DSM failed with error %d\n", ret); + return -EIO; +} + +/** + * tb_acpi_power_on_retimers() - Call platform to power on retimers + * @port: USB4 port + * + * Calls platform to turn on power to all retimers behind this USB4 + * port. After this function returns successfully the caller can + * continue with the normal retimer flows (as specified in the USB4 + * spec). Note if this returns %-EBUSY it means the type-C port is in + * non-USB4/TBT mode (there is non-USB4/TBT device connected). + * + * This should only be called if the USB4/TBT link is not up. + * + * Returns %0 on success. + */ +int tb_acpi_power_on_retimers(struct tb_port *port) +{ + return tb_acpi_retimer_set_power(port, true); +} + +/** + * tb_acpi_power_off_retimers() - Call platform to power off retimers + * @port: USB4 port + * + * This is the opposite of tb_acpi_power_on_retimers(). After returning + * successfully the normal operations with the @port can continue. + * + * Returns %0 on success. + */ +int tb_acpi_power_off_retimers(struct tb_port *port) +{ + return tb_acpi_retimer_set_power(port, false); +} + +static bool tb_acpi_bus_match(struct device *dev) +{ + return tb_is_switch(dev) || tb_is_usb4_port_device(dev); +} + +static struct acpi_device *tb_acpi_find_port(struct acpi_device *adev, + const struct tb_port *port) +{ + struct acpi_device *port_adev; + + if (!adev) + return NULL; + + /* + * Device routers exists under the downstream facing USB4 port + * of the parent router. Their _ADR is always 0. + */ + list_for_each_entry(port_adev, &adev->children, node) { + if (acpi_device_adr(port_adev) == port->port) + return port_adev; + } + + return NULL; +} + +static struct acpi_device *tb_acpi_switch_find_companion(struct tb_switch *sw) +{ + struct acpi_device *adev = NULL; + struct tb_switch *parent_sw; + + parent_sw = tb_switch_parent(sw); + if (parent_sw) { + struct tb_port *port = tb_port_at(tb_route(sw), parent_sw); + struct acpi_device *port_adev; + + port_adev = tb_acpi_find_port(ACPI_COMPANION(&parent_sw->dev), port); + if (port_adev) + adev = acpi_find_child_device(port_adev, 0, false); + } else { + struct tb_nhi *nhi = sw->tb->nhi; + struct acpi_device *parent_adev; + + parent_adev = ACPI_COMPANION(&nhi->pdev->dev); + if (parent_adev) + adev = acpi_find_child_device(parent_adev, 0, false); + } + + return adev; +} + +static struct acpi_device *tb_acpi_find_companion(struct device *dev) +{ + /* + * The Thunderbolt/USB4 hierarchy looks like following: + * + * Device (NHI) + * Device (HR) // Host router _ADR == 0 + * Device (DFP0) // Downstream port _ADR == lane 0 adapter + * Device (DR) // Device router _ADR == 0 + * Device (UFP) // Upstream port _ADR == lane 0 adapter + * Device (DFP1) // Downstream port _ADR == lane 0 adapter number + * + * At the moment we bind the host router to the corresponding + * Linux device. + */ + if (tb_is_switch(dev)) + return tb_acpi_switch_find_companion(tb_to_switch(dev)); + else if (tb_is_usb4_port_device(dev)) + return tb_acpi_find_port(ACPI_COMPANION(dev->parent), + tb_to_usb4_port_device(dev)->port); + return NULL; +} + +static void tb_acpi_setup(struct device *dev) +{ + struct acpi_device *adev = ACPI_COMPANION(dev); + struct usb4_port *usb4 = tb_to_usb4_port_device(dev); + + if (!adev || !usb4) + return; + + if (acpi_check_dsm(adev->handle, &retimer_dsm_guid, 1, + BIT(RETIMER_DSM_QUERY_ONLINE_STATE) | + BIT(RETIMER_DSM_SET_ONLINE_STATE))) + usb4->can_offline = true; +} + +static struct acpi_bus_type tb_acpi_bus = { + .name = "thunderbolt", + .match = tb_acpi_bus_match, + .find_companion = tb_acpi_find_companion, + .setup = tb_acpi_setup, +}; + +int tb_acpi_init(void) +{ + return register_acpi_bus_type(&tb_acpi_bus); +} + +void tb_acpi_exit(void) +{ + unregister_acpi_bus_type(&tb_acpi_bus); +} diff --git a/drivers/thunderbolt/dma_port.c b/drivers/thunderbolt/dma_port.c index 5631319f7b20..9f20c7bbf0ce 100644 --- a/drivers/thunderbolt/dma_port.c +++ b/drivers/thunderbolt/dma_port.c @@ -299,15 +299,13 @@ static int dma_port_request(struct tb_dma_port *dma, u32 in, return status_to_errno(out); } -static int dma_port_flash_read_block(struct tb_dma_port *dma, u32 address, - void *buf, u32 size) +static int dma_port_flash_read_block(void *data, unsigned int dwaddress, + void *buf, size_t dwords) { + struct tb_dma_port *dma = data; struct tb_switch *sw = dma->sw; - u32 in, dwaddress, dwords; int ret; - - dwaddress = address / 4; - dwords = size / 4; + u32 in; in = MAIL_IN_CMD_FLASH_READ << MAIL_IN_CMD_SHIFT; if (dwords < MAIL_DATA_DWORDS) @@ -323,14 +321,13 @@ static int dma_port_flash_read_block(struct tb_dma_port *dma, u32 address, dma->base + MAIL_DATA, dwords, DMA_PORT_TIMEOUT); } -static int dma_port_flash_write_block(struct tb_dma_port *dma, u32 address, - const void *buf, u32 size) +static int dma_port_flash_write_block(void *data, unsigned int dwaddress, + const void *buf, size_t dwords) { + struct tb_dma_port *dma = data; struct tb_switch *sw = dma->sw; - u32 in, dwaddress, dwords; int ret; - - dwords = size / 4; + u32 in; /* Write the block to MAIL_DATA registers */ ret = dma_port_write(sw->tb->ctl, buf, tb_route(sw), dma->port, @@ -341,12 +338,8 @@ static int dma_port_flash_write_block(struct tb_dma_port *dma, u32 address, in = MAIL_IN_CMD_FLASH_WRITE << MAIL_IN_CMD_SHIFT; /* CSS header write is always done to the same magic address */ - if (address >= DMA_PORT_CSS_ADDRESS) { - dwaddress = DMA_PORT_CSS_ADDRESS; + if (dwaddress >= DMA_PORT_CSS_ADDRESS) in |= MAIL_IN_CSS; - } else { - dwaddress = address / 4; - } in |= ((dwords - 1) << MAIL_IN_DWORDS_SHIFT) & MAIL_IN_DWORDS_MASK; in |= (dwaddress << MAIL_IN_ADDRESS_SHIFT) & MAIL_IN_ADDRESS_MASK; @@ -365,36 +358,8 @@ static int dma_port_flash_write_block(struct tb_dma_port *dma, u32 address, int dma_port_flash_read(struct tb_dma_port *dma, unsigned int address, void *buf, size_t size) { - unsigned int retries = DMA_PORT_RETRIES; - - do { - unsigned int offset; - size_t nbytes; - int ret; - - offset = address & 3; - nbytes = min_t(size_t, size + offset, MAIL_DATA_DWORDS * 4); - - ret = dma_port_flash_read_block(dma, address, dma->buf, - ALIGN(nbytes, 4)); - if (ret) { - if (ret == -ETIMEDOUT) { - if (retries--) - continue; - ret = -EIO; - } - return ret; - } - - nbytes -= offset; - memcpy(buf, dma->buf + offset, nbytes); - - size -= nbytes; - address += nbytes; - buf += nbytes; - } while (size > 0); - - return 0; + return tb_nvm_read_data(address, buf, size, DMA_PORT_RETRIES, + dma_port_flash_read_block, dma); } /** @@ -411,40 +376,11 @@ int dma_port_flash_read(struct tb_dma_port *dma, unsigned int address, int dma_port_flash_write(struct tb_dma_port *dma, unsigned int address, const void *buf, size_t size) { - unsigned int retries = DMA_PORT_RETRIES; - unsigned int offset; - - if (address >= DMA_PORT_CSS_ADDRESS) { - offset = 0; - if (size > DMA_PORT_CSS_MAX_SIZE) - return -E2BIG; - } else { - offset = address & 3; - address = address & ~3; - } - - do { - u32 nbytes = min_t(u32, size, MAIL_DATA_DWORDS * 4); - int ret; + if (address >= DMA_PORT_CSS_ADDRESS && size > DMA_PORT_CSS_MAX_SIZE) + return -E2BIG; - memcpy(dma->buf + offset, buf, nbytes); - - ret = dma_port_flash_write_block(dma, address, buf, nbytes); - if (ret) { - if (ret == -ETIMEDOUT) { - if (retries--) - continue; - ret = -EIO; - } - return ret; - } - - size -= nbytes; - address += nbytes; - buf += nbytes; - } while (size > 0); - - return 0; + return tb_nvm_write_data(address, buf, size, DMA_PORT_RETRIES, + dma_port_flash_write_block, dma); } /** diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c index 98f4056f89ff..a062befcb3b2 100644 --- a/drivers/thunderbolt/domain.c +++ b/drivers/thunderbolt/domain.c @@ -881,11 +881,12 @@ int tb_domain_init(void) int ret; tb_test_init(); - tb_debugfs_init(); + tb_acpi_init(); + ret = tb_xdomain_init(); if (ret) - goto err_debugfs; + goto err_acpi; ret = bus_register(&tb_bus_type); if (ret) goto err_xdomain; @@ -894,7 +895,8 @@ int tb_domain_init(void) err_xdomain: tb_xdomain_exit(); -err_debugfs: +err_acpi: + tb_acpi_exit(); tb_debugfs_exit(); tb_test_exit(); @@ -907,6 +909,7 @@ void tb_domain_exit(void) ida_destroy(&tb_domain_ida); tb_nvm_exit(); tb_xdomain_exit(); + tb_acpi_exit(); tb_debugfs_exit(); tb_test_exit(); } diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c index 46d0906a3070..470885e6f1c8 100644 --- a/drivers/thunderbolt/eeprom.c +++ b/drivers/thunderbolt/eeprom.c @@ -214,7 +214,10 @@ static u32 tb_crc32(void *data, size_t len) return ~__crc32c_le(~0, data, len); } -#define TB_DROM_DATA_START 13 +#define TB_DROM_DATA_START 13 +#define TB_DROM_HEADER_SIZE 22 +#define USB4_DROM_HEADER_SIZE 16 + struct tb_drom_header { /* BYTE 0 */ u8 uid_crc8; /* checksum for uid */ @@ -224,9 +227,9 @@ struct tb_drom_header { u32 data_crc32; /* checksum for data_len bytes starting at byte 13 */ /* BYTE 13 */ u8 device_rom_revision; /* should be <= 1 */ - u16 data_len:10; - u8 __unknown1:6; - /* BYTES 16-21 */ + u16 data_len:12; + u8 reserved:4; + /* BYTES 16-21 - Only for TBT DROM, nonexistent in USB4 DROM */ u16 vendor_id; u16 model_id; u8 model_rev; @@ -401,10 +404,10 @@ static int tb_drom_parse_entry_port(struct tb_switch *sw, * * Drom must have been copied to sw->drom. */ -static int tb_drom_parse_entries(struct tb_switch *sw) +static int tb_drom_parse_entries(struct tb_switch *sw, size_t header_size) { struct tb_drom_header *header = (void *) sw->drom; - u16 pos = sizeof(*header); + u16 pos = header_size; u16 drom_size = header->data_len + TB_DROM_DATA_START; int res; @@ -566,7 +569,7 @@ static int tb_drom_parse(struct tb_switch *sw) header->data_crc32, crc); } - return tb_drom_parse_entries(sw); + return tb_drom_parse_entries(sw, TB_DROM_HEADER_SIZE); } static int usb4_drom_parse(struct tb_switch *sw) @@ -583,7 +586,7 @@ static int usb4_drom_parse(struct tb_switch *sw) return -EINVAL; } - return tb_drom_parse_entries(sw); + return tb_drom_parse_entries(sw, USB4_DROM_HEADER_SIZE); } /** diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c index 2f30b816705a..6255f1ef9599 100644 --- a/drivers/thunderbolt/icm.c +++ b/drivers/thunderbolt/icm.c @@ -1677,14 +1677,18 @@ static void icm_icl_rtd3_veto(struct tb *tb, const struct icm_pkg_header *hdr) static bool icm_tgl_is_supported(struct tb *tb) { - u32 val; + unsigned long end = jiffies + msecs_to_jiffies(10); - /* - * If the firmware is not running use software CM. This platform - * should fully support both. - */ - val = ioread32(tb->nhi->iobase + REG_FW_STS); - return !!(val & REG_FW_STS_NVM_AUTH_DONE); + do { + u32 val; + + val = ioread32(tb->nhi->iobase + REG_FW_STS); + if (val & REG_FW_STS_NVM_AUTH_DONE) + return true; + usleep_range(100, 500); + } while (time_before(jiffies, end)); + + return false; } static void icm_handle_notification(struct work_struct *work) @@ -2505,6 +2509,8 @@ struct tb *icm_probe(struct tb_nhi *nhi) case PCI_DEVICE_ID_INTEL_TGL_NHI1: case PCI_DEVICE_ID_INTEL_TGL_H_NHI0: case PCI_DEVICE_ID_INTEL_TGL_H_NHI1: + case PCI_DEVICE_ID_INTEL_ADL_NHI0: + case PCI_DEVICE_ID_INTEL_ADL_NHI1: icm->is_supported = icm_tgl_is_supported; icm->driver_ready = icm_icl_driver_ready; icm->set_uuid = icm_icl_set_uuid; diff --git a/drivers/thunderbolt/lc.c b/drivers/thunderbolt/lc.c index bc671730a11f..c178f0d7beab 100644 --- a/drivers/thunderbolt/lc.c +++ b/drivers/thunderbolt/lc.c @@ -208,8 +208,8 @@ static int tb_lc_set_wake_one(struct tb_switch *sw, unsigned int offset, if (ret) return ret; - ctrl &= ~(TB_LC_SX_CTRL_WOC | TB_LC_SX_CTRL_WOD | TB_LC_SX_CTRL_WOP | - TB_LC_SX_CTRL_WOU4); + ctrl &= ~(TB_LC_SX_CTRL_WOC | TB_LC_SX_CTRL_WOD | TB_LC_SX_CTRL_WODPC | + TB_LC_SX_CTRL_WODPD | TB_LC_SX_CTRL_WOP | TB_LC_SX_CTRL_WOU4); if (flags & TB_WAKE_ON_CONNECT) ctrl |= TB_LC_SX_CTRL_WOC | TB_LC_SX_CTRL_WOD; @@ -217,6 +217,8 @@ static int tb_lc_set_wake_one(struct tb_switch *sw, unsigned int offset, ctrl |= TB_LC_SX_CTRL_WOU4; if (flags & TB_WAKE_ON_PCIE) ctrl |= TB_LC_SX_CTRL_WOP; + if (flags & TB_WAKE_ON_DP) + ctrl |= TB_LC_SX_CTRL_WODPC | TB_LC_SX_CTRL_WODPD; return tb_sw_write(sw, &ctrl, TB_CFG_SWITCH, offset + TB_LC_SX_CTRL, 1); } diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c index a0386d1e3fc9..fa44332845a1 100644 --- a/drivers/thunderbolt/nhi.c +++ b/drivers/thunderbolt/nhi.c @@ -17,7 +17,6 @@ #include <linux/module.h> #include <linux/delay.h> #include <linux/property.h> -#include <linux/platform_data/x86/apple.h> #include "nhi.h" #include "nhi_regs.h" @@ -1127,69 +1126,6 @@ static bool nhi_imr_valid(struct pci_dev *pdev) return true; } -/* - * During suspend the Thunderbolt controller is reset and all PCIe - * tunnels are lost. The NHI driver will try to reestablish all tunnels - * during resume. This adds device links between the tunneled PCIe - * downstream ports and the NHI so that the device core will make sure - * NHI is resumed first before the rest. - */ -static void tb_apple_add_links(struct tb_nhi *nhi) -{ - struct pci_dev *upstream, *pdev; - - if (!x86_apple_machine) - return; - - switch (nhi->pdev->device) { - case PCI_DEVICE_ID_INTEL_LIGHT_RIDGE: - case PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C: - case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI: - case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI: - break; - default: - return; - } - - upstream = pci_upstream_bridge(nhi->pdev); - while (upstream) { - if (!pci_is_pcie(upstream)) - return; - if (pci_pcie_type(upstream) == PCI_EXP_TYPE_UPSTREAM) - break; - upstream = pci_upstream_bridge(upstream); - } - - if (!upstream) - return; - - /* - * For each hotplug downstream port, create add device link - * back to NHI so that PCIe tunnels can be re-established after - * sleep. - */ - for_each_pci_bridge(pdev, upstream->subordinate) { - const struct device_link *link; - - if (!pci_is_pcie(pdev)) - continue; - if (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM || - !pdev->is_hotplug_bridge) - continue; - - link = device_link_add(&pdev->dev, &nhi->pdev->dev, - DL_FLAG_AUTOREMOVE_SUPPLIER | - DL_FLAG_PM_RUNTIME); - if (link) { - dev_dbg(&nhi->pdev->dev, "created link from %s\n", - dev_name(&pdev->dev)); - } else { - dev_warn(&nhi->pdev->dev, "device link creation from %s failed\n", - dev_name(&pdev->dev)); - } - } -} - static struct tb *nhi_select_cm(struct tb_nhi *nhi) { struct tb *tb; @@ -1278,9 +1214,6 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) return res; } - tb_apple_add_links(nhi); - tb_acpi_add_links(nhi); - tb = nhi_select_cm(nhi); if (!tb) { dev_err(&nhi->pdev->dev, @@ -1400,6 +1333,10 @@ static struct pci_device_id nhi_ids[] = { .driver_data = (kernel_ulong_t)&icl_nhi_ops }, { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGL_H_NHI1), .driver_data = (kernel_ulong_t)&icl_nhi_ops }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ADL_NHI0), + .driver_data = (kernel_ulong_t)&icl_nhi_ops }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ADL_NHI1), + .driver_data = (kernel_ulong_t)&icl_nhi_ops }, /* Any USB4 compliant host */ { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_USB4, ~0) }, diff --git a/drivers/thunderbolt/nhi.h b/drivers/thunderbolt/nhi.h index 69770beca792..69083aab2736 100644 --- a/drivers/thunderbolt/nhi.h +++ b/drivers/thunderbolt/nhi.h @@ -72,6 +72,8 @@ extern const struct tb_nhi_ops icl_nhi_ops; #define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_BRIDGE 0x15ea #define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_NHI 0x15eb #define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_BRIDGE 0x15ef +#define PCI_DEVICE_ID_INTEL_ADL_NHI0 0x463e +#define PCI_DEVICE_ID_INTEL_ADL_NHI1 0x466d #define PCI_DEVICE_ID_INTEL_ICL_NHI1 0x8a0d #define PCI_DEVICE_ID_INTEL_ICL_NHI0 0x8a17 #define PCI_DEVICE_ID_INTEL_TGL_NHI0 0x9a1b diff --git a/drivers/thunderbolt/nvm.c b/drivers/thunderbolt/nvm.c index 29de6d95c6e7..3a5336913cca 100644 --- a/drivers/thunderbolt/nvm.c +++ b/drivers/thunderbolt/nvm.c @@ -164,6 +164,101 @@ void tb_nvm_free(struct tb_nvm *nvm) kfree(nvm); } +/** + * tb_nvm_read_data() - Read data from NVM + * @address: Start address on the flash + * @buf: Buffer where the read data is copied + * @size: Size of the buffer in bytes + * @retries: Number of retries if block read fails + * @read_block: Function that reads block from the flash + * @read_block_data: Data passsed to @read_block + * + * This is a generic function that reads data from NVM or NVM like + * device. + * + * Returns %0 on success and negative errno otherwise. + */ +int tb_nvm_read_data(unsigned int address, void *buf, size_t size, + unsigned int retries, read_block_fn read_block, + void *read_block_data) +{ + do { + unsigned int dwaddress, dwords, offset; + u8 data[NVM_DATA_DWORDS * 4]; + size_t nbytes; + int ret; + + offset = address & 3; + nbytes = min_t(size_t, size + offset, NVM_DATA_DWORDS * 4); + + dwaddress = address / 4; + dwords = ALIGN(nbytes, 4) / 4; + + ret = read_block(read_block_data, dwaddress, data, dwords); + if (ret) { + if (ret != -ENODEV && retries--) + continue; + return ret; + } + + nbytes -= offset; + memcpy(buf, data + offset, nbytes); + + size -= nbytes; + address += nbytes; + buf += nbytes; + } while (size > 0); + + return 0; +} + +/** + * tb_nvm_write_data() - Write data to NVM + * @address: Start address on the flash + * @buf: Buffer where the data is copied from + * @size: Size of the buffer in bytes + * @retries: Number of retries if the block write fails + * @write_block: Function that writes block to the flash + * @write_block_data: Data passwd to @write_block + * + * This is generic function that writes data to NVM or NVM like device. + * + * Returns %0 on success and negative errno otherwise. + */ +int tb_nvm_write_data(unsigned int address, const void *buf, size_t size, + unsigned int retries, write_block_fn write_block, + void *write_block_data) +{ + do { + unsigned int offset, dwaddress; + u8 data[NVM_DATA_DWORDS * 4]; + size_t nbytes; + int ret; + + offset = address & 3; + nbytes = min_t(u32, size + offset, NVM_DATA_DWORDS * 4); + + memcpy(data + offset, buf, nbytes); + + dwaddress = address / 4; + ret = write_block(write_block_data, dwaddress, data, nbytes / 4); + if (ret) { + if (ret == -ETIMEDOUT) { + if (retries--) + continue; + ret = -EIO; + } + return ret; + } + + size -= nbytes; + address += nbytes; + buf += nbytes; + } while (size > 0); + + return 0; +} + void tb_nvm_exit(void) { ida_destroy(&nvm_ida); diff --git a/drivers/thunderbolt/path.c b/drivers/thunderbolt/path.c index f63e205a35d9..564e2f42cebd 100644 --- a/drivers/thunderbolt/path.c +++ b/drivers/thunderbolt/path.c @@ -367,7 +367,7 @@ static void __tb_path_deallocate_nfc(struct tb_path *path, int first_hop) int i, res; for (i = first_hop; i < path->path_length; i++) { res = tb_port_add_nfc_credits(path->hops[i].in_port, - -path->nfc_credits); + -path->hops[i].nfc_credits); if (res) tb_port_warn(path->hops[i].in_port, "nfc credits deallocation failed for hop %d\n", @@ -502,7 +502,7 @@ int tb_path_activate(struct tb_path *path) /* Add non flow controlled credits. */ for (i = path->path_length - 1; i >= 0; i--) { res = tb_port_add_nfc_credits(path->hops[i].in_port, - path->nfc_credits); + path->hops[i].nfc_credits); if (res) { __tb_path_deallocate_nfc(path, i); goto err; diff --git a/drivers/thunderbolt/quirks.c b/drivers/thunderbolt/quirks.c index 57e2978a3c21..b5f2ec79c4d6 100644 --- a/drivers/thunderbolt/quirks.c +++ b/drivers/thunderbolt/quirks.c @@ -12,7 +12,17 @@ static void quirk_force_power_link(struct tb_switch *sw) sw->quirks |= QUIRK_FORCE_POWER_LINK_CONTROLLER; } +static void quirk_dp_credit_allocation(struct tb_switch *sw) +{ + if (sw->credit_allocation && sw->min_dp_main_credits == 56) { + sw->min_dp_main_credits = 18; + tb_sw_dbg(sw, "quirked DP main: %u\n", sw->min_dp_main_credits); + } +} + struct tb_quirk { + u16 hw_vendor_id; + u16 hw_device_id; u16 vendor; u16 device; void (*hook)(struct tb_switch *sw); @@ -20,7 +30,13 @@ struct tb_quirk { static const struct tb_quirk tb_quirks[] = { /* Dell WD19TB supports self-authentication on unplug */ - { 0x00d4, 0xb070, quirk_force_power_link }, + { 0x0000, 0x0000, 0x00d4, 0xb070, quirk_force_power_link }, + { 0x0000, 0x0000, 0x00d4, 0xb071, quirk_force_power_link }, + /* + * Intel Goshen Ridge NVM 27 and before report wrong number of + * DP buffers. + */ + { 0x8087, 0x0b26, 0x0000, 0x0000, quirk_dp_credit_allocation }, }; /** @@ -36,7 +52,15 @@ void tb_check_quirks(struct tb_switch *sw) for (i = 0; i < ARRAY_SIZE(tb_quirks); i++) { const struct tb_quirk *q = &tb_quirks[i]; - if (sw->device == q->device && sw->vendor == q->vendor) - q->hook(sw); + if (q->hw_vendor_id && q->hw_vendor_id != sw->config.vendor_id) + continue; + if (q->hw_device_id && q->hw_device_id != sw->config.device_id) + continue; + if (q->vendor && q->vendor != sw->vendor) + continue; + if (q->device && q->device != sw->device) + continue; + + q->hook(sw); } } diff --git a/drivers/thunderbolt/retimer.c b/drivers/thunderbolt/retimer.c index c44fad2b9fbb..722694052f4a 100644 --- a/drivers/thunderbolt/retimer.c +++ b/drivers/thunderbolt/retimer.c @@ -103,6 +103,7 @@ static int tb_retimer_nvm_validate_and_write(struct tb_retimer *rt) unsigned int image_size, hdr_size; const u8 *buf = rt->nvm->buf; u16 ds_size, device; + int ret; image_size = rt->nvm->buf_data_size; if (image_size < NVM_MIN_SIZE || image_size > NVM_MAX_SIZE) @@ -140,8 +141,43 @@ static int tb_retimer_nvm_validate_and_write(struct tb_retimer *rt) buf += hdr_size; image_size -= hdr_size; - return usb4_port_retimer_nvm_write(rt->port, rt->index, 0, buf, - image_size); + ret = usb4_port_retimer_nvm_write(rt->port, rt->index, 0, buf, + image_size); + if (!ret) + rt->nvm->flushed = true; + + return ret; +} + +static int tb_retimer_nvm_authenticate(struct tb_retimer *rt, bool auth_only) +{ + u32 status; + int ret; + + if (auth_only) { + ret = usb4_port_retimer_nvm_set_offset(rt->port, rt->index, 0); + if (ret) + return ret; + } + + ret = usb4_port_retimer_nvm_authenticate(rt->port, rt->index); + if (ret) + return ret; + + usleep_range(100, 150); + + /* + * Check the status now if we still can access the retimer. It + * is expected that the below fails. + */ + ret = usb4_port_retimer_nvm_authenticate_status(rt->port, rt->index, + &status); + if (!ret) { + rt->auth_status = status; + return status ? -EINVAL : 0; + } + + return 0; } static ssize_t device_show(struct device *dev, struct device_attribute *attr, @@ -176,8 +212,7 @@ static ssize_t nvm_authenticate_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct tb_retimer *rt = tb_to_retimer(dev); - bool val; - int ret; + int val, ret; pm_runtime_get_sync(&rt->dev); @@ -191,7 +226,7 @@ static ssize_t nvm_authenticate_store(struct device *dev, goto exit_unlock; } - ret = kstrtobool(buf, &val); + ret = kstrtoint(buf, 10, &val); if (ret) goto exit_unlock; @@ -199,16 +234,22 @@ static ssize_t nvm_authenticate_store(struct device *dev, rt->auth_status = 0; if (val) { - if (!rt->nvm->buf) { - ret = -EINVAL; - goto exit_unlock; + if (val == AUTHENTICATE_ONLY) { + ret = tb_retimer_nvm_authenticate(rt, true); + } else { + if (!rt->nvm->flushed) { + if (!rt->nvm->buf) { + ret = -EINVAL; + goto exit_unlock; + } + + ret = tb_retimer_nvm_validate_and_write(rt); + if (ret || val == WRITE_ONLY) + goto exit_unlock; + } + if (val == WRITE_AND_AUTHENTICATE) + ret = tb_retimer_nvm_authenticate(rt, false); } - - ret = tb_retimer_nvm_validate_and_write(rt); - if (ret) - goto exit_unlock; - - ret = usb4_port_retimer_nvm_authenticate(rt->port, rt->index); } exit_unlock: @@ -283,11 +324,13 @@ struct device_type tb_retimer_type = { static int tb_retimer_add(struct tb_port *port, u8 index, u32 auth_status) { + struct usb4_port *usb4; struct tb_retimer *rt; u32 vendor, device; int ret; - if (!port->cap_usb4) + usb4 = port->usb4; + if (!usb4) return -EINVAL; ret = usb4_port_retimer_read(port, index, USB4_SB_VENDOR_ID, &vendor, @@ -331,7 +374,7 @@ static int tb_retimer_add(struct tb_port *port, u8 index, u32 auth_status) rt->port = port; rt->tb = port->sw->tb; - rt->dev.parent = &port->sw->dev; + rt->dev.parent = &usb4->dev; rt->dev.bus = &tb_bus_type; rt->dev.type = &tb_retimer_type; dev_set_name(&rt->dev, "%s:%u.%u", dev_name(&port->sw->dev), @@ -389,7 +432,7 @@ static struct tb_retimer *tb_port_find_retimer(struct tb_port *port, u8 index) struct tb_retimer_lookup lookup = { .port = port, .index = index }; struct device *dev; - dev = device_find_child(&port->sw->dev, &lookup, retimer_match); + dev = device_find_child(&port->usb4->dev, &lookup, retimer_match); if (dev) return tb_to_retimer(dev); @@ -399,19 +442,18 @@ static struct tb_retimer *tb_port_find_retimer(struct tb_port *port, u8 index) /** * tb_retimer_scan() - Scan for on-board retimers under port * @port: USB4 port to scan + * @add: If true also registers found retimers * - * Tries to enumerate on-board retimers connected to @port. Found - * retimers are registered as children of @port. Does not scan for cable - * retimers for now. + * Brings the sideband into a state where retimers can be accessed. + * Then Tries to enumerate on-board retimers connected to @port. Found + * retimers are registered as children of @port if @add is set. Does + * not scan for cable retimers for now. */ -int tb_retimer_scan(struct tb_port *port) +int tb_retimer_scan(struct tb_port *port, bool add) { u32 status[TB_MAX_RETIMER_INDEX + 1] = {}; int ret, i, last_idx = 0; - if (!port->cap_usb4) - return 0; - /* * Send broadcast RT to make sure retimer indices facing this * port are set. @@ -421,6 +463,13 @@ int tb_retimer_scan(struct tb_port *port) return ret; /* + * Enable sideband channel for each retimer. We can do this + * regardless whether there is device connected or not. + */ + for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++) + usb4_port_retimer_set_inbound_sbtx(port, i); + + /* * Before doing anything else, read the authentication status. * If the retimer has it set, store it for the new retimer * device instance. @@ -451,10 +500,10 @@ int tb_retimer_scan(struct tb_port *port) rt = tb_port_find_retimer(port, i); if (rt) { put_device(&rt->dev); - } else { + } else if (add) { ret = tb_retimer_add(port, i, status[i]); if (ret && ret != -EOPNOTSUPP) - return ret; + break; } } @@ -479,7 +528,10 @@ static int remove_retimer(struct device *dev, void *data) */ void tb_retimer_remove_all(struct tb_port *port) { - if (port->cap_usb4) - device_for_each_child_reverse(&port->sw->dev, port, + struct usb4_port *usb4; + + usb4 = port->usb4; + if (usb4) + device_for_each_child_reverse(&usb4->dev, port, remove_retimer); } diff --git a/drivers/thunderbolt/sb_regs.h b/drivers/thunderbolt/sb_regs.h index 9dafd696612f..bda889ff3bda 100644 --- a/drivers/thunderbolt/sb_regs.h +++ b/drivers/thunderbolt/sb_regs.h @@ -17,7 +17,9 @@ enum usb4_sb_opcode { USB4_SB_OPCODE_ERR = 0x20525245, /* "ERR " */ USB4_SB_OPCODE_ONS = 0x444d4321, /* "!CMD" */ + USB4_SB_OPCODE_ROUTER_OFFLINE = 0x4e45534c, /* "LSEN" */ USB4_SB_OPCODE_ENUMERATE_RETIMERS = 0x4d554e45, /* "ENUM" */ + USB4_SB_OPCODE_SET_INBOUND_SBTX = 0x5055534c, /* "LSUP" */ USB4_SB_OPCODE_QUERY_LAST_RETIMER = 0x5453414c, /* "LAST" */ USB4_SB_OPCODE_GET_NVM_SECTOR_SIZE = 0x53534e47, /* "GNSS" */ USB4_SB_OPCODE_NVM_SET_OFFSET = 0x53504f42, /* "BOPS" */ diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index e73cd296db7e..83b1ef3d5d03 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -26,11 +26,6 @@ struct nvm_auth_status { u32 status; }; -enum nvm_write_ops { - WRITE_AND_AUTHENTICATE = 1, - WRITE_ONLY = 2, -}; - /* * Hold NVM authentication failure status per switch This information * needs to stay around even when the switch gets power cycled so we @@ -308,13 +303,23 @@ static inline int nvm_read(struct tb_switch *sw, unsigned int address, return dma_port_flash_read(sw->dma_port, address, buf, size); } -static int nvm_authenticate(struct tb_switch *sw) +static int nvm_authenticate(struct tb_switch *sw, bool auth_only) { int ret; - if (tb_switch_is_usb4(sw)) + if (tb_switch_is_usb4(sw)) { + if (auth_only) { + ret = usb4_switch_nvm_set_offset(sw, 0); + if (ret) + return ret; + } + sw->nvm->authenticating = true; return usb4_switch_nvm_authenticate(sw); + } else if (auth_only) { + return -EOPNOTSUPP; + } + sw->nvm->authenticating = true; if (!tb_route(sw)) { nvm_authenticate_start_dma_port(sw); ret = nvm_authenticate_host_dma_port(sw); @@ -459,7 +464,7 @@ static void tb_switch_nvm_remove(struct tb_switch *sw) /* port utility functions */ -static const char *tb_port_type(struct tb_regs_port_header *port) +static const char *tb_port_type(const struct tb_regs_port_header *port) { switch (port->type >> 16) { case 0: @@ -488,17 +493,21 @@ static const char *tb_port_type(struct tb_regs_port_header *port) } } -static void tb_dump_port(struct tb *tb, struct tb_regs_port_header *port) +static void tb_dump_port(struct tb *tb, const struct tb_port *port) { + const struct tb_regs_port_header *regs = &port->config; + tb_dbg(tb, " Port %d: %x:%x (Revision: %d, TB Version: %d, Type: %s (%#x))\n", - port->port_number, port->vendor_id, port->device_id, - port->revision, port->thunderbolt_version, tb_port_type(port), - port->type); + regs->port_number, regs->vendor_id, regs->device_id, + regs->revision, regs->thunderbolt_version, tb_port_type(regs), + regs->type); tb_dbg(tb, " Max hop id (in/out): %d/%d\n", - port->max_in_hop_id, port->max_out_hop_id); - tb_dbg(tb, " Max counters: %d\n", port->max_counters); - tb_dbg(tb, " NFC Credits: %#x\n", port->nfc_credits); + regs->max_in_hop_id, regs->max_out_hop_id); + tb_dbg(tb, " Max counters: %d\n", regs->max_counters); + tb_dbg(tb, " NFC Credits: %#x\n", regs->nfc_credits); + tb_dbg(tb, " Credits (total/control): %u/%u\n", port->total_credits, + port->ctl_credits); } /** @@ -738,13 +747,32 @@ static int tb_init_port(struct tb_port *port) cap = tb_port_find_cap(port, TB_PORT_CAP_USB4); if (cap > 0) port->cap_usb4 = cap; + + /* + * USB4 ports the buffers allocated for the control path + * can be read from the path config space. Legacy + * devices we use hard-coded value. + */ + if (tb_switch_is_usb4(port->sw)) { + struct tb_regs_hop hop; + + if (!tb_port_read(port, &hop, TB_CFG_HOPS, 0, 2)) + port->ctl_credits = hop.initial_credits; + } + if (!port->ctl_credits) + port->ctl_credits = 2; + } else if (port->port != 0) { cap = tb_port_find_cap(port, TB_PORT_CAP_ADAP); if (cap > 0) port->cap_adap = cap; } - tb_dump_port(port->sw->tb, &port->config); + port->total_credits = + (port->config.nfc_credits & ADP_CS_4_TOTAL_BUFFERS_MASK) >> + ADP_CS_4_TOTAL_BUFFERS_SHIFT; + + tb_dump_port(port->sw->tb, port); INIT_LIST_HEAD(&port->list); return 0; @@ -991,8 +1019,11 @@ static int tb_port_set_link_width(struct tb_port *port, unsigned int width) * tb_port_lane_bonding_enable() - Enable bonding on port * @port: port to enable * - * Enable bonding by setting the link width of the port and the - * other port in case of dual link port. + * Enable bonding by setting the link width of the port and the other + * port in case of dual link port. Does not wait for the link to + * actually reach the bonded state so caller needs to call + * tb_port_wait_for_link_width() before enabling any paths through the + * link to make sure the link is in expected state. * * Return: %0 in case of success and negative errno in case of error */ @@ -1043,6 +1074,79 @@ void tb_port_lane_bonding_disable(struct tb_port *port) tb_port_set_link_width(port, 1); } +/** + * tb_port_wait_for_link_width() - Wait until link reaches specific width + * @port: Port to wait for + * @width: Expected link width (%1 or %2) + * @timeout_msec: Timeout in ms how long to wait + * + * Should be used after both ends of the link have been bonded (or + * bonding has been disabled) to wait until the link actually reaches + * the expected state. Returns %-ETIMEDOUT if the @width was not reached + * within the given timeout, %0 if it did. + */ +int tb_port_wait_for_link_width(struct tb_port *port, int width, + int timeout_msec) +{ + ktime_t timeout = ktime_add_ms(ktime_get(), timeout_msec); + int ret; + + do { + ret = tb_port_get_link_width(port); + if (ret < 0) + return ret; + else if (ret == width) + return 0; + + usleep_range(1000, 2000); + } while (ktime_before(ktime_get(), timeout)); + + return -ETIMEDOUT; +} + +static int tb_port_do_update_credits(struct tb_port *port) +{ + u32 nfc_credits; + int ret; + + ret = tb_port_read(port, &nfc_credits, TB_CFG_PORT, ADP_CS_4, 1); + if (ret) + return ret; + + if (nfc_credits != port->config.nfc_credits) { + u32 total; + + total = (nfc_credits & ADP_CS_4_TOTAL_BUFFERS_MASK) >> + ADP_CS_4_TOTAL_BUFFERS_SHIFT; + + tb_port_dbg(port, "total credits changed %u -> %u\n", + port->total_credits, total); + + port->config.nfc_credits = nfc_credits; + port->total_credits = total; + } + + return 0; +} + +/** + * tb_port_update_credits() - Re-read port total credits + * @port: Port to update + * + * After the link is bonded (or bonding was disabled) the port total + * credits may change, so this function needs to be called to re-read + * the credits. Updates also the second lane adapter. + */ +int tb_port_update_credits(struct tb_port *port) +{ + int ret; + + ret = tb_port_do_update_credits(port); + if (ret) + return ret; + return tb_port_do_update_credits(port->dual_link_port); +} + static int tb_port_start_lane_initialization(struct tb_port *port) { int ret; @@ -1054,6 +1158,33 @@ static int tb_port_start_lane_initialization(struct tb_port *port) return ret == -EINVAL ? 0 : ret; } +/* + * Returns true if the port had something (router, XDomain) connected + * before suspend. + */ +static bool tb_port_resume(struct tb_port *port) +{ + bool has_remote = tb_port_has_remote(port); + + if (port->usb4) { + usb4_port_device_resume(port->usb4); + } else if (!has_remote) { + /* + * For disconnected downstream lane adapters start lane + * initialization now so we detect future connects. + * + * For XDomain start the lane initialzation now so the + * link gets re-established. + * + * This is only needed for non-USB4 ports. + */ + if (!tb_is_upstream_port(port) || port->xdomain) + tb_port_start_lane_initialization(port); + } + + return has_remote || port->xdomain; +} + /** * tb_port_is_enabled() - Is the adapter port enabled * @port: Port to check @@ -1592,8 +1723,7 @@ static ssize_t nvm_authenticate_sysfs(struct device *dev, const char *buf, bool disconnect) { struct tb_switch *sw = tb_to_switch(dev); - int val; - int ret; + int val, ret; pm_runtime_get_sync(&sw->dev); @@ -1616,22 +1746,27 @@ static ssize_t nvm_authenticate_sysfs(struct device *dev, const char *buf, nvm_clear_auth_status(sw); if (val > 0) { - if (!sw->nvm->flushed) { - if (!sw->nvm->buf) { + if (val == AUTHENTICATE_ONLY) { + if (disconnect) ret = -EINVAL; - goto exit_unlock; + else + ret = nvm_authenticate(sw, true); + } else { + if (!sw->nvm->flushed) { + if (!sw->nvm->buf) { + ret = -EINVAL; + goto exit_unlock; + } + + ret = nvm_validate_and_write(sw); + if (ret || val == WRITE_ONLY) + goto exit_unlock; } - - ret = nvm_validate_and_write(sw); - if (ret || val == WRITE_ONLY) - goto exit_unlock; - } - if (val == WRITE_AND_AUTHENTICATE) { - if (disconnect) { - ret = tb_lc_force_power(sw); - } else { - sw->nvm->authenticating = true; - ret = nvm_authenticate(sw); + if (val == WRITE_AND_AUTHENTICATE) { + if (disconnect) + ret = tb_lc_force_power(sw); + else + ret = nvm_authenticate(sw, false); } } } @@ -2432,6 +2567,14 @@ int tb_switch_lane_bonding_enable(struct tb_switch *sw) return ret; } + ret = tb_port_wait_for_link_width(down, 2, 100); + if (ret) { + tb_port_warn(down, "timeout enabling lane bonding\n"); + return ret; + } + + tb_port_update_credits(down); + tb_port_update_credits(up); tb_switch_update_link_attributes(sw); tb_sw_dbg(sw, "lane bonding enabled\n"); @@ -2462,7 +2605,17 @@ void tb_switch_lane_bonding_disable(struct tb_switch *sw) tb_port_lane_bonding_disable(up); tb_port_lane_bonding_disable(down); + /* + * It is fine if we get other errors as the router might have + * been unplugged. + */ + if (tb_port_wait_for_link_width(down, 1, 100) == -ETIMEDOUT) + tb_sw_warn(sw, "timeout disabling lane bonding\n"); + + tb_port_update_credits(down); + tb_port_update_credits(up); tb_switch_update_link_attributes(sw); + tb_sw_dbg(sw, "lane bonding disabled\n"); } @@ -2529,6 +2682,16 @@ void tb_switch_unconfigure_link(struct tb_switch *sw) tb_lc_unconfigure_port(down); } +static void tb_switch_credits_init(struct tb_switch *sw) +{ + if (tb_switch_is_icm(sw)) + return; + if (!tb_switch_is_usb4(sw)) + return; + if (usb4_switch_credits_init(sw)) + tb_sw_info(sw, "failed to determine preferred buffer allocation, using defaults\n"); +} + /** * tb_switch_add() - Add a switch to the domain * @sw: Switch to add @@ -2559,6 +2722,8 @@ int tb_switch_add(struct tb_switch *sw) } if (!sw->safe_mode) { + tb_switch_credits_init(sw); + /* read drom */ ret = tb_drom_read(sw); if (ret) { @@ -2612,11 +2777,16 @@ int tb_switch_add(struct tb_switch *sw) sw->device_name); } + ret = usb4_switch_add_ports(sw); + if (ret) { + dev_err(&sw->dev, "failed to add USB4 ports\n"); + goto err_del; + } + ret = tb_switch_nvm_add(sw); if (ret) { dev_err(&sw->dev, "failed to add NVM devices\n"); - device_del(&sw->dev); - return ret; + goto err_ports; } /* @@ -2637,6 +2807,13 @@ int tb_switch_add(struct tb_switch *sw) tb_switch_debugfs_init(sw); return 0; + +err_ports: + usb4_switch_remove_ports(sw); +err_del: + device_del(&sw->dev); + + return ret; } /** @@ -2676,6 +2853,7 @@ void tb_switch_remove(struct tb_switch *sw) tb_plug_events_active(sw, false); tb_switch_nvm_remove(sw); + usb4_switch_remove_ports(sw); if (tb_route(sw)) dev_info(&sw->dev, "device disconnected\n"); @@ -2773,22 +2951,11 @@ int tb_switch_resume(struct tb_switch *sw) /* check for surviving downstream switches */ tb_switch_for_each_port(sw, port) { - if (!tb_port_has_remote(port) && !port->xdomain) { - /* - * For disconnected downstream lane adapters - * start lane initialization now so we detect - * future connects. - */ - if (!tb_is_upstream_port(port) && tb_port_is_null(port)) - tb_port_start_lane_initialization(port); + if (!tb_port_is_null(port)) + continue; + + if (!tb_port_resume(port)) continue; - } else if (port->xdomain) { - /* - * Start lane initialization for XDomain so the - * link gets re-established. - */ - tb_port_start_lane_initialization(port); - } if (tb_wait_for_port(port, true) <= 0) { tb_port_warn(port, @@ -2797,7 +2964,7 @@ int tb_switch_resume(struct tb_switch *sw) tb_sw_set_unplugged(port->remote->sw); else if (port->xdomain) port->xdomain->is_unplugged = true; - } else if (tb_port_has_remote(port) || port->xdomain) { + } else { /* * Always unlock the port so the downstream * switch/domain is accessible. @@ -2844,7 +3011,8 @@ void tb_switch_suspend(struct tb_switch *sw, bool runtime) if (runtime) { /* Trigger wake when something is plugged in/out */ flags |= TB_WAKE_ON_CONNECT | TB_WAKE_ON_DISCONNECT; - flags |= TB_WAKE_ON_USB4 | TB_WAKE_ON_USB3 | TB_WAKE_ON_PCIE; + flags |= TB_WAKE_ON_USB4; + flags |= TB_WAKE_ON_USB3 | TB_WAKE_ON_PCIE | TB_WAKE_ON_DP; } else if (device_may_wakeup(&sw->dev)) { flags |= TB_WAKE_ON_USB4 | TB_WAKE_ON_USB3 | TB_WAKE_ON_PCIE; } diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index 7e6dc2b03bed..2897a77d44c3 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -10,6 +10,7 @@ #include <linux/errno.h> #include <linux/delay.h> #include <linux/pm_runtime.h> +#include <linux/platform_data/x86/apple.h> #include "tb.h" #include "tb_regs.h" @@ -595,7 +596,7 @@ static void tb_scan_port(struct tb_port *port) return; } - tb_retimer_scan(port); + tb_retimer_scan(port, true); sw = tb_switch_alloc(port->sw->tb, &port->sw->dev, tb_downstream_route(port)); @@ -662,7 +663,7 @@ static void tb_scan_port(struct tb_port *port) tb_sw_warn(sw, "failed to enable TMU\n"); /* Scan upstream retimers */ - tb_retimer_scan(upstream_port); + tb_retimer_scan(upstream_port, true); /* * Create USB 3.x tunnels only when the switch is plugged to the @@ -1571,6 +1572,69 @@ static const struct tb_cm_ops tb_cm_ops = { .disconnect_xdomain_paths = tb_disconnect_xdomain_paths, }; +/* + * During suspend the Thunderbolt controller is reset and all PCIe + * tunnels are lost. The NHI driver will try to reestablish all tunnels + * during resume. This adds device links between the tunneled PCIe + * downstream ports and the NHI so that the device core will make sure + * NHI is resumed first before the rest. + */ +static void tb_apple_add_links(struct tb_nhi *nhi) +{ + struct pci_dev *upstream, *pdev; + + if (!x86_apple_machine) + return; + + switch (nhi->pdev->device) { + case PCI_DEVICE_ID_INTEL_LIGHT_RIDGE: + case PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C: + case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI: + case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI: + break; + default: + return; + } + + upstream = pci_upstream_bridge(nhi->pdev); + while (upstream) { + if (!pci_is_pcie(upstream)) + return; + if (pci_pcie_type(upstream) == PCI_EXP_TYPE_UPSTREAM) + break; + upstream = pci_upstream_bridge(upstream); + } + + if (!upstream) + return; + + /* + * For each hotplug downstream port, create add device link + * back to NHI so that PCIe tunnels can be re-established after + * sleep. + */ + for_each_pci_bridge(pdev, upstream->subordinate) { + const struct device_link *link; + + if (!pci_is_pcie(pdev)) + continue; + if (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM || + !pdev->is_hotplug_bridge) + continue; + + link = device_link_add(&pdev->dev, &nhi->pdev->dev, + DL_FLAG_AUTOREMOVE_SUPPLIER | + DL_FLAG_PM_RUNTIME); + if (link) { + dev_dbg(&nhi->pdev->dev, "created link from %s\n", + dev_name(&pdev->dev)); + } else { + dev_warn(&nhi->pdev->dev, "device link creation from %s failed\n", + dev_name(&pdev->dev)); + } + } +} + struct tb *tb_probe(struct tb_nhi *nhi) { struct tb_cm *tcm; @@ -1594,5 +1658,8 @@ struct tb *tb_probe(struct tb_nhi *nhi) tb_dbg(tb, "using software connection manager\n"); + tb_apple_add_links(nhi); + tb_acpi_add_links(nhi); + return tb; } diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index 9790e9f13d2b..725104c83e3d 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -20,6 +20,7 @@ #define NVM_MIN_SIZE SZ_32K #define NVM_MAX_SIZE SZ_512K +#define NVM_DATA_DWORDS 16 /* Intel specific NVM offsets */ #define NVM_DEVID 0x05 @@ -57,6 +58,12 @@ struct tb_nvm { bool flushed; }; +enum tb_nvm_write_ops { + WRITE_AND_AUTHENTICATE = 1, + WRITE_ONLY = 2, + AUTHENTICATE_ONLY = 3, +}; + #define TB_SWITCH_KEY_SIZE 32 #define TB_SWITCH_MAX_DEPTH 6 #define USB4_SWITCH_MAX_DEPTH 5 @@ -135,6 +142,12 @@ struct tb_switch_tmu { * @rpm_complete: Completion used to wait for runtime resume to * complete (ICM only) * @quirks: Quirks used for this Thunderbolt switch + * @credit_allocation: Are the below buffer allocation parameters valid + * @max_usb3_credits: Router preferred number of buffers for USB 3.x + * @min_dp_aux_credits: Router preferred minimum number of buffers for DP AUX + * @min_dp_main_credits: Router preferred minimum number of buffers for DP MAIN + * @max_pcie_credits: Router preferred number of buffers for PCIe + * @max_dma_credits: Router preferred number of buffers for DMA/P2P * * When the switch is being added or removed to the domain (other * switches) you need to have domain lock held. @@ -177,6 +190,12 @@ struct tb_switch { u8 depth; struct completion rpm_complete; unsigned long quirks; + bool credit_allocation; + unsigned int max_usb3_credits; + unsigned int min_dp_aux_credits; + unsigned int min_dp_main_credits; + unsigned int max_pcie_credits; + unsigned int max_dma_credits; }; /** @@ -189,6 +208,7 @@ struct tb_switch { * @cap_tmu: Offset of the adapter specific TMU capability (%0 if not present) * @cap_adap: Offset of the adapter specific capability (%0 if not present) * @cap_usb4: Offset to the USB4 port capability (%0 if not present) + * @usb4: Pointer to the USB4 port structure (only if @cap_usb4 is != %0) * @port: Port number on switch * @disabled: Disabled by eeprom or enabled but not implemented * @bonded: true if the port is bonded (two lanes combined as one) @@ -198,6 +218,10 @@ struct tb_switch { * @in_hopids: Currently allocated input HopIDs * @out_hopids: Currently allocated output HopIDs * @list: Used to link ports to DP resources list + * @total_credits: Total number of buffers available for this port + * @ctl_credits: Buffers reserved for control path + * @dma_credits: Number of credits allocated for DMA tunneling for all + * DMA paths through this port. * * In USB4 terminology this structure represents an adapter (protocol or * lane adapter). @@ -211,6 +235,7 @@ struct tb_port { int cap_tmu; int cap_adap; int cap_usb4; + struct usb4_port *usb4; u8 port; bool disabled; bool bonded; @@ -219,6 +244,24 @@ struct tb_port { struct ida in_hopids; struct ida out_hopids; struct list_head list; + unsigned int total_credits; + unsigned int ctl_credits; + unsigned int dma_credits; +}; + +/** + * struct usb4_port - USB4 port device + * @dev: Device for the port + * @port: Pointer to the lane 0 adapter + * @can_offline: Does the port have necessary platform support to moved + * it into offline mode and back + * @offline: The port is currently in offline mode + */ +struct usb4_port { + struct device dev; + struct tb_port *port; + bool can_offline; + bool offline; }; /** @@ -255,6 +298,8 @@ struct tb_retimer { * @next_hop_index: HopID of the packet when it is routed out from @out_port * @initial_credits: Number of initial flow control credits allocated for * the path + * @nfc_credits: Number of non-flow controlled buffers allocated for the + * @in_port. * * Hop configuration is always done on the IN port of a switch. * in_port and out_port have to be on the same switch. Packets arriving on @@ -274,6 +319,7 @@ struct tb_path_hop { int in_counter_index; int next_hop_index; unsigned int initial_credits; + unsigned int nfc_credits; }; /** @@ -296,7 +342,6 @@ enum tb_path_port { * struct tb_path - a unidirectional path between two ports * @tb: Pointer to the domain structure * @name: Name of the path (used for debugging) - * @nfc_credits: Number of non flow controlled credits allocated for the path * @ingress_shared_buffer: Shared buffering used for ingress ports on the path * @egress_shared_buffer: Shared buffering used for egress ports on the path * @ingress_fc_enable: Flow control for ingress ports on the path @@ -317,7 +362,6 @@ enum tb_path_port { struct tb_path { struct tb *tb; const char *name; - int nfc_credits; enum tb_path_port ingress_shared_buffer; enum tb_path_port egress_shared_buffer; enum tb_path_port ingress_fc_enable; @@ -346,6 +390,7 @@ struct tb_path { #define TB_WAKE_ON_USB4 BIT(2) #define TB_WAKE_ON_USB3 BIT(3) #define TB_WAKE_ON_PCIE BIT(4) +#define TB_WAKE_ON_DP BIT(5) /** * struct tb_cm_ops - Connection manager specific operations vector @@ -623,6 +668,7 @@ struct tb *tb_probe(struct tb_nhi *nhi); extern struct device_type tb_domain_type; extern struct device_type tb_retimer_type; extern struct device_type tb_switch_type; +extern struct device_type usb4_port_device_type; int tb_domain_init(void); void tb_domain_exit(void); @@ -674,6 +720,16 @@ int tb_nvm_add_non_active(struct tb_nvm *nvm, size_t size, void tb_nvm_free(struct tb_nvm *nvm); void tb_nvm_exit(void); +typedef int (*read_block_fn)(void *, unsigned int, void *, size_t); +typedef int (*write_block_fn)(void *, unsigned int, const void *, size_t); + +int tb_nvm_read_data(unsigned int address, void *buf, size_t size, + unsigned int retries, read_block_fn read_block, + void *read_block_data); +int tb_nvm_write_data(unsigned int address, const void *buf, size_t size, + unsigned int retries, write_block_fn write_next_block, + void *write_block_data); + struct tb_switch *tb_switch_alloc(struct tb *tb, struct device *parent, u64 route); struct tb_switch *tb_switch_alloc_safe_mode(struct tb *tb, @@ -853,6 +909,11 @@ void tb_port_release_out_hopid(struct tb_port *port, int hopid); struct tb_port *tb_next_port_on_path(struct tb_port *start, struct tb_port *end, struct tb_port *prev); +static inline bool tb_port_use_credit_allocation(const struct tb_port *port) +{ + return tb_port_is_null(port) && port->sw->credit_allocation; +} + /** * tb_for_each_port_on_path() - Iterate over each port on path * @src: Source port @@ -870,6 +931,9 @@ int tb_port_get_link_width(struct tb_port *port); int tb_port_state(struct tb_port *port); int tb_port_lane_bonding_enable(struct tb_port *port); void tb_port_lane_bonding_disable(struct tb_port *port); +int tb_port_wait_for_link_width(struct tb_port *port, int width, + int timeout_msec); +int tb_port_update_credits(struct tb_port *port); int tb_switch_find_vse_cap(struct tb_switch *sw, enum tb_switch_vse_cap vsec); int tb_switch_find_cap(struct tb_switch *sw, enum tb_switch_cap cap); @@ -904,6 +968,17 @@ bool tb_path_is_invalid(struct tb_path *path); bool tb_path_port_on_path(const struct tb_path *path, const struct tb_port *port); +/** + * tb_path_for_each_hop() - Iterate over each hop on path + * @path: Path whose hops to iterate + * @hop: Hop used as iterator + * + * Iterates over each hop on path. + */ +#define tb_path_for_each_hop(path, hop) \ + for ((hop) = &(path)->hops[0]; \ + (hop) <= &(path)->hops[(path)->path_length - 1]; (hop)++) + int tb_drom_read(struct tb_switch *sw); int tb_drom_read_uid_only(struct tb_switch *sw, u64 *uid); @@ -950,7 +1025,7 @@ void tb_xdomain_remove(struct tb_xdomain *xd); struct tb_xdomain *tb_xdomain_find_by_link_depth(struct tb *tb, u8 link, u8 depth); -int tb_retimer_scan(struct tb_port *port); +int tb_retimer_scan(struct tb_port *port, bool add); void tb_retimer_remove_all(struct tb_port *port); static inline bool tb_is_retimer(const struct device *dev) @@ -975,10 +1050,12 @@ int usb4_switch_set_sleep(struct tb_switch *sw); int usb4_switch_nvm_sector_size(struct tb_switch *sw); int usb4_switch_nvm_read(struct tb_switch *sw, unsigned int address, void *buf, size_t size); +int usb4_switch_nvm_set_offset(struct tb_switch *sw, unsigned int address); int usb4_switch_nvm_write(struct tb_switch *sw, unsigned int address, const void *buf, size_t size); int usb4_switch_nvm_authenticate(struct tb_switch *sw); int usb4_switch_nvm_authenticate_status(struct tb_switch *sw, u32 *status); +int usb4_switch_credits_init(struct tb_switch *sw); bool usb4_switch_query_dp_resource(struct tb_switch *sw, struct tb_port *in); int usb4_switch_alloc_dp_resource(struct tb_switch *sw, struct tb_port *in); int usb4_switch_dealloc_dp_resource(struct tb_switch *sw, struct tb_port *in); @@ -986,20 +1063,27 @@ struct tb_port *usb4_switch_map_pcie_down(struct tb_switch *sw, const struct tb_port *port); struct tb_port *usb4_switch_map_usb3_down(struct tb_switch *sw, const struct tb_port *port); +int usb4_switch_add_ports(struct tb_switch *sw); +void usb4_switch_remove_ports(struct tb_switch *sw); int usb4_port_unlock(struct tb_port *port); int usb4_port_configure(struct tb_port *port); void usb4_port_unconfigure(struct tb_port *port); int usb4_port_configure_xdomain(struct tb_port *port); void usb4_port_unconfigure_xdomain(struct tb_port *port); +int usb4_port_router_offline(struct tb_port *port); +int usb4_port_router_online(struct tb_port *port); int usb4_port_enumerate_retimers(struct tb_port *port); +int usb4_port_retimer_set_inbound_sbtx(struct tb_port *port, u8 index); int usb4_port_retimer_read(struct tb_port *port, u8 index, u8 reg, void *buf, u8 size); int usb4_port_retimer_write(struct tb_port *port, u8 index, u8 reg, const void *buf, u8 size); int usb4_port_retimer_is_last(struct tb_port *port, u8 index); int usb4_port_retimer_nvm_sector_size(struct tb_port *port, u8 index); +int usb4_port_retimer_nvm_set_offset(struct tb_port *port, u8 index, + unsigned int address); int usb4_port_retimer_nvm_write(struct tb_port *port, u8 index, unsigned int address, const void *buf, size_t size); @@ -1018,6 +1102,22 @@ int usb4_usb3_port_allocate_bandwidth(struct tb_port *port, int *upstream_bw, int usb4_usb3_port_release_bandwidth(struct tb_port *port, int *upstream_bw, int *downstream_bw); +static inline bool tb_is_usb4_port_device(const struct device *dev) +{ + return dev->type == &usb4_port_device_type; +} + +static inline struct usb4_port *tb_to_usb4_port_device(struct device *dev) +{ + if (tb_is_usb4_port_device(dev)) + return container_of(dev, struct usb4_port, dev); + return NULL; +} + +struct usb4_port *usb4_port_device_add(struct tb_port *port); +void usb4_port_device_remove(struct usb4_port *usb4); +int usb4_port_device_resume(struct usb4_port *usb4); + /* Keep link controller awake during update */ #define QUIRK_FORCE_POWER_LINK_CONTROLLER BIT(0) @@ -1031,6 +1131,11 @@ bool tb_acpi_may_tunnel_usb3(void); bool tb_acpi_may_tunnel_dp(void); bool tb_acpi_may_tunnel_pcie(void); bool tb_acpi_is_xdomain_allowed(void); + +int tb_acpi_init(void); +void tb_acpi_exit(void); +int tb_acpi_power_on_retimers(struct tb_port *port); +int tb_acpi_power_off_retimers(struct tb_port *port); #else static inline void tb_acpi_add_links(struct tb_nhi *nhi) { } @@ -1039,6 +1144,11 @@ static inline bool tb_acpi_may_tunnel_usb3(void) { return true; } static inline bool tb_acpi_may_tunnel_dp(void) { return true; } static inline bool tb_acpi_may_tunnel_pcie(void) { return true; } static inline bool tb_acpi_is_xdomain_allowed(void) { return true; } + +static inline int tb_acpi_init(void) { return 0; } +static inline void tb_acpi_exit(void) { } +static inline int tb_acpi_power_on_retimers(struct tb_port *port) { return 0; } +static inline int tb_acpi_power_off_retimers(struct tb_port *port) { return 0; } #endif #ifdef CONFIG_DEBUG_FS diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h index 626751e06292..484f25be2849 100644 --- a/drivers/thunderbolt/tb_regs.h +++ b/drivers/thunderbolt/tb_regs.h @@ -195,6 +195,7 @@ struct tb_regs_switch_header { #define ROUTER_CS_5_SLP BIT(0) #define ROUTER_CS_5_WOP BIT(1) #define ROUTER_CS_5_WOU BIT(2) +#define ROUTER_CS_5_WOD BIT(3) #define ROUTER_CS_5_C3S BIT(23) #define ROUTER_CS_5_PTO BIT(24) #define ROUTER_CS_5_UTO BIT(25) @@ -228,6 +229,7 @@ enum usb4_switch_op { USB4_SWITCH_OP_NVM_SET_OFFSET = 0x23, USB4_SWITCH_OP_DROM_READ = 0x24, USB4_SWITCH_OP_NVM_SECTOR_SIZE = 0x25, + USB4_SWITCH_OP_BUFFER_ALLOC = 0x33, }; /* Router TMU configuration */ @@ -458,6 +460,8 @@ struct tb_regs_hop { #define TB_LC_SX_CTRL 0x96 #define TB_LC_SX_CTRL_WOC BIT(1) #define TB_LC_SX_CTRL_WOD BIT(2) +#define TB_LC_SX_CTRL_WODPC BIT(3) +#define TB_LC_SX_CTRL_WODPD BIT(4) #define TB_LC_SX_CTRL_WOU4 BIT(5) #define TB_LC_SX_CTRL_WOP BIT(6) #define TB_LC_SX_CTRL_L1C BIT(16) diff --git a/drivers/thunderbolt/test.c b/drivers/thunderbolt/test.c index 3cc36ef639f3..eca0ef311bde 100644 --- a/drivers/thunderbolt/test.c +++ b/drivers/thunderbolt/test.c @@ -87,22 +87,30 @@ static struct tb_switch *alloc_host(struct kunit *test) sw->ports[1].config.type = TB_TYPE_PORT; sw->ports[1].config.max_in_hop_id = 19; sw->ports[1].config.max_out_hop_id = 19; + sw->ports[1].total_credits = 60; + sw->ports[1].ctl_credits = 2; sw->ports[1].dual_link_port = &sw->ports[2]; sw->ports[2].config.type = TB_TYPE_PORT; sw->ports[2].config.max_in_hop_id = 19; sw->ports[2].config.max_out_hop_id = 19; + sw->ports[2].total_credits = 60; + sw->ports[2].ctl_credits = 2; sw->ports[2].dual_link_port = &sw->ports[1]; sw->ports[2].link_nr = 1; sw->ports[3].config.type = TB_TYPE_PORT; sw->ports[3].config.max_in_hop_id = 19; sw->ports[3].config.max_out_hop_id = 19; + sw->ports[3].total_credits = 60; + sw->ports[3].ctl_credits = 2; sw->ports[3].dual_link_port = &sw->ports[4]; sw->ports[4].config.type = TB_TYPE_PORT; sw->ports[4].config.max_in_hop_id = 19; sw->ports[4].config.max_out_hop_id = 19; + sw->ports[4].total_credits = 60; + sw->ports[4].ctl_credits = 2; sw->ports[4].dual_link_port = &sw->ports[3]; sw->ports[4].link_nr = 1; @@ -143,6 +151,25 @@ static struct tb_switch *alloc_host(struct kunit *test) return sw; } +static struct tb_switch *alloc_host_usb4(struct kunit *test) +{ + struct tb_switch *sw; + + sw = alloc_host(test); + if (!sw) + return NULL; + + sw->generation = 4; + sw->credit_allocation = true; + sw->max_usb3_credits = 32; + sw->min_dp_aux_credits = 1; + sw->min_dp_main_credits = 0; + sw->max_pcie_credits = 64; + sw->max_dma_credits = 14; + + return sw; +} + static struct tb_switch *alloc_dev_default(struct kunit *test, struct tb_switch *parent, u64 route, bool bonded) @@ -164,44 +191,60 @@ static struct tb_switch *alloc_dev_default(struct kunit *test, sw->ports[1].config.type = TB_TYPE_PORT; sw->ports[1].config.max_in_hop_id = 19; sw->ports[1].config.max_out_hop_id = 19; + sw->ports[1].total_credits = 60; + sw->ports[1].ctl_credits = 2; sw->ports[1].dual_link_port = &sw->ports[2]; sw->ports[2].config.type = TB_TYPE_PORT; sw->ports[2].config.max_in_hop_id = 19; sw->ports[2].config.max_out_hop_id = 19; + sw->ports[2].total_credits = 60; + sw->ports[2].ctl_credits = 2; sw->ports[2].dual_link_port = &sw->ports[1]; sw->ports[2].link_nr = 1; sw->ports[3].config.type = TB_TYPE_PORT; sw->ports[3].config.max_in_hop_id = 19; sw->ports[3].config.max_out_hop_id = 19; + sw->ports[3].total_credits = 60; + sw->ports[3].ctl_credits = 2; sw->ports[3].dual_link_port = &sw->ports[4]; sw->ports[4].config.type = TB_TYPE_PORT; sw->ports[4].config.max_in_hop_id = 19; sw->ports[4].config.max_out_hop_id = 19; + sw->ports[4].total_credits = 60; + sw->ports[4].ctl_credits = 2; sw->ports[4].dual_link_port = &sw->ports[3]; sw->ports[4].link_nr = 1; sw->ports[5].config.type = TB_TYPE_PORT; sw->ports[5].config.max_in_hop_id = 19; sw->ports[5].config.max_out_hop_id = 19; + sw->ports[5].total_credits = 60; + sw->ports[5].ctl_credits = 2; sw->ports[5].dual_link_port = &sw->ports[6]; sw->ports[6].config.type = TB_TYPE_PORT; sw->ports[6].config.max_in_hop_id = 19; sw->ports[6].config.max_out_hop_id = 19; + sw->ports[6].total_credits = 60; + sw->ports[6].ctl_credits = 2; sw->ports[6].dual_link_port = &sw->ports[5]; sw->ports[6].link_nr = 1; sw->ports[7].config.type = TB_TYPE_PORT; sw->ports[7].config.max_in_hop_id = 19; sw->ports[7].config.max_out_hop_id = 19; + sw->ports[7].total_credits = 60; + sw->ports[7].ctl_credits = 2; sw->ports[7].dual_link_port = &sw->ports[8]; sw->ports[8].config.type = TB_TYPE_PORT; sw->ports[8].config.max_in_hop_id = 19; sw->ports[8].config.max_out_hop_id = 19; + sw->ports[8].total_credits = 60; + sw->ports[8].ctl_credits = 2; sw->ports[8].dual_link_port = &sw->ports[7]; sw->ports[8].link_nr = 1; @@ -260,14 +303,18 @@ static struct tb_switch *alloc_dev_default(struct kunit *test, if (port->dual_link_port && upstream_port->dual_link_port) { port->dual_link_port->remote = upstream_port->dual_link_port; upstream_port->dual_link_port->remote = port->dual_link_port; - } - if (bonded) { - /* Bonding is used */ - port->bonded = true; - port->dual_link_port->bonded = true; - upstream_port->bonded = true; - upstream_port->dual_link_port->bonded = true; + if (bonded) { + /* Bonding is used */ + port->bonded = true; + port->total_credits *= 2; + port->dual_link_port->bonded = true; + port->dual_link_port->total_credits = 0; + upstream_port->bonded = true; + upstream_port->total_credits *= 2; + upstream_port->dual_link_port->bonded = true; + upstream_port->dual_link_port->total_credits = 0; + } } return sw; @@ -294,6 +341,27 @@ static struct tb_switch *alloc_dev_with_dpin(struct kunit *test, return sw; } +static struct tb_switch *alloc_dev_usb4(struct kunit *test, + struct tb_switch *parent, + u64 route, bool bonded) +{ + struct tb_switch *sw; + + sw = alloc_dev_default(test, parent, route, bonded); + if (!sw) + return NULL; + + sw->generation = 4; + sw->credit_allocation = true; + sw->max_usb3_credits = 14; + sw->min_dp_aux_credits = 1; + sw->min_dp_main_credits = 18; + sw->max_pcie_credits = 32; + sw->max_dma_credits = 14; + + return sw; +} + static void tb_test_path_basic(struct kunit *test) { struct tb_port *src_port, *dst_port, *p; @@ -1829,6 +1897,475 @@ static void tb_test_tunnel_dma_match(struct kunit *test) tb_tunnel_free(tunnel); } +static void tb_test_credit_alloc_legacy_not_bonded(struct kunit *test) +{ + struct tb_switch *host, *dev; + struct tb_port *up, *down; + struct tb_tunnel *tunnel; + struct tb_path *path; + + host = alloc_host(test); + dev = alloc_dev_default(test, host, 0x1, false); + + down = &host->ports[8]; + up = &dev->ports[9]; + tunnel = tb_tunnel_alloc_pci(NULL, up, down); + KUNIT_ASSERT_TRUE(test, tunnel != NULL); + KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)2); + + path = tunnel->paths[0]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 16U); + + path = tunnel->paths[1]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 16U); + + tb_tunnel_free(tunnel); +} + +static void tb_test_credit_alloc_legacy_bonded(struct kunit *test) +{ + struct tb_switch *host, *dev; + struct tb_port *up, *down; + struct tb_tunnel *tunnel; + struct tb_path *path; + + host = alloc_host(test); + dev = alloc_dev_default(test, host, 0x1, true); + + down = &host->ports[8]; + up = &dev->ports[9]; + tunnel = tb_tunnel_alloc_pci(NULL, up, down); + KUNIT_ASSERT_TRUE(test, tunnel != NULL); + KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)2); + + path = tunnel->paths[0]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 32U); + + path = tunnel->paths[1]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 32U); + + tb_tunnel_free(tunnel); +} + +static void tb_test_credit_alloc_pcie(struct kunit *test) +{ + struct tb_switch *host, *dev; + struct tb_port *up, *down; + struct tb_tunnel *tunnel; + struct tb_path *path; + + host = alloc_host_usb4(test); + dev = alloc_dev_usb4(test, host, 0x1, true); + + down = &host->ports[8]; + up = &dev->ports[9]; + tunnel = tb_tunnel_alloc_pci(NULL, up, down); + KUNIT_ASSERT_TRUE(test, tunnel != NULL); + KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)2); + + path = tunnel->paths[0]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 32U); + + path = tunnel->paths[1]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 64U); + + tb_tunnel_free(tunnel); +} + +static void tb_test_credit_alloc_dp(struct kunit *test) +{ + struct tb_switch *host, *dev; + struct tb_port *in, *out; + struct tb_tunnel *tunnel; + struct tb_path *path; + + host = alloc_host_usb4(test); + dev = alloc_dev_usb4(test, host, 0x1, true); + + in = &host->ports[5]; + out = &dev->ports[14]; + + tunnel = tb_tunnel_alloc_dp(NULL, in, out, 0, 0); + KUNIT_ASSERT_TRUE(test, tunnel != NULL); + KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)3); + + /* Video (main) path */ + path = tunnel->paths[0]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 12U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 18U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 0U); + + /* AUX TX */ + path = tunnel->paths[1]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 1U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); + + /* AUX RX */ + path = tunnel->paths[2]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 1U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); + + tb_tunnel_free(tunnel); +} + +static void tb_test_credit_alloc_usb3(struct kunit *test) +{ + struct tb_switch *host, *dev; + struct tb_port *up, *down; + struct tb_tunnel *tunnel; + struct tb_path *path; + + host = alloc_host_usb4(test); + dev = alloc_dev_usb4(test, host, 0x1, true); + + down = &host->ports[12]; + up = &dev->ports[16]; + tunnel = tb_tunnel_alloc_usb3(NULL, up, down, 0, 0); + KUNIT_ASSERT_TRUE(test, tunnel != NULL); + KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)2); + + path = tunnel->paths[0]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); + + path = tunnel->paths[1]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 32U); + + tb_tunnel_free(tunnel); +} + +static void tb_test_credit_alloc_dma(struct kunit *test) +{ + struct tb_switch *host, *dev; + struct tb_port *nhi, *port; + struct tb_tunnel *tunnel; + struct tb_path *path; + + host = alloc_host_usb4(test); + dev = alloc_dev_usb4(test, host, 0x1, true); + + nhi = &host->ports[7]; + port = &dev->ports[3]; + + tunnel = tb_tunnel_alloc_dma(NULL, nhi, port, 8, 1, 8, 1); + KUNIT_ASSERT_TRUE(test, tunnel != NULL); + KUNIT_ASSERT_EQ(test, tunnel->npaths, (size_t)2); + + /* DMA RX */ + path = tunnel->paths[0]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 14U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); + + /* DMA TX */ + path = tunnel->paths[1]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); + + tb_tunnel_free(tunnel); +} + +static void tb_test_credit_alloc_dma_multiple(struct kunit *test) +{ + struct tb_tunnel *tunnel1, *tunnel2, *tunnel3; + struct tb_switch *host, *dev; + struct tb_port *nhi, *port; + struct tb_path *path; + + host = alloc_host_usb4(test); + dev = alloc_dev_usb4(test, host, 0x1, true); + + nhi = &host->ports[7]; + port = &dev->ports[3]; + + /* + * Create three DMA tunnels through the same ports. With the + * default buffers we should be able to create two and the last + * one fails. + * + * For default host we have following buffers for DMA: + * + * 120 - (2 + 2 * (1 + 0) + 32 + 64 + spare) = 20 + * + * For device we have following: + * + * 120 - (2 + 2 * (1 + 18) + 14 + 32 + spare) = 34 + * + * spare = 14 + 1 = 15 + * + * So on host the first tunnel gets 14 and the second gets the + * remaining 1 and then we run out of buffers. + */ + tunnel1 = tb_tunnel_alloc_dma(NULL, nhi, port, 8, 1, 8, 1); + KUNIT_ASSERT_TRUE(test, tunnel1 != NULL); + KUNIT_ASSERT_EQ(test, tunnel1->npaths, (size_t)2); + + path = tunnel1->paths[0]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 14U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); + + path = tunnel1->paths[1]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); + + tunnel2 = tb_tunnel_alloc_dma(NULL, nhi, port, 9, 2, 9, 2); + KUNIT_ASSERT_TRUE(test, tunnel2 != NULL); + KUNIT_ASSERT_EQ(test, tunnel2->npaths, (size_t)2); + + path = tunnel2->paths[0]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 14U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); + + path = tunnel2->paths[1]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); + + tunnel3 = tb_tunnel_alloc_dma(NULL, nhi, port, 10, 3, 10, 3); + KUNIT_ASSERT_TRUE(test, tunnel3 == NULL); + + /* + * Release the first DMA tunnel. That should make 14 buffers + * available for the next tunnel. + */ + tb_tunnel_free(tunnel1); + + tunnel3 = tb_tunnel_alloc_dma(NULL, nhi, port, 10, 3, 10, 3); + KUNIT_ASSERT_TRUE(test, tunnel3 != NULL); + + path = tunnel3->paths[0]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 14U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); + + path = tunnel3->paths[1]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); + + tb_tunnel_free(tunnel3); + tb_tunnel_free(tunnel2); +} + +static void tb_test_credit_alloc_all(struct kunit *test) +{ + struct tb_port *up, *down, *in, *out, *nhi, *port; + struct tb_tunnel *pcie_tunnel, *dp_tunnel1, *dp_tunnel2, *usb3_tunnel; + struct tb_tunnel *dma_tunnel1, *dma_tunnel2; + struct tb_switch *host, *dev; + struct tb_path *path; + + /* + * Create PCIe, 2 x DP, USB 3.x and two DMA tunnels from host to + * device. Expectation is that all these can be established with + * the default credit allocation found in Intel hardware. + */ + + host = alloc_host_usb4(test); + dev = alloc_dev_usb4(test, host, 0x1, true); + + down = &host->ports[8]; + up = &dev->ports[9]; + pcie_tunnel = tb_tunnel_alloc_pci(NULL, up, down); + KUNIT_ASSERT_TRUE(test, pcie_tunnel != NULL); + KUNIT_ASSERT_EQ(test, pcie_tunnel->npaths, (size_t)2); + + path = pcie_tunnel->paths[0]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 32U); + + path = pcie_tunnel->paths[1]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 64U); + + in = &host->ports[5]; + out = &dev->ports[13]; + + dp_tunnel1 = tb_tunnel_alloc_dp(NULL, in, out, 0, 0); + KUNIT_ASSERT_TRUE(test, dp_tunnel1 != NULL); + KUNIT_ASSERT_EQ(test, dp_tunnel1->npaths, (size_t)3); + + path = dp_tunnel1->paths[0]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 12U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 18U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 0U); + + path = dp_tunnel1->paths[1]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 1U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); + + path = dp_tunnel1->paths[2]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 1U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); + + in = &host->ports[6]; + out = &dev->ports[14]; + + dp_tunnel2 = tb_tunnel_alloc_dp(NULL, in, out, 0, 0); + KUNIT_ASSERT_TRUE(test, dp_tunnel2 != NULL); + KUNIT_ASSERT_EQ(test, dp_tunnel2->npaths, (size_t)3); + + path = dp_tunnel2->paths[0]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 12U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 18U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 0U); + + path = dp_tunnel2->paths[1]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 1U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); + + path = dp_tunnel2->paths[2]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 1U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); + + down = &host->ports[12]; + up = &dev->ports[16]; + usb3_tunnel = tb_tunnel_alloc_usb3(NULL, up, down, 0, 0); + KUNIT_ASSERT_TRUE(test, usb3_tunnel != NULL); + KUNIT_ASSERT_EQ(test, usb3_tunnel->npaths, (size_t)2); + + path = usb3_tunnel->paths[0]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); + + path = usb3_tunnel->paths[1]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 7U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 32U); + + nhi = &host->ports[7]; + port = &dev->ports[3]; + + dma_tunnel1 = tb_tunnel_alloc_dma(NULL, nhi, port, 8, 1, 8, 1); + KUNIT_ASSERT_TRUE(test, dma_tunnel1 != NULL); + KUNIT_ASSERT_EQ(test, dma_tunnel1->npaths, (size_t)2); + + path = dma_tunnel1->paths[0]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 14U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); + + path = dma_tunnel1->paths[1]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 14U); + + dma_tunnel2 = tb_tunnel_alloc_dma(NULL, nhi, port, 9, 2, 9, 2); + KUNIT_ASSERT_TRUE(test, dma_tunnel2 != NULL); + KUNIT_ASSERT_EQ(test, dma_tunnel2->npaths, (size_t)2); + + path = dma_tunnel2->paths[0]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 14U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); + + path = dma_tunnel2->paths[1]; + KUNIT_ASSERT_EQ(test, path->path_length, 2); + KUNIT_EXPECT_EQ(test, path->hops[0].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[0].initial_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].nfc_credits, 0U); + KUNIT_EXPECT_EQ(test, path->hops[1].initial_credits, 1U); + + tb_tunnel_free(dma_tunnel2); + tb_tunnel_free(dma_tunnel1); + tb_tunnel_free(usb3_tunnel); + tb_tunnel_free(dp_tunnel2); + tb_tunnel_free(dp_tunnel1); + tb_tunnel_free(pcie_tunnel); +} + static const u32 root_directory[] = { 0x55584401, /* "UXD" v1 */ 0x00000018, /* Root directory length */ @@ -2105,6 +2642,14 @@ static struct kunit_case tb_test_cases[] = { KUNIT_CASE(tb_test_tunnel_dma_tx), KUNIT_CASE(tb_test_tunnel_dma_chain), KUNIT_CASE(tb_test_tunnel_dma_match), + KUNIT_CASE(tb_test_credit_alloc_legacy_not_bonded), + KUNIT_CASE(tb_test_credit_alloc_legacy_bonded), + KUNIT_CASE(tb_test_credit_alloc_pcie), + KUNIT_CASE(tb_test_credit_alloc_dp), + KUNIT_CASE(tb_test_credit_alloc_usb3), + KUNIT_CASE(tb_test_credit_alloc_dma), + KUNIT_CASE(tb_test_credit_alloc_dma_multiple), + KUNIT_CASE(tb_test_credit_alloc_all), KUNIT_CASE(tb_test_property_parse), KUNIT_CASE(tb_test_property_format), KUNIT_CASE(tb_test_property_copy), diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c index e1979bed7146..bb5cc480fc9a 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c @@ -34,6 +34,16 @@ #define TB_DP_AUX_PATH_OUT 1 #define TB_DP_AUX_PATH_IN 2 +/* Minimum number of credits needed for PCIe path */ +#define TB_MIN_PCIE_CREDITS 6U +/* + * Number of credits we try to allocate for each DMA path if not limited + * by the host router baMaxHI. + */ +#define TB_DMA_CREDITS 14U +/* Minimum number of credits for DMA path */ +#define TB_MIN_DMA_CREDITS 1U + static const char * const tb_tunnel_names[] = { "PCI", "DP", "DMA", "USB3" }; #define __TB_TUNNEL_PRINT(level, tunnel, fmt, arg...) \ @@ -57,6 +67,55 @@ static const char * const tb_tunnel_names[] = { "PCI", "DP", "DMA", "USB3" }; #define tb_tunnel_dbg(tunnel, fmt, arg...) \ __TB_TUNNEL_PRINT(tb_dbg, tunnel, fmt, ##arg) +static inline unsigned int tb_usable_credits(const struct tb_port *port) +{ + return port->total_credits - port->ctl_credits; +} + +/** + * tb_available_credits() - Available credits for PCIe and DMA + * @port: Lane adapter to check + * @max_dp_streams: If non-%NULL stores maximum number of simultaneous DP + * streams possible through this lane adapter + */ +static unsigned int tb_available_credits(const struct tb_port *port, + size_t *max_dp_streams) +{ + const struct tb_switch *sw = port->sw; + int credits, usb3, pcie, spare; + size_t ndp; + + usb3 = tb_acpi_may_tunnel_usb3() ? sw->max_usb3_credits : 0; + pcie = tb_acpi_may_tunnel_pcie() ? sw->max_pcie_credits : 0; + + if (tb_acpi_is_xdomain_allowed()) { + spare = min_not_zero(sw->max_dma_credits, TB_DMA_CREDITS); + /* Add some credits for potential second DMA tunnel */ + spare += TB_MIN_DMA_CREDITS; + } else { + spare = 0; + } + + credits = tb_usable_credits(port); + if (tb_acpi_may_tunnel_dp()) { + /* + * Maximum number of DP streams possible through the + * lane adapter. + */ + ndp = (credits - (usb3 + pcie + spare)) / + (sw->min_dp_aux_credits + sw->min_dp_main_credits); + } else { + ndp = 0; + } + credits -= ndp * (sw->min_dp_aux_credits + sw->min_dp_main_credits); + credits -= usb3; + + if (max_dp_streams) + *max_dp_streams = ndp; + + return credits > 0 ? credits : 0; +} + static struct tb_tunnel *tb_tunnel_alloc(struct tb *tb, size_t npaths, enum tb_tunnel_type type) { @@ -94,24 +153,37 @@ static int tb_pci_activate(struct tb_tunnel *tunnel, bool activate) return 0; } -static int tb_initial_credits(const struct tb_switch *sw) +static int tb_pci_init_credits(struct tb_path_hop *hop) { - /* If the path is complete sw is not NULL */ - if (sw) { - /* More credits for faster link */ - switch (sw->link_speed * sw->link_width) { - case 40: - return 32; - case 20: - return 24; - } + struct tb_port *port = hop->in_port; + struct tb_switch *sw = port->sw; + unsigned int credits; + + if (tb_port_use_credit_allocation(port)) { + unsigned int available; + + available = tb_available_credits(port, NULL); + credits = min(sw->max_pcie_credits, available); + + if (credits < TB_MIN_PCIE_CREDITS) + return -ENOSPC; + + credits = max(TB_MIN_PCIE_CREDITS, credits); + } else { + if (tb_port_is_null(port)) + credits = port->bonded ? 32 : 16; + else + credits = 7; } - return 16; + hop->initial_credits = credits; + return 0; } -static void tb_pci_init_path(struct tb_path *path) +static int tb_pci_init_path(struct tb_path *path) { + struct tb_path_hop *hop; + path->egress_fc_enable = TB_PATH_SOURCE | TB_PATH_INTERNAL; path->egress_shared_buffer = TB_PATH_NONE; path->ingress_fc_enable = TB_PATH_ALL; @@ -119,11 +191,16 @@ static void tb_pci_init_path(struct tb_path *path) path->priority = 3; path->weight = 1; path->drop_packages = 0; - path->nfc_credits = 0; - path->hops[0].initial_credits = 7; - if (path->path_length > 1) - path->hops[1].initial_credits = - tb_initial_credits(path->hops[1].in_port->sw); + + tb_path_for_each_hop(path, hop) { + int ret; + + ret = tb_pci_init_credits(hop); + if (ret) + return ret; + } + + return 0; } /** @@ -163,14 +240,16 @@ struct tb_tunnel *tb_tunnel_discover_pci(struct tb *tb, struct tb_port *down) goto err_free; } tunnel->paths[TB_PCI_PATH_UP] = path; - tb_pci_init_path(tunnel->paths[TB_PCI_PATH_UP]); + if (tb_pci_init_path(tunnel->paths[TB_PCI_PATH_UP])) + goto err_free; path = tb_path_discover(tunnel->dst_port, -1, down, TB_PCI_HOPID, NULL, "PCIe Down"); if (!path) goto err_deactivate; tunnel->paths[TB_PCI_PATH_DOWN] = path; - tb_pci_init_path(tunnel->paths[TB_PCI_PATH_DOWN]); + if (tb_pci_init_path(tunnel->paths[TB_PCI_PATH_DOWN])) + goto err_deactivate; /* Validate that the tunnel is complete */ if (!tb_port_is_pcie_up(tunnel->dst_port)) { @@ -228,23 +307,25 @@ struct tb_tunnel *tb_tunnel_alloc_pci(struct tb *tb, struct tb_port *up, path = tb_path_alloc(tb, down, TB_PCI_HOPID, up, TB_PCI_HOPID, 0, "PCIe Down"); - if (!path) { - tb_tunnel_free(tunnel); - return NULL; - } - tb_pci_init_path(path); + if (!path) + goto err_free; tunnel->paths[TB_PCI_PATH_DOWN] = path; + if (tb_pci_init_path(path)) + goto err_free; path = tb_path_alloc(tb, up, TB_PCI_HOPID, down, TB_PCI_HOPID, 0, "PCIe Up"); - if (!path) { - tb_tunnel_free(tunnel); - return NULL; - } - tb_pci_init_path(path); + if (!path) + goto err_free; tunnel->paths[TB_PCI_PATH_UP] = path; + if (tb_pci_init_path(path)) + goto err_free; return tunnel; + +err_free: + tb_tunnel_free(tunnel); + return NULL; } static bool tb_dp_is_usb4(const struct tb_switch *sw) @@ -599,9 +680,20 @@ static int tb_dp_consumed_bandwidth(struct tb_tunnel *tunnel, int *consumed_up, return 0; } +static void tb_dp_init_aux_credits(struct tb_path_hop *hop) +{ + struct tb_port *port = hop->in_port; + struct tb_switch *sw = port->sw; + + if (tb_port_use_credit_allocation(port)) + hop->initial_credits = sw->min_dp_aux_credits; + else + hop->initial_credits = 1; +} + static void tb_dp_init_aux_path(struct tb_path *path) { - int i; + struct tb_path_hop *hop; path->egress_fc_enable = TB_PATH_SOURCE | TB_PATH_INTERNAL; path->egress_shared_buffer = TB_PATH_NONE; @@ -610,13 +702,42 @@ static void tb_dp_init_aux_path(struct tb_path *path) path->priority = 2; path->weight = 1; - for (i = 0; i < path->path_length; i++) - path->hops[i].initial_credits = 1; + tb_path_for_each_hop(path, hop) + tb_dp_init_aux_credits(hop); } -static void tb_dp_init_video_path(struct tb_path *path, bool discover) +static int tb_dp_init_video_credits(struct tb_path_hop *hop) { - u32 nfc_credits = path->hops[0].in_port->config.nfc_credits; + struct tb_port *port = hop->in_port; + struct tb_switch *sw = port->sw; + + if (tb_port_use_credit_allocation(port)) { + unsigned int nfc_credits; + size_t max_dp_streams; + + tb_available_credits(port, &max_dp_streams); + /* + * Read the number of currently allocated NFC credits + * from the lane adapter. Since we only use them for DP + * tunneling we can use that to figure out how many DP + * tunnels already go through the lane adapter. + */ + nfc_credits = port->config.nfc_credits & + ADP_CS_4_NFC_BUFFERS_MASK; + if (nfc_credits / sw->min_dp_main_credits > max_dp_streams) + return -ENOSPC; + + hop->nfc_credits = sw->min_dp_main_credits; + } else { + hop->nfc_credits = min(port->total_credits - 2, 12U); + } + + return 0; +} + +static int tb_dp_init_video_path(struct tb_path *path) +{ + struct tb_path_hop *hop; path->egress_fc_enable = TB_PATH_NONE; path->egress_shared_buffer = TB_PATH_NONE; @@ -625,16 +746,15 @@ static void tb_dp_init_video_path(struct tb_path *path, bool discover) path->priority = 1; path->weight = 1; - if (discover) { - path->nfc_credits = nfc_credits & ADP_CS_4_NFC_BUFFERS_MASK; - } else { - u32 max_credits; + tb_path_for_each_hop(path, hop) { + int ret; - max_credits = (nfc_credits & ADP_CS_4_TOTAL_BUFFERS_MASK) >> - ADP_CS_4_TOTAL_BUFFERS_SHIFT; - /* Leave some credits for AUX path */ - path->nfc_credits = min(max_credits - 2, 12U); + ret = tb_dp_init_video_credits(hop); + if (ret) + return ret; } + + return 0; } /** @@ -674,7 +794,8 @@ struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb, struct tb_port *in) goto err_free; } tunnel->paths[TB_DP_VIDEO_PATH_OUT] = path; - tb_dp_init_video_path(tunnel->paths[TB_DP_VIDEO_PATH_OUT], true); + if (tb_dp_init_video_path(tunnel->paths[TB_DP_VIDEO_PATH_OUT])) + goto err_free; path = tb_path_discover(in, TB_DP_AUX_TX_HOPID, NULL, -1, NULL, "AUX TX"); if (!path) @@ -761,7 +882,7 @@ struct tb_tunnel *tb_tunnel_alloc_dp(struct tb *tb, struct tb_port *in, 1, "Video"); if (!path) goto err_free; - tb_dp_init_video_path(path, false); + tb_dp_init_video_path(path); paths[TB_DP_VIDEO_PATH_OUT] = path; path = tb_path_alloc(tb, in, TB_DP_AUX_TX_HOPID, out, @@ -785,20 +906,92 @@ err_free: return NULL; } -static u32 tb_dma_credits(struct tb_port *nhi) +static unsigned int tb_dma_available_credits(const struct tb_port *port) { - u32 max_credits; + const struct tb_switch *sw = port->sw; + int credits; - max_credits = (nhi->config.nfc_credits & ADP_CS_4_TOTAL_BUFFERS_MASK) >> - ADP_CS_4_TOTAL_BUFFERS_SHIFT; - return min(max_credits, 13U); + credits = tb_available_credits(port, NULL); + if (tb_acpi_may_tunnel_pcie()) + credits -= sw->max_pcie_credits; + credits -= port->dma_credits; + + return credits > 0 ? credits : 0; } -static void tb_dma_init_path(struct tb_path *path, unsigned int efc, u32 credits) +static int tb_dma_reserve_credits(struct tb_path_hop *hop, unsigned int credits) { - int i; + struct tb_port *port = hop->in_port; - path->egress_fc_enable = efc; + if (tb_port_use_credit_allocation(port)) { + unsigned int available = tb_dma_available_credits(port); + + /* + * Need to have at least TB_MIN_DMA_CREDITS, otherwise + * DMA path cannot be established. + */ + if (available < TB_MIN_DMA_CREDITS) + return -ENOSPC; + + while (credits > available) + credits--; + + tb_port_dbg(port, "reserving %u credits for DMA path\n", + credits); + + port->dma_credits += credits; + } else { + if (tb_port_is_null(port)) + credits = port->bonded ? 14 : 6; + else + credits = min(port->total_credits, credits); + } + + hop->initial_credits = credits; + return 0; +} + +/* Path from lane adapter to NHI */ +static int tb_dma_init_rx_path(struct tb_path *path, unsigned int credits) +{ + struct tb_path_hop *hop; + unsigned int i, tmp; + + path->egress_fc_enable = TB_PATH_SOURCE | TB_PATH_INTERNAL; + path->ingress_fc_enable = TB_PATH_ALL; + path->egress_shared_buffer = TB_PATH_NONE; + path->ingress_shared_buffer = TB_PATH_NONE; + path->priority = 5; + path->weight = 1; + path->clear_fc = true; + + /* + * First lane adapter is the one connected to the remote host. + * We don't tunnel other traffic over this link so can use all + * the credits (except the ones reserved for control traffic). + */ + hop = &path->hops[0]; + tmp = min(tb_usable_credits(hop->in_port), credits); + hop->initial_credits = tmp; + hop->in_port->dma_credits += tmp; + + for (i = 1; i < path->path_length; i++) { + int ret; + + ret = tb_dma_reserve_credits(&path->hops[i], credits); + if (ret) + return ret; + } + + return 0; +} + +/* Path from NHI to lane adapter */ +static int tb_dma_init_tx_path(struct tb_path *path, unsigned int credits) +{ + struct tb_path_hop *hop; + + path->egress_fc_enable = TB_PATH_ALL; path->ingress_fc_enable = TB_PATH_ALL; path->egress_shared_buffer = TB_PATH_NONE; path->ingress_shared_buffer = TB_PATH_NONE; @@ -806,8 +999,46 @@ static void tb_dma_init_path(struct tb_path *path, unsigned int efc, u32 credits path->weight = 1; path->clear_fc = true; - for (i = 0; i < path->path_length; i++) - path->hops[i].initial_credits = credits; + tb_path_for_each_hop(path, hop) { + int ret; + + ret = tb_dma_reserve_credits(hop, credits); + if (ret) + return ret; + } + + return 0; +} + +static void tb_dma_release_credits(struct tb_path_hop *hop) +{ + struct tb_port *port = hop->in_port; + + if (tb_port_use_credit_allocation(port)) { + port->dma_credits -= hop->initial_credits; + + tb_port_dbg(port, "released %u DMA path credits\n", + hop->initial_credits); + } +} + +static void tb_dma_deinit_path(struct tb_path *path) +{ + struct tb_path_hop *hop; + + tb_path_for_each_hop(path, hop) + tb_dma_release_credits(hop); +} + +static void tb_dma_deinit(struct tb_tunnel *tunnel) +{ + int i; + + for (i = 0; i < tunnel->npaths; i++) { + if (!tunnel->paths[i]) + continue; + tb_dma_deinit_path(tunnel->paths[i]); + } } /** @@ -832,7 +1063,7 @@ struct tb_tunnel *tb_tunnel_alloc_dma(struct tb *tb, struct tb_port *nhi, struct tb_tunnel *tunnel; size_t npaths = 0, i = 0; struct tb_path *path; - u32 credits; + int credits; if (receive_ring > 0) npaths++; @@ -848,32 +1079,39 @@ struct tb_tunnel *tb_tunnel_alloc_dma(struct tb *tb, struct tb_port *nhi, tunnel->src_port = nhi; tunnel->dst_port = dst; + tunnel->deinit = tb_dma_deinit; - credits = tb_dma_credits(nhi); + credits = min_not_zero(TB_DMA_CREDITS, nhi->sw->max_dma_credits); if (receive_ring > 0) { path = tb_path_alloc(tb, dst, receive_path, nhi, receive_ring, 0, "DMA RX"); - if (!path) { - tb_tunnel_free(tunnel); - return NULL; - } - tb_dma_init_path(path, TB_PATH_SOURCE | TB_PATH_INTERNAL, credits); + if (!path) + goto err_free; tunnel->paths[i++] = path; + if (tb_dma_init_rx_path(path, credits)) { + tb_tunnel_dbg(tunnel, "not enough buffers for RX path\n"); + goto err_free; + } } if (transmit_ring > 0) { path = tb_path_alloc(tb, nhi, transmit_ring, dst, transmit_path, 0, "DMA TX"); - if (!path) { - tb_tunnel_free(tunnel); - return NULL; - } - tb_dma_init_path(path, TB_PATH_ALL, credits); + if (!path) + goto err_free; tunnel->paths[i++] = path; + if (tb_dma_init_tx_path(path, credits)) { + tb_tunnel_dbg(tunnel, "not enough buffers for TX path\n"); + goto err_free; + } } return tunnel; + +err_free: + tb_tunnel_free(tunnel); + return NULL; } /** @@ -1067,8 +1305,28 @@ static void tb_usb3_reclaim_available_bandwidth(struct tb_tunnel *tunnel, tunnel->allocated_up, tunnel->allocated_down); } +static void tb_usb3_init_credits(struct tb_path_hop *hop) +{ + struct tb_port *port = hop->in_port; + struct tb_switch *sw = port->sw; + unsigned int credits; + + if (tb_port_use_credit_allocation(port)) { + credits = sw->max_usb3_credits; + } else { + if (tb_port_is_null(port)) + credits = port->bonded ? 32 : 16; + else + credits = 7; + } + + hop->initial_credits = credits; +} + static void tb_usb3_init_path(struct tb_path *path) { + struct tb_path_hop *hop; + path->egress_fc_enable = TB_PATH_SOURCE | TB_PATH_INTERNAL; path->egress_shared_buffer = TB_PATH_NONE; path->ingress_fc_enable = TB_PATH_ALL; @@ -1076,11 +1334,9 @@ static void tb_usb3_init_path(struct tb_path *path) path->priority = 3; path->weight = 3; path->drop_packages = 0; - path->nfc_credits = 0; - path->hops[0].initial_credits = 7; - if (path->path_length > 1) - path->hops[1].initial_credits = - tb_initial_credits(path->hops[1].in_port->sw); + + tb_path_for_each_hop(path, hop) + tb_usb3_init_credits(hop); } /** @@ -1280,6 +1536,9 @@ void tb_tunnel_free(struct tb_tunnel *tunnel) if (!tunnel) return; + if (tunnel->deinit) + tunnel->deinit(tunnel); + for (i = 0; i < tunnel->npaths; i++) { if (tunnel->paths[i]) tb_path_free(tunnel->paths[i]); diff --git a/drivers/thunderbolt/tunnel.h b/drivers/thunderbolt/tunnel.h index a66994fb4e60..eea14e24f7e0 100644 --- a/drivers/thunderbolt/tunnel.h +++ b/drivers/thunderbolt/tunnel.h @@ -27,6 +27,7 @@ enum tb_tunnel_type { * @paths: All paths required by the tunnel * @npaths: Number of paths in @paths * @init: Optional tunnel specific initialization + * @deinit: Optional tunnel specific de-initialization * @activate: Optional tunnel specific activation/deactivation * @consumed_bandwidth: Return how much bandwidth the tunnel consumes * @release_unused_bandwidth: Release all unused bandwidth @@ -47,6 +48,7 @@ struct tb_tunnel { struct tb_path **paths; size_t npaths; int (*init)(struct tb_tunnel *tunnel); + void (*deinit)(struct tb_tunnel *tunnel); int (*activate)(struct tb_tunnel *tunnel, bool activate); int (*consumed_bandwidth)(struct tb_tunnel *tunnel, int *consumed_up, int *consumed_down); diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c index 671d72af8ba1..ceddbe7e9f93 100644 --- a/drivers/thunderbolt/usb4.c +++ b/drivers/thunderbolt/usb4.c @@ -13,7 +13,6 @@ #include "sb_regs.h" #include "tb.h" -#define USB4_DATA_DWORDS 16 #define USB4_DATA_RETRIES 3 enum usb4_sb_target { @@ -37,8 +36,19 @@ enum usb4_sb_target { #define USB4_NVM_SECTOR_SIZE_MASK GENMASK(23, 0) -typedef int (*read_block_fn)(void *, unsigned int, void *, size_t); -typedef int (*write_block_fn)(void *, const void *, size_t); +#define USB4_BA_LENGTH_MASK GENMASK(7, 0) +#define USB4_BA_INDEX_MASK GENMASK(15, 0) + +enum usb4_ba_index { + USB4_BA_MAX_USB3 = 0x1, + USB4_BA_MIN_DP_AUX = 0x2, + USB4_BA_MIN_DP_MAIN = 0x3, + USB4_BA_MAX_PCIE = 0x4, + USB4_BA_MAX_HI = 0x5, +}; + +#define USB4_BA_VALUE_MASK GENMASK(31, 16) +#define USB4_BA_VALUE_SHIFT 16 static int usb4_switch_wait_for_bit(struct tb_switch *sw, u32 offset, u32 bit, u32 value, int timeout_msec) @@ -62,76 +72,6 @@ static int usb4_switch_wait_for_bit(struct tb_switch *sw, u32 offset, u32 bit, return -ETIMEDOUT; } -static int usb4_do_read_data(u16 address, void *buf, size_t size, - read_block_fn read_block, void *read_block_data) -{ - unsigned int retries = USB4_DATA_RETRIES; - unsigned int offset; - - do { - unsigned int dwaddress, dwords; - u8 data[USB4_DATA_DWORDS * 4]; - size_t nbytes; - int ret; - - offset = address & 3; - nbytes = min_t(size_t, size + offset, USB4_DATA_DWORDS * 4); - - dwaddress = address / 4; - dwords = ALIGN(nbytes, 4) / 4; - - ret = read_block(read_block_data, dwaddress, data, dwords); - if (ret) { - if (ret != -ENODEV && retries--) - continue; - return ret; - } - - nbytes -= offset; - memcpy(buf, data + offset, nbytes); - - size -= nbytes; - address += nbytes; - buf += nbytes; - } while (size > 0); - - return 0; -} - -static int usb4_do_write_data(unsigned int address, const void *buf, size_t size, - write_block_fn write_next_block, void *write_block_data) -{ - unsigned int retries = USB4_DATA_RETRIES; - unsigned int offset; - - offset = address & 3; - address = address & ~3; - - do { - u32 nbytes = min_t(u32, size, USB4_DATA_DWORDS * 4); - u8 data[USB4_DATA_DWORDS * 4]; - int ret; - - memcpy(data + offset, buf, nbytes); - - ret = write_next_block(write_block_data, data, nbytes / 4); - if (ret) { - if (ret == -ETIMEDOUT) { - if (retries--) - continue; - ret = -EIO; - } - return ret; - } - - size -= nbytes; - address += nbytes; - buf += nbytes; - } while (size > 0); - - return 0; -} - static int usb4_native_switch_op(struct tb_switch *sw, u16 opcode, u32 *metadata, u8 *status, const void *tx_data, size_t tx_dwords, @@ -193,7 +133,7 @@ static int __usb4_switch_op(struct tb_switch *sw, u16 opcode, u32 *metadata, { const struct tb_cm_ops *cm_ops = sw->tb->cm_ops; - if (tx_dwords > USB4_DATA_DWORDS || rx_dwords > USB4_DATA_DWORDS) + if (tx_dwords > NVM_DATA_DWORDS || rx_dwords > NVM_DATA_DWORDS) return -EINVAL; /* @@ -320,7 +260,7 @@ int usb4_switch_setup(struct tb_switch *sw) parent = tb_switch_parent(sw); downstream_port = tb_port_at(tb_route(sw), parent); sw->link_usb4 = link_is_usb4(downstream_port); - tb_sw_dbg(sw, "link: %s\n", sw->link_usb4 ? "USB4" : "TBT3"); + tb_sw_dbg(sw, "link: %s\n", sw->link_usb4 ? "USB4" : "TBT"); xhci = val & ROUTER_CS_6_HCI; tbt3 = !(val & ROUTER_CS_6_TNS); @@ -414,8 +354,8 @@ static int usb4_switch_drom_read_block(void *data, int usb4_switch_drom_read(struct tb_switch *sw, unsigned int address, void *buf, size_t size) { - return usb4_do_read_data(address, buf, size, - usb4_switch_drom_read_block, sw); + return tb_nvm_read_data(address, buf, size, USB4_DATA_RETRIES, + usb4_switch_drom_read_block, sw); } /** @@ -473,12 +413,18 @@ int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags) val &= ~(PORT_CS_19_WOC | PORT_CS_19_WOD | PORT_CS_19_WOU4); - if (flags & TB_WAKE_ON_CONNECT) - val |= PORT_CS_19_WOC; - if (flags & TB_WAKE_ON_DISCONNECT) - val |= PORT_CS_19_WOD; - if (flags & TB_WAKE_ON_USB4) + if (tb_is_upstream_port(port)) { val |= PORT_CS_19_WOU4; + } else { + bool configured = val & PORT_CS_19_PC; + + if ((flags & TB_WAKE_ON_CONNECT) && !configured) + val |= PORT_CS_19_WOC; + if ((flags & TB_WAKE_ON_DISCONNECT) && configured) + val |= PORT_CS_19_WOD; + if ((flags & TB_WAKE_ON_USB4) && configured) + val |= PORT_CS_19_WOU4; + } ret = tb_port_write(port, &val, TB_CFG_PORT, port->cap_usb4 + PORT_CS_19, 1); @@ -487,7 +433,7 @@ int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags) } /* - * Enable wakes from PCIe and USB 3.x on this router. Only + * Enable wakes from PCIe, USB 3.x and DP on this router. Only * needed for device routers. */ if (route) { @@ -495,11 +441,13 @@ int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags) if (ret) return ret; - val &= ~(ROUTER_CS_5_WOP | ROUTER_CS_5_WOU); + val &= ~(ROUTER_CS_5_WOP | ROUTER_CS_5_WOU | ROUTER_CS_5_WOD); if (flags & TB_WAKE_ON_USB3) val |= ROUTER_CS_5_WOU; if (flags & TB_WAKE_ON_PCIE) val |= ROUTER_CS_5_WOP; + if (flags & TB_WAKE_ON_DP) + val |= ROUTER_CS_5_WOD; ret = tb_sw_write(sw, &val, TB_CFG_SWITCH, ROUTER_CS_5, 1); if (ret) @@ -595,12 +543,21 @@ static int usb4_switch_nvm_read_block(void *data, int usb4_switch_nvm_read(struct tb_switch *sw, unsigned int address, void *buf, size_t size) { - return usb4_do_read_data(address, buf, size, - usb4_switch_nvm_read_block, sw); + return tb_nvm_read_data(address, buf, size, USB4_DATA_RETRIES, + usb4_switch_nvm_read_block, sw); } -static int usb4_switch_nvm_set_offset(struct tb_switch *sw, - unsigned int address) +/** + * usb4_switch_nvm_set_offset() - Set NVM write offset + * @sw: USB4 router + * @address: Start offset + * + * Explicitly sets NVM write offset. Normally when writing to NVM this + * is done automatically by usb4_switch_nvm_write(). + * + * Returns %0 in success and negative errno if there was a failure. + */ +int usb4_switch_nvm_set_offset(struct tb_switch *sw, unsigned int address) { u32 metadata, dwaddress; u8 status = 0; @@ -618,8 +575,8 @@ static int usb4_switch_nvm_set_offset(struct tb_switch *sw, return status ? -EIO : 0; } -static int usb4_switch_nvm_write_next_block(void *data, const void *buf, - size_t dwords) +static int usb4_switch_nvm_write_next_block(void *data, unsigned int dwaddress, + const void *buf, size_t dwords) { struct tb_switch *sw = data; u8 status; @@ -652,8 +609,8 @@ int usb4_switch_nvm_write(struct tb_switch *sw, unsigned int address, if (ret) return ret; - return usb4_do_write_data(address, buf, size, - usb4_switch_nvm_write_next_block, sw); + return tb_nvm_write_data(address, buf, size, USB4_DATA_RETRIES, + usb4_switch_nvm_write_next_block, sw); } /** @@ -736,6 +693,147 @@ int usb4_switch_nvm_authenticate_status(struct tb_switch *sw, u32 *status) } /** + * usb4_switch_credits_init() - Read buffer allocation parameters + * @sw: USB4 router + * + * Reads @sw buffer allocation parameters and initializes @sw buffer + * allocation fields accordingly. Specifically @sw->credits_allocation + * is set to %true if these parameters can be used in tunneling. + * + * Returns %0 on success and negative errno otherwise. + */ +int usb4_switch_credits_init(struct tb_switch *sw) +{ + int max_usb3, min_dp_aux, min_dp_main, max_pcie, max_dma; + int ret, length, i, nports; + const struct tb_port *port; + u32 data[NVM_DATA_DWORDS]; + u32 metadata = 0; + u8 status = 0; + + memset(data, 0, sizeof(data)); + ret = usb4_switch_op_data(sw, USB4_SWITCH_OP_BUFFER_ALLOC, &metadata, + &status, NULL, 0, data, ARRAY_SIZE(data)); + if (ret) + return ret; + if (status) + return -EIO; + + length = metadata & USB4_BA_LENGTH_MASK; + if (WARN_ON(length > ARRAY_SIZE(data))) + return -EMSGSIZE; + + max_usb3 = -1; + min_dp_aux = -1; + min_dp_main = -1; + max_pcie = -1; + max_dma = -1; + + tb_sw_dbg(sw, "credit allocation parameters:\n"); + + for (i = 0; i < length; i++) { + u16 index, value; + + index = data[i] & USB4_BA_INDEX_MASK; + value = (data[i] & USB4_BA_VALUE_MASK) >> USB4_BA_VALUE_SHIFT; + + switch (index) { + case USB4_BA_MAX_USB3: + tb_sw_dbg(sw, " USB3: %u\n", value); + max_usb3 = value; + break; + case USB4_BA_MIN_DP_AUX: + tb_sw_dbg(sw, " DP AUX: %u\n", value); + min_dp_aux = value; + break; + case USB4_BA_MIN_DP_MAIN: + tb_sw_dbg(sw, " DP main: %u\n", value); + min_dp_main = value; + break; + case USB4_BA_MAX_PCIE: + tb_sw_dbg(sw, " PCIe: %u\n", value); + max_pcie = value; + break; + case USB4_BA_MAX_HI: + tb_sw_dbg(sw, " DMA: %u\n", value); + max_dma = value; + break; + default: + tb_sw_dbg(sw, " unknown credit allocation index %#x, skipping\n", + index); + break; + } + } + + /* + * Validate the buffer allocation preferences. If we find + * issues, log a warning and fall back using the hard-coded + * values. + */ + + /* Host router must report baMaxHI */ + if (!tb_route(sw) && max_dma < 0) { + tb_sw_warn(sw, "host router is missing baMaxHI\n"); + goto err_invalid; + } + + nports = 0; + tb_switch_for_each_port(sw, port) { + if (tb_port_is_null(port)) + nports++; + } + + /* Must have DP buffer allocation (multiple USB4 ports) */ + if (nports > 2 && (min_dp_aux < 0 || min_dp_main < 0)) { + tb_sw_warn(sw, "multiple USB4 ports require baMinDPaux/baMinDPmain\n"); + goto err_invalid; + } + + tb_switch_for_each_port(sw, port) { + if (tb_port_is_dpout(port) && min_dp_main < 0) { + tb_sw_warn(sw, "missing baMinDPmain"); + goto err_invalid; + } + if ((tb_port_is_dpin(port) || tb_port_is_dpout(port)) && + min_dp_aux < 0) { + tb_sw_warn(sw, "missing baMinDPaux"); + goto err_invalid; + } + if ((tb_port_is_usb3_down(port) || tb_port_is_usb3_up(port)) && + max_usb3 < 0) { + tb_sw_warn(sw, "missing baMaxUSB3"); + goto err_invalid; + } + if ((tb_port_is_pcie_down(port) || tb_port_is_pcie_up(port)) && + max_pcie < 0) { + tb_sw_warn(sw, "missing baMaxPCIe"); + goto err_invalid; + } + } + + /* + * Buffer allocation passed the validation so we can use it in + * path creation. + */ + sw->credit_allocation = true; + if (max_usb3 > 0) + sw->max_usb3_credits = max_usb3; + if (min_dp_aux > 0) + sw->min_dp_aux_credits = min_dp_aux; + if (min_dp_main > 0) + sw->min_dp_main_credits = min_dp_main; + if (max_pcie > 0) + sw->max_pcie_credits = max_pcie; + if (max_dma > 0) + sw->max_dma_credits = max_dma; + + return 0; + +err_invalid: + return -EINVAL; +} + +/** * usb4_switch_query_dp_resource() - Query availability of DP IN resource * @sw: USB4 router * @in: DP IN adapter @@ -897,6 +995,60 @@ struct tb_port *usb4_switch_map_usb3_down(struct tb_switch *sw, } /** + * usb4_switch_add_ports() - Add USB4 ports for this router + * @sw: USB4 router + * + * For USB4 router finds all USB4 ports and registers devices for each. + * Can be called to any router. + * + * Return %0 in case of success and negative errno in case of failure. + */ +int usb4_switch_add_ports(struct tb_switch *sw) +{ + struct tb_port *port; + + if (tb_switch_is_icm(sw) || !tb_switch_is_usb4(sw)) + return 0; + + tb_switch_for_each_port(sw, port) { + struct usb4_port *usb4; + + if (!tb_port_is_null(port)) + continue; + if (!port->cap_usb4) + continue; + + usb4 = usb4_port_device_add(port); + if (IS_ERR(usb4)) { + usb4_switch_remove_ports(sw); + return PTR_ERR(usb4); + } + + port->usb4 = usb4; + } + + return 0; +} + +/** + * usb4_switch_remove_ports() - Removes USB4 ports from this router + * @sw: USB4 router + * + * Unregisters previously registered USB4 ports. + */ +void usb4_switch_remove_ports(struct tb_switch *sw) +{ + struct tb_port *port; + + tb_switch_for_each_port(sw, port) { + if (port->usb4) { + usb4_port_device_remove(port->usb4); + port->usb4 = NULL; + } + } +} + +/** * usb4_port_unlock() - Unlock USB4 downstream port * @port: USB4 port to unlock * @@ -1029,7 +1181,7 @@ static int usb4_port_wait_for_bit(struct tb_port *port, u32 offset, u32 bit, static int usb4_port_read_data(struct tb_port *port, void *data, size_t dwords) { - if (dwords > USB4_DATA_DWORDS) + if (dwords > NVM_DATA_DWORDS) return -EINVAL; return tb_port_read(port, data, TB_CFG_PORT, port->cap_usb4 + PORT_CS_2, @@ -1039,7 +1191,7 @@ static int usb4_port_read_data(struct tb_port *port, void *data, size_t dwords) static int usb4_port_write_data(struct tb_port *port, const void *data, size_t dwords) { - if (dwords > USB4_DATA_DWORDS) + if (dwords > NVM_DATA_DWORDS) return -EINVAL; return tb_port_write(port, data, TB_CFG_PORT, port->cap_usb4 + PORT_CS_2, @@ -1175,6 +1327,48 @@ static int usb4_port_sb_op(struct tb_port *port, enum usb4_sb_target target, return -ETIMEDOUT; } +static int usb4_port_set_router_offline(struct tb_port *port, bool offline) +{ + u32 val = !offline; + int ret; + + ret = usb4_port_sb_write(port, USB4_SB_TARGET_ROUTER, 0, + USB4_SB_METADATA, &val, sizeof(val)); + if (ret) + return ret; + + val = USB4_SB_OPCODE_ROUTER_OFFLINE; + return usb4_port_sb_write(port, USB4_SB_TARGET_ROUTER, 0, + USB4_SB_OPCODE, &val, sizeof(val)); +} + +/** + * usb4_port_router_offline() - Put the USB4 port to offline mode + * @port: USB4 port + * + * This function puts the USB4 port into offline mode. In this mode the + * port does not react on hotplug events anymore. This needs to be + * called before retimer access is done when the USB4 links is not up. + * + * Returns %0 in case of success and negative errno if there was an + * error. + */ +int usb4_port_router_offline(struct tb_port *port) +{ + return usb4_port_set_router_offline(port, true); +} + +/** + * usb4_port_router_online() - Put the USB4 port back to online + * @port: USB4 port + * + * Makes the USB4 port functional again. + */ +int usb4_port_router_online(struct tb_port *port) +{ + return usb4_port_set_router_offline(port, false); +} + /** * usb4_port_enumerate_retimers() - Send RT broadcast transaction * @port: USB4 port @@ -1201,6 +1395,33 @@ static inline int usb4_port_retimer_op(struct tb_port *port, u8 index, } /** + * usb4_port_retimer_set_inbound_sbtx() - Enable sideband channel transactions + * @port: USB4 port + * @index: Retimer index + * + * Enables sideband channel transations on SBTX. Can be used when USB4 + * link does not go up, for example if there is no device connected. + */ +int usb4_port_retimer_set_inbound_sbtx(struct tb_port *port, u8 index) +{ + int ret; + + ret = usb4_port_retimer_op(port, index, USB4_SB_OPCODE_SET_INBOUND_SBTX, + 500); + + if (ret != -ENODEV) + return ret; + + /* + * Per the USB4 retimer spec, the retimer is not required to + * send an RT (Retimer Transaction) response for the first + * SET_INBOUND_SBTX command + */ + return usb4_port_retimer_op(port, index, USB4_SB_OPCODE_SET_INBOUND_SBTX, + 500); +} + +/** * usb4_port_retimer_read() - Read from retimer sideband registers * @port: USB4 port * @index: Retimer index @@ -1292,8 +1513,19 @@ int usb4_port_retimer_nvm_sector_size(struct tb_port *port, u8 index) return ret ? ret : metadata & USB4_NVM_SECTOR_SIZE_MASK; } -static int usb4_port_retimer_nvm_set_offset(struct tb_port *port, u8 index, - unsigned int address) +/** + * usb4_port_retimer_nvm_set_offset() - Set NVM write offset + * @port: USB4 port + * @index: Retimer index + * @address: Start offset + * + * Exlicitly sets NVM write offset. Normally when writing to NVM this is + * done automatically by usb4_port_retimer_nvm_write(). + * + * Returns %0 in success and negative errno if there was a failure. + */ +int usb4_port_retimer_nvm_set_offset(struct tb_port *port, u8 index, + unsigned int address) { u32 metadata, dwaddress; int ret; @@ -1316,8 +1548,8 @@ struct retimer_info { u8 index; }; -static int usb4_port_retimer_nvm_write_next_block(void *data, const void *buf, - size_t dwords) +static int usb4_port_retimer_nvm_write_next_block(void *data, + unsigned int dwaddress, const void *buf, size_t dwords) { const struct retimer_info *info = data; @@ -1357,8 +1589,8 @@ int usb4_port_retimer_nvm_write(struct tb_port *port, u8 index, unsigned int add if (ret) return ret; - return usb4_do_write_data(address, buf, size, - usb4_port_retimer_nvm_write_next_block, &info); + return tb_nvm_write_data(address, buf, size, USB4_DATA_RETRIES, + usb4_port_retimer_nvm_write_next_block, &info); } /** @@ -1442,7 +1674,7 @@ static int usb4_port_retimer_nvm_read_block(void *data, unsigned int dwaddress, int ret; metadata = dwaddress << USB4_NVM_READ_OFFSET_SHIFT; - if (dwords < USB4_DATA_DWORDS) + if (dwords < NVM_DATA_DWORDS) metadata |= dwords << USB4_NVM_READ_LENGTH_SHIFT; ret = usb4_port_retimer_write(port, index, USB4_SB_METADATA, &metadata, @@ -1475,8 +1707,8 @@ int usb4_port_retimer_nvm_read(struct tb_port *port, u8 index, { struct retimer_info info = { .port = port, .index = index }; - return usb4_do_read_data(address, buf, size, - usb4_port_retimer_nvm_read_block, &info); + return tb_nvm_read_data(address, buf, size, USB4_DATA_RETRIES, + usb4_port_retimer_nvm_read_block, &info); } /** diff --git a/drivers/thunderbolt/usb4_port.c b/drivers/thunderbolt/usb4_port.c new file mode 100644 index 000000000000..29e2a4f9c9f5 --- /dev/null +++ b/drivers/thunderbolt/usb4_port.c @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * USB4 port device + * + * Copyright (C) 2021, Intel Corporation + * Author: Mika Westerberg <mika.westerberg@linux.intel.com> + */ + +#include <linux/pm_runtime.h> + +#include "tb.h" + +static ssize_t link_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct usb4_port *usb4 = tb_to_usb4_port_device(dev); + struct tb_port *port = usb4->port; + struct tb *tb = port->sw->tb; + const char *link; + + if (mutex_lock_interruptible(&tb->lock)) + return -ERESTARTSYS; + + if (tb_is_upstream_port(port)) + link = port->sw->link_usb4 ? "usb4" : "tbt"; + else if (tb_port_has_remote(port)) + link = port->remote->sw->link_usb4 ? "usb4" : "tbt"; + else + link = "none"; + + mutex_unlock(&tb->lock); + + return sysfs_emit(buf, "%s\n", link); +} +static DEVICE_ATTR_RO(link); + +static struct attribute *common_attrs[] = { + &dev_attr_link.attr, + NULL +}; + +static const struct attribute_group common_group = { + .attrs = common_attrs, +}; + +static int usb4_port_offline(struct usb4_port *usb4) +{ + struct tb_port *port = usb4->port; + int ret; + + ret = tb_acpi_power_on_retimers(port); + if (ret) + return ret; + + ret = usb4_port_router_offline(port); + if (ret) { + tb_acpi_power_off_retimers(port); + return ret; + } + + ret = tb_retimer_scan(port, false); + if (ret) { + usb4_port_router_online(port); + tb_acpi_power_off_retimers(port); + } + + return ret; +} + +static void usb4_port_online(struct usb4_port *usb4) +{ + struct tb_port *port = usb4->port; + + usb4_port_router_online(port); + tb_acpi_power_off_retimers(port); +} + +static ssize_t offline_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb4_port *usb4 = tb_to_usb4_port_device(dev); + + return sysfs_emit(buf, "%d\n", usb4->offline); +} + +static ssize_t offline_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct usb4_port *usb4 = tb_to_usb4_port_device(dev); + struct tb_port *port = usb4->port; + struct tb *tb = port->sw->tb; + bool val; + int ret; + + ret = kstrtobool(buf, &val); + if (ret) + return ret; + + pm_runtime_get_sync(&usb4->dev); + + if (mutex_lock_interruptible(&tb->lock)) { + ret = -ERESTARTSYS; + goto out_rpm; + } + + if (val == usb4->offline) + goto out_unlock; + + /* Offline mode works only for ports that are not connected */ + if (tb_port_has_remote(port)) { + ret = -EBUSY; + goto out_unlock; + } + + if (val) { + ret = usb4_port_offline(usb4); + if (ret) + goto out_unlock; + } else { + usb4_port_online(usb4); + tb_retimer_remove_all(port); + } + + usb4->offline = val; + tb_port_dbg(port, "%s offline mode\n", val ? "enter" : "exit"); + +out_unlock: + mutex_unlock(&tb->lock); +out_rpm: + pm_runtime_mark_last_busy(&usb4->dev); + pm_runtime_put_autosuspend(&usb4->dev); + + return ret ? ret : count; +} +static DEVICE_ATTR_RW(offline); + +static ssize_t rescan_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct usb4_port *usb4 = tb_to_usb4_port_device(dev); + struct tb_port *port = usb4->port; + struct tb *tb = port->sw->tb; + bool val; + int ret; + + ret = kstrtobool(buf, &val); + if (ret) + return ret; + + if (!val) + return count; + + pm_runtime_get_sync(&usb4->dev); + + if (mutex_lock_interruptible(&tb->lock)) { + ret = -ERESTARTSYS; + goto out_rpm; + } + + /* Must be in offline mode already */ + if (!usb4->offline) { + ret = -EINVAL; + goto out_unlock; + } + + tb_retimer_remove_all(port); + ret = tb_retimer_scan(port, true); + +out_unlock: + mutex_unlock(&tb->lock); +out_rpm: + pm_runtime_mark_last_busy(&usb4->dev); + pm_runtime_put_autosuspend(&usb4->dev); + + return ret ? ret : count; +} +static DEVICE_ATTR_WO(rescan); + +static struct attribute *service_attrs[] = { + &dev_attr_offline.attr, + &dev_attr_rescan.attr, + NULL +}; + +static umode_t service_attr_is_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device *dev = kobj_to_dev(kobj); + struct usb4_port *usb4 = tb_to_usb4_port_device(dev); + + /* + * Always need some platform help to cycle the modes so that + * retimers can be accessed through the sideband. + */ + return usb4->can_offline ? attr->mode : 0; +} + +static const struct attribute_group service_group = { + .attrs = service_attrs, + .is_visible = service_attr_is_visible, +}; + +static const struct attribute_group *usb4_port_device_groups[] = { + &common_group, + &service_group, + NULL +}; + +static void usb4_port_device_release(struct device *dev) +{ + struct usb4_port *usb4 = container_of(dev, struct usb4_port, dev); + + kfree(usb4); +} + +struct device_type usb4_port_device_type = { + .name = "usb4_port", + .groups = usb4_port_device_groups, + .release = usb4_port_device_release, +}; + +/** + * usb4_port_device_add() - Add USB4 port device + * @port: Lane 0 adapter port to add the USB4 port + * + * Creates and registers a USB4 port device for @port. Returns the new + * USB4 port device pointer or ERR_PTR() in case of error. + */ +struct usb4_port *usb4_port_device_add(struct tb_port *port) +{ + struct usb4_port *usb4; + int ret; + + usb4 = kzalloc(sizeof(*usb4), GFP_KERNEL); + if (!usb4) + return ERR_PTR(-ENOMEM); + + usb4->port = port; + usb4->dev.type = &usb4_port_device_type; + usb4->dev.parent = &port->sw->dev; + dev_set_name(&usb4->dev, "usb4_port%d", port->port); + + ret = device_register(&usb4->dev); + if (ret) { + put_device(&usb4->dev); + return ERR_PTR(ret); + } + + pm_runtime_no_callbacks(&usb4->dev); + pm_runtime_set_active(&usb4->dev); + pm_runtime_enable(&usb4->dev); + pm_runtime_set_autosuspend_delay(&usb4->dev, TB_AUTOSUSPEND_DELAY); + pm_runtime_mark_last_busy(&usb4->dev); + pm_runtime_use_autosuspend(&usb4->dev); + + return usb4; +} + +/** + * usb4_port_device_remove() - Removes USB4 port device + * @usb4: USB4 port device + * + * Unregisters the USB4 port device from the system. The device will be + * released when the last reference is dropped. + */ +void usb4_port_device_remove(struct usb4_port *usb4) +{ + device_unregister(&usb4->dev); +} + +/** + * usb4_port_device_resume() - Resumes USB4 port device + * @usb4: USB4 port device + * + * Used to resume USB4 port device after sleep state. + */ +int usb4_port_device_resume(struct usb4_port *usb4) +{ + return usb4->offline ? usb4_port_offline(usb4) : 0; +} diff --git a/drivers/thunderbolt/xdomain.c b/drivers/thunderbolt/xdomain.c index b21d99d59412..d66ea4d616fd 100644 --- a/drivers/thunderbolt/xdomain.c +++ b/drivers/thunderbolt/xdomain.c @@ -1527,6 +1527,13 @@ int tb_xdomain_lane_bonding_enable(struct tb_xdomain *xd) return ret; } + ret = tb_port_wait_for_link_width(port, 2, 100); + if (ret) { + tb_port_warn(port, "timeout enabling lane bonding\n"); + return ret; + } + + tb_port_update_credits(port); tb_xdomain_update_link_attributes(xd); dev_dbg(&xd->dev, "lane bonding enabled\n"); @@ -1548,7 +1555,10 @@ void tb_xdomain_lane_bonding_disable(struct tb_xdomain *xd) port = tb_port_at(xd->route, tb_xdomain_parent(xd)); if (port->dual_link_port) { tb_port_lane_bonding_disable(port); + if (tb_port_wait_for_link_width(port, 1, 100) == -ETIMEDOUT) + tb_port_warn(port, "timeout disabling lane bonding\n"); tb_port_disable(port->dual_link_port); + tb_port_update_credits(port); tb_xdomain_update_link_attributes(xd); dev_dbg(&xd->dev, "lane bonding disabled\n"); diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig index f6a7fd6d3bb6..23cc988c68a4 100644 --- a/drivers/tty/Kconfig +++ b/drivers/tty/Kconfig @@ -12,9 +12,8 @@ if TTY config VT bool "Virtual terminal" if EXPERT - depends on !UML select INPUT - default y + default y if !UML help If you say Y here, you will get support for terminal devices with display and keyboard devices. These are called "virtual" because you @@ -78,7 +77,7 @@ config VT_CONSOLE_SLEEP config HW_CONSOLE bool - depends on VT && !UML + depends on VT default y config VT_HW_CONSOLE_BINDING @@ -204,7 +203,7 @@ config MOXA_INTELLIO config MOXA_SMARTIO tristate "Moxa SmartIO support v. 2.0" - depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) + depends on SERIAL_NONSTANDARD && PCI help Say Y here if you have a Moxa SmartIO multiport serial card and/or want to help develop a new version of this driver. diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile index c7054f5117c3..a2bd75fbaaa4 100644 --- a/drivers/tty/Makefile +++ b/drivers/tty/Makefile @@ -9,7 +9,6 @@ obj-$(CONFIG_AUDIT) += tty_audit.o obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o obj-$(CONFIG_N_HDLC) += n_hdlc.o obj-$(CONFIG_N_GSM) += n_gsm.o -obj-$(CONFIG_R3964) += n_r3964.o obj-y += vt/ obj-$(CONFIG_HVC_DRIVER) += hvc/ diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index ca48ce5a0862..5ec19c48fb7a 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -148,7 +148,7 @@ static __inline__ void rtsdtr_ctrl(int bits) * ------------------------------------------------------------ * rs_stop() and rs_start() * - * This routines are called before setting or resetting tty->stopped. + * This routines are called before setting or resetting tty->flow.stopped. * They enable or disable transmitter interrupts, as necessary. * ------------------------------------------------------------ */ @@ -309,7 +309,7 @@ static void transmit_chars(struct serial_state *info) return; } if (info->xmit.head == info->xmit.tail - || info->tport.tty->stopped + || info->tport.tty->flow.stopped || info->tport.tty->hw_stopped) { info->IER &= ~UART_IER_THRI; custom.intena = IF_TBE; @@ -768,7 +768,7 @@ static void rs_flush_chars(struct tty_struct *tty) unsigned long flags; if (info->xmit.head == info->xmit.tail - || tty->stopped + || tty->flow.stopped || tty->hw_stopped || !info->xmit.buf) return; @@ -812,7 +812,7 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count local_irq_restore(flags); if (info->xmit.head != info->xmit.tail - && !tty->stopped + && !tty->flow.stopped && !tty->hw_stopped && !(info->IER & UART_IER_THRI)) { info->IER |= UART_IER_THRI; @@ -827,14 +827,14 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count return ret; } -static int rs_write_room(struct tty_struct *tty) +static unsigned int rs_write_room(struct tty_struct *tty) { struct serial_state *info = tty->driver_data; return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); } -static int rs_chars_in_buffer(struct tty_struct *tty) +static unsigned int rs_chars_in_buffer(struct tty_struct *tty) { struct serial_state *info = tty->driver_data; diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c index 3c6dd06ec5fb..445e5ff9b36d 100644 --- a/drivers/tty/ehv_bytechan.c +++ b/drivers/tty/ehv_bytechan.c @@ -536,11 +536,11 @@ static void ehv_bc_tty_close(struct tty_struct *ttys, struct file *filp) * how much write room the driver can guarantee will be sent OR BUFFERED. This * driver MUST honor the return value. */ -static int ehv_bc_tty_write_room(struct tty_struct *ttys) +static unsigned int ehv_bc_tty_write_room(struct tty_struct *ttys) { struct ehv_bc_data *bc = ttys->driver_data; unsigned long flags; - int count; + unsigned int count; spin_lock_irqsave(&bc->lock, flags); count = CIRC_SPACE(bc->head, bc->tail, BUF_SIZE); diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c index cd23a4b05c8f..ccb683a6e6f5 100644 --- a/drivers/tty/goldfish.c +++ b/drivers/tty/goldfish.c @@ -193,12 +193,12 @@ static int goldfish_tty_write(struct tty_struct *tty, const unsigned char *buf, return count; } -static int goldfish_tty_write_room(struct tty_struct *tty) +static unsigned int goldfish_tty_write_room(struct tty_struct *tty) { return 0x10000; } -static int goldfish_tty_chars_in_buffer(struct tty_struct *tty) +static unsigned int goldfish_tty_chars_in_buffer(struct tty_struct *tty) { struct goldfish_tty *qtty = &goldfish_ttys[tty->index]; void __iomem *base = qtty->base; diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c index cdcc64ea2554..5bb8c4e44961 100644 --- a/drivers/tty/hvc/hvc_console.c +++ b/drivers/tty/hvc/hvc_console.c @@ -292,7 +292,7 @@ int hvc_instantiate(uint32_t vtermno, int index, const struct hv_ops *ops) if (vtermnos[index] != -1) return -1; - /* make sure no no tty has been registered in this index */ + /* make sure no tty has been registered in this index */ hp = hvc_get_by_index(index); if (hp) { tty_port_put(&hp->port); @@ -586,7 +586,7 @@ static void hvc_set_winsz(struct work_struct *work) * how much write room the driver can guarantee will be sent OR BUFFERED. This * driver MUST honor the return value. */ -static int hvc_write_room(struct tty_struct *tty) +static unsigned int hvc_write_room(struct tty_struct *tty) { struct hvc_struct *hp = tty->driver_data; @@ -596,7 +596,7 @@ static int hvc_write_room(struct tty_struct *tty) return hp->outbuf_size - hp->n_outbuf; } -static int hvc_chars_in_buffer(struct tty_struct *tty) +static unsigned int hvc_chars_in_buffer(struct tty_struct *tty) { struct hvc_struct *hp = tty->driver_data; @@ -620,7 +620,7 @@ static u32 timeout = MIN_TIMEOUT; /* * Maximum number of bytes to get from the console driver if hvc_poll is * called from driver (and can't sleep). Any more than this and we break - * and start polling with khvcd. This value was derived from from an OpenBMC + * and start polling with khvcd. This value was derived from an OpenBMC * console with the OPAL driver that results in about 0.25ms interrupts off * latency. */ diff --git a/drivers/tty/hvc/hvc_iucv.c b/drivers/tty/hvc/hvc_iucv.c index 2af1e5751bd6..82a76cac94de 100644 --- a/drivers/tty/hvc/hvc_iucv.c +++ b/drivers/tty/hvc/hvc_iucv.c @@ -438,8 +438,6 @@ static void hvc_iucv_sndbuf_work(struct work_struct *work) struct hvc_iucv_private *priv; priv = container_of(work, struct hvc_iucv_private, sndbuf_work.work); - if (!priv) - return; spin_lock_bh(&priv->lock); hvc_iucv_send(priv); @@ -966,37 +964,6 @@ static void hvc_iucv_msg_complete(struct iucv_path *path, destroy_tty_buffer_list(&list_remove); } -/** - * hvc_iucv_pm_freeze() - Freeze PM callback - * @dev: IUVC HVC terminal device - * - * Sever an established IUCV communication path and - * trigger a hang-up of the underlying HVC terminal. - */ -static int hvc_iucv_pm_freeze(struct device *dev) -{ - struct hvc_iucv_private *priv = dev_get_drvdata(dev); - - local_bh_disable(); - hvc_iucv_hangup(priv); - local_bh_enable(); - - return 0; -} - -/** - * hvc_iucv_pm_restore_thaw() - Thaw and restore PM callback - * @dev: IUVC HVC terminal device - * - * Wake up the HVC thread to trigger hang-up and respective - * HVC back-end notifier invocations. - */ -static int hvc_iucv_pm_restore_thaw(struct device *dev) -{ - hvc_kick(); - return 0; -} - static ssize_t hvc_iucv_dev_termid_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -1051,20 +1018,6 @@ static const struct hv_ops hvc_iucv_ops = { .dtr_rts = hvc_iucv_dtr_rts, }; -/* Suspend / resume device operations */ -static const struct dev_pm_ops hvc_iucv_pm_ops = { - .freeze = hvc_iucv_pm_freeze, - .thaw = hvc_iucv_pm_restore_thaw, - .restore = hvc_iucv_pm_restore_thaw, -}; - -/* IUCV HVC device driver */ -static struct device_driver hvc_iucv_driver = { - .name = KMSG_COMPONENT, - .bus = &iucv_bus, - .pm = &hvc_iucv_pm_ops, -}; - /* IUCV HVC device attributes */ static DEVICE_ATTR(termid, 0640, hvc_iucv_dev_termid_show, NULL); static DEVICE_ATTR(state, 0640, hvc_iucv_dev_state_show, NULL); @@ -1144,7 +1097,6 @@ static int __init hvc_iucv_alloc(int id, unsigned int is_console) dev_set_drvdata(priv->dev, priv); priv->dev->bus = &iucv_bus; priv->dev->parent = iucv_root; - priv->dev->driver = &hvc_iucv_driver; priv->dev->groups = hvc_iucv_dev_attr_groups; priv->dev->release = (void (*)(struct device *)) kfree; rc = device_register(priv->dev); @@ -1376,11 +1328,6 @@ static int __init hvc_iucv_init(void) goto out_error; } - /* register IUCV HVC device driver */ - rc = driver_register(&hvc_iucv_driver); - if (rc) - goto out_error; - /* parse hvc_iucv_allow string and create z/VM user ID filter list */ if (hvc_iucv_filter_string) { rc = hvc_iucv_setup_filter(hvc_iucv_filter_string); diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c index 197988c55e0c..fe5e6b4f43de 100644 --- a/drivers/tty/hvc/hvcs.c +++ b/drivers/tty/hvc/hvcs.c @@ -1376,7 +1376,7 @@ static int hvcs_write(struct tty_struct *tty, * absolutely WILL BUFFER if we can't send it. This driver MUST honor the * return value, hence the reason for hvcs_struct buffering. */ -static int hvcs_write_room(struct tty_struct *tty) +static unsigned int hvcs_write_room(struct tty_struct *tty) { struct hvcs_struct *hvcsd = tty->driver_data; @@ -1386,7 +1386,7 @@ static int hvcs_write_room(struct tty_struct *tty) return HVCS_BUFF_LEN - hvcsd->chars_in_buffer; } -static int hvcs_chars_in_buffer(struct tty_struct *tty) +static unsigned int hvcs_chars_in_buffer(struct tty_struct *tty) { struct hvcs_struct *hvcsd = tty->driver_data; diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c index e8c58f9bd263..bfc15279d5bc 100644 --- a/drivers/tty/hvc/hvsi.c +++ b/drivers/tty/hvc/hvsi.c @@ -890,14 +890,14 @@ out: spin_unlock_irqrestore(&hp->lock, flags); } -static int hvsi_write_room(struct tty_struct *tty) +static unsigned int hvsi_write_room(struct tty_struct *tty) { struct hvsi_struct *hp = tty->driver_data; return N_OUTBUF - hp->n_outbuf; } -static int hvsi_chars_in_buffer(struct tty_struct *tty) +static unsigned int hvsi_chars_in_buffer(struct tty_struct *tty) { struct hvsi_struct *hp = tty->driver_data; @@ -929,7 +929,7 @@ static int hvsi_write(struct tty_struct *tty, * will see there is no room in outbuf and return. */ while ((count > 0) && (hvsi_write_room(tty) > 0)) { - int chunksize = min(count, hvsi_write_room(tty)); + int chunksize = min_t(int, count, hvsi_write_room(tty)); BUG_ON(hp->n_outbuf < 0); memcpy(hp->outbuf + hp->n_outbuf, source, chunksize); diff --git a/drivers/tty/ipwireless/tty.c b/drivers/tty/ipwireless/tty.c index 99bb2f149ff5..e3a5a5ba752c 100644 --- a/drivers/tty/ipwireless/tty.c +++ b/drivers/tty/ipwireless/tty.c @@ -54,7 +54,6 @@ struct ipw_tty { unsigned int control_lines; struct mutex ipw_tty_mutex; int tx_bytes_queued; - int closing; }; static struct ipw_tty *ttys[IPWIRELESS_PCMCIA_MINORS]; @@ -228,7 +227,7 @@ static int ipw_write(struct tty_struct *linux_tty, return count; } -static int ipw_write_room(struct tty_struct *linux_tty) +static unsigned int ipw_write_room(struct tty_struct *linux_tty) { struct ipw_tty *tty = linux_tty->driver_data; int room; @@ -270,7 +269,7 @@ static int ipwireless_set_serial_info(struct tty_struct *linux_tty, return 0; /* Keeps the PCMCIA scripts happy. */ } -static int ipw_chars_in_buffer(struct tty_struct *linux_tty) +static unsigned int ipw_chars_in_buffer(struct tty_struct *linux_tty) { struct ipw_tty *tty = linux_tty->driver_data; @@ -525,7 +524,6 @@ void ipwireless_tty_free(struct ipw_tty *tty) printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": deregistering %s device ttyIPWp%d\n", tty_type_name(ttyj->tty_type), j); - ttyj->closing = 1; if (ttyj->port.tty != NULL) { mutex_unlock(&ttyj->ipw_tty_mutex); tty_vhangup(ttyj->port.tty); diff --git a/drivers/tty/mips_ejtag_fdc.c b/drivers/tty/mips_ejtag_fdc.c index a8e19b4833bf..3b5915b94fac 100644 --- a/drivers/tty/mips_ejtag_fdc.c +++ b/drivers/tty/mips_ejtag_fdc.c @@ -840,11 +840,11 @@ static int mips_ejtag_fdc_tty_write(struct tty_struct *tty, return total; } -static int mips_ejtag_fdc_tty_write_room(struct tty_struct *tty) +static unsigned int mips_ejtag_fdc_tty_write_room(struct tty_struct *tty) { struct mips_ejtag_fdc_tty_port *dport = tty->driver_data; struct mips_ejtag_fdc_tty *priv = dport->driver; - int room; + unsigned int room; /* Report the space in the xmit buffer */ spin_lock(&dport->xmit_lock); @@ -854,10 +854,10 @@ static int mips_ejtag_fdc_tty_write_room(struct tty_struct *tty) return room; } -static int mips_ejtag_fdc_tty_chars_in_buffer(struct tty_struct *tty) +static unsigned int mips_ejtag_fdc_tty_chars_in_buffer(struct tty_struct *tty) { struct mips_ejtag_fdc_tty_port *dport = tty->driver_data; - int chars; + unsigned int chars; /* Report the number of bytes in the xmit buffer */ spin_lock(&dport->xmit_lock); diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c index 4d4f15b5cd29..64b18177c790 100644 --- a/drivers/tty/moxa.c +++ b/drivers/tty/moxa.c @@ -188,9 +188,9 @@ module_param(ttymajor, int, 0); static int moxa_open(struct tty_struct *, struct file *); static void moxa_close(struct tty_struct *, struct file *); static int moxa_write(struct tty_struct *, const unsigned char *, int); -static int moxa_write_room(struct tty_struct *); +static unsigned int moxa_write_room(struct tty_struct *); static void moxa_flush_buffer(struct tty_struct *); -static int moxa_chars_in_buffer(struct tty_struct *); +static unsigned int moxa_chars_in_buffer(struct tty_struct *); static void moxa_set_termios(struct tty_struct *, struct ktermios *); static void moxa_stop(struct tty_struct *); static void moxa_start(struct tty_struct *); @@ -216,9 +216,9 @@ static int MoxaPortLineStatus(struct moxa_port *); static void MoxaPortFlushData(struct moxa_port *, int); static int MoxaPortWriteData(struct tty_struct *, const unsigned char *, int); static int MoxaPortReadData(struct moxa_port *); -static int MoxaPortTxQueue(struct moxa_port *); +static unsigned int MoxaPortTxQueue(struct moxa_port *); static int MoxaPortRxQueue(struct moxa_port *); -static int MoxaPortTxFree(struct moxa_port *); +static unsigned int MoxaPortTxFree(struct moxa_port *); static void MoxaPortTxDisable(struct moxa_port *); static void MoxaPortTxEnable(struct moxa_port *); static int moxa_get_serial_info(struct tty_struct *, struct serial_struct *); @@ -1217,11 +1217,11 @@ static int moxa_write(struct tty_struct *tty, return len; } -static int moxa_write_room(struct tty_struct *tty) +static unsigned int moxa_write_room(struct tty_struct *tty) { struct moxa_port *ch; - if (tty->stopped) + if (tty->flow.stopped) return 0; ch = tty->driver_data; if (ch == NULL) @@ -1239,10 +1239,10 @@ static void moxa_flush_buffer(struct tty_struct *tty) tty_wakeup(tty); } -static int moxa_chars_in_buffer(struct tty_struct *tty) +static unsigned int moxa_chars_in_buffer(struct tty_struct *tty) { struct moxa_port *ch = tty->driver_data; - int chars; + unsigned int chars; chars = MoxaPortTxQueue(ch); if (chars) @@ -1374,7 +1374,7 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle, clear_bit(EMPTYWAIT, &p->statusflags); tty_wakeup(tty); } - if (test_bit(LOWWAIT, &p->statusflags) && !tty->stopped && + if (test_bit(LOWWAIT, &p->statusflags) && !tty->flow.stopped && MoxaPortTxQueue(p) <= WAKEUP_CHARS) { clear_bit(LOWWAIT, &p->statusflags); tty_wakeup(tty); @@ -1981,7 +1981,7 @@ static int MoxaPortReadData(struct moxa_port *port) } -static int MoxaPortTxQueue(struct moxa_port *port) +static unsigned int MoxaPortTxQueue(struct moxa_port *port) { void __iomem *ofsAddr = port->tableAddr; u16 rptr, wptr, mask; @@ -1992,7 +1992,7 @@ static int MoxaPortTxQueue(struct moxa_port *port) return (wptr - rptr) & mask; } -static int MoxaPortTxFree(struct moxa_port *port) +static unsigned int MoxaPortTxFree(struct moxa_port *port) { void __iomem *ofsAddr = port->tableAddr; u16 rptr, wptr, mask; diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 16a852ecbe8a..900ccb2ca166 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -41,9 +41,112 @@ #include <asm/irq.h> #include <linux/uaccess.h> -#include "mxser.h" +/* + * Semi-public control interfaces + */ + +/* + * MOXA ioctls + */ + +#define MOXA 0x400 +#define MOXA_SET_OP_MODE (MOXA + 66) +#define MOXA_GET_OP_MODE (MOXA + 67) + +#define RS232_MODE 0 +#define RS485_2WIRE_MODE 1 +#define RS422_MODE 2 +#define RS485_4WIRE_MODE 3 +#define OP_MODE_MASK 3 + +/* --------------------------------------------------- */ + +/* + * Follow just what Moxa Must chip defines. + * + * When LCR register (offset 0x03) is written the following value, the Must chip + * will enter enhanced mode. And a write to EFR (offset 0x02) bit 6,7 will + * change bank. + */ +#define MOXA_MUST_ENTER_ENHANCED 0xBF + +/* when enhanced mode is enabled, access to general bank register */ +#define MOXA_MUST_GDL_REGISTER 0x07 +#define MOXA_MUST_GDL_MASK 0x7F +#define MOXA_MUST_GDL_HAS_BAD_DATA 0x80 + +#define MOXA_MUST_LSR_RERR 0x80 /* error in receive FIFO */ +/* enhanced register bank select and enhanced mode setting register */ +/* This works only when LCR register equals to 0xBF */ +#define MOXA_MUST_EFR_REGISTER 0x02 +#define MOXA_MUST_EFR_EFRB_ENABLE 0x10 /* enhanced mode enable */ +/* enhanced register bank set 0, 1, 2 */ +#define MOXA_MUST_EFR_BANK0 0x00 +#define MOXA_MUST_EFR_BANK1 0x40 +#define MOXA_MUST_EFR_BANK2 0x80 +#define MOXA_MUST_EFR_BANK3 0xC0 +#define MOXA_MUST_EFR_BANK_MASK 0xC0 + +/* set XON1 value register, when LCR=0xBF and change to bank0 */ +#define MOXA_MUST_XON1_REGISTER 0x04 + +/* set XON2 value register, when LCR=0xBF and change to bank0 */ +#define MOXA_MUST_XON2_REGISTER 0x05 + +/* set XOFF1 value register, when LCR=0xBF and change to bank0 */ +#define MOXA_MUST_XOFF1_REGISTER 0x06 + +/* set XOFF2 value register, when LCR=0xBF and change to bank0 */ +#define MOXA_MUST_XOFF2_REGISTER 0x07 + +#define MOXA_MUST_RBRTL_REGISTER 0x04 +#define MOXA_MUST_RBRTH_REGISTER 0x05 +#define MOXA_MUST_RBRTI_REGISTER 0x06 +#define MOXA_MUST_THRTL_REGISTER 0x07 +#define MOXA_MUST_ENUM_REGISTER 0x04 +#define MOXA_MUST_HWID_REGISTER 0x05 +#define MOXA_MUST_ECR_REGISTER 0x06 +#define MOXA_MUST_CSR_REGISTER 0x07 + +#define MOXA_MUST_FCR_GDA_MODE_ENABLE 0x20 /* good data mode enable */ +#define MOXA_MUST_FCR_GDA_ONLY_ENABLE 0x10 /* only good data put into RxFIFO */ + +#define MOXA_MUST_IER_ECTSI 0x80 /* enable CTS interrupt */ +#define MOXA_MUST_IER_ERTSI 0x40 /* enable RTS interrupt */ +#define MOXA_MUST_IER_XINT 0x20 /* enable Xon/Xoff interrupt */ +#define MOXA_MUST_IER_EGDAI 0x10 /* enable GDA interrupt */ + +#define MOXA_MUST_RECV_ISR (UART_IER_RDI | MOXA_MUST_IER_EGDAI) + +/* GDA interrupt pending */ +#define MOXA_MUST_IIR_GDA 0x1C +#define MOXA_MUST_IIR_RDA 0x04 +#define MOXA_MUST_IIR_RTO 0x0C +#define MOXA_MUST_IIR_LSR 0x06 + +/* received Xon/Xoff or specical interrupt pending */ +#define MOXA_MUST_IIR_XSC 0x10 + +/* RTS/CTS change state interrupt pending */ +#define MOXA_MUST_IIR_RTSCTS 0x20 +#define MOXA_MUST_IIR_MASK 0x3E + +#define MOXA_MUST_MCR_XON_FLAG 0x40 +#define MOXA_MUST_MCR_XON_ANY 0x80 +#define MOXA_MUST_MCR_TX_XON 0x08 + +#define MOXA_MUST_EFR_SF_MASK 0x0F /* software flow control on chip mask value */ +#define MOXA_MUST_EFR_SF_TX1 0x08 /* send Xon1/Xoff1 */ +#define MOXA_MUST_EFR_SF_TX2 0x04 /* send Xon2/Xoff2 */ +#define MOXA_MUST_EFR_SF_TX12 0x0C /* send Xon1,Xon2/Xoff1,Xoff2 */ +#define MOXA_MUST_EFR_SF_TX_NO 0x00 /* don't send Xon/Xoff */ +#define MOXA_MUST_EFR_SF_TX_MASK 0x0C /* Tx software flow control mask */ +#define MOXA_MUST_EFR_SF_RX_NO 0x00 /* don't receive Xon/Xoff */ +#define MOXA_MUST_EFR_SF_RX1 0x02 /* receive Xon1/Xoff1 */ +#define MOXA_MUST_EFR_SF_RX2 0x01 /* receive Xon2/Xoff2 */ +#define MOXA_MUST_EFR_SF_RX12 0x03 /* receive Xon1,Xon2/Xoff1,Xoff2 */ +#define MOXA_MUST_EFR_SF_RX_MASK 0x03 /* Rx software flow control mask */ -#define MXSER_VERSION "2.0.5" /* 1.14 */ #define MXSERMAJOR 174 #define MXSER_BOARDS 4 /* Max. boards */ @@ -51,15 +154,10 @@ #define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD) #define MXSER_ISR_PASS_LIMIT 100 -/*CheckIsMoxaMust return value*/ -#define MOXA_OTHER_UART 0x00 -#define MOXA_MUST_MU150_HWID 0x01 -#define MOXA_MUST_MU860_HWID 0x02 - #define WAKEUP_CHARS 256 -#define UART_MCR_AFE 0x20 -#define UART_LSR_SPECIAL 0x1E +#define MXSER_BAUD_BASE 921600 +#define MXSER_CUSTOM_DIVISOR (MXSER_BAUD_BASE * 16) #define PCI_DEVICE_ID_POS104UL 0x1044 #define PCI_DEVICE_ID_CB108 0x1080 @@ -70,151 +168,71 @@ #define PCI_DEVICE_ID_CB134I 0x1341 #define PCI_DEVICE_ID_CP138U 0x1380 +#define MXSER_NPORTS(ddata) ((ddata) & 0xffU) +#define MXSER_HIGHBAUD 0x0100 -#define C168_ASIC_ID 1 -#define C104_ASIC_ID 2 -#define C102_ASIC_ID 0xB -#define CI132_ASIC_ID 4 -#define CI134_ASIC_ID 3 -#define CI104J_ASIC_ID 5 - -#define MXSER_HIGHBAUD 1 -#define MXSER_HAS2 2 +enum mxser_must_hwid { + MOXA_OTHER_UART = 0x00, + MOXA_MUST_MU150_HWID = 0x01, + MOXA_MUST_MU860_HWID = 0x02, +}; -/* This is only for PCI */ static const struct { - int type; - int tx_fifo; - int rx_fifo; - int xmit_fifo_size; - int rx_high_water; - int rx_trigger; - int rx_low_water; - long max_baud; + u8 type; + u8 fifo_size; + u8 rx_high_water; + u8 rx_low_water; + speed_t max_baud; } Gpci_uart_info[] = { - {MOXA_OTHER_UART, 16, 16, 16, 14, 14, 1, 921600L}, - {MOXA_MUST_MU150_HWID, 64, 64, 64, 48, 48, 16, 230400L}, - {MOXA_MUST_MU860_HWID, 128, 128, 128, 96, 96, 32, 921600L} + { MOXA_OTHER_UART, 16, 14, 1, 921600 }, + { MOXA_MUST_MU150_HWID, 64, 48, 16, 230400 }, + { MOXA_MUST_MU860_HWID, 128, 96, 32, 921600 } }; #define UART_INFO_NUM ARRAY_SIZE(Gpci_uart_info) -struct mxser_cardinfo { - char *name; - unsigned int nports; - unsigned int flags; -}; - -static const struct mxser_cardinfo mxser_cards[] = { -/* 0*/ { "C168 series", 8, }, - { "C104 series", 4, }, - { "CI-104J series", 4, }, - { "C168H/PCI series", 8, }, - { "C104H/PCI series", 4, }, -/* 5*/ { "C102 series", 4, MXSER_HAS2 }, /* C102-ISA */ - { "CI-132 series", 4, MXSER_HAS2 }, - { "CI-134 series", 4, }, - { "CP-132 series", 2, }, - { "CP-114 series", 4, }, -/*10*/ { "CT-114 series", 4, }, - { "CP-102 series", 2, MXSER_HIGHBAUD }, - { "CP-104U series", 4, }, - { "CP-168U series", 8, }, - { "CP-132U series", 2, }, -/*15*/ { "CP-134U series", 4, }, - { "CP-104JU series", 4, }, - { "Moxa UC7000 Serial", 8, }, /* RC7000 */ - { "CP-118U series", 8, }, - { "CP-102UL series", 2, }, -/*20*/ { "CP-102U series", 2, }, - { "CP-118EL series", 8, }, - { "CP-168EL series", 8, }, - { "CP-104EL series", 4, }, - { "CB-108 series", 8, }, -/*25*/ { "CB-114 series", 4, }, - { "CB-134I series", 4, }, - { "CP-138U series", 8, }, - { "POS-104UL series", 4, }, - { "CP-114UL series", 4, }, -/*30*/ { "CP-102UF series", 2, }, - { "CP-112UL series", 2, }, -}; /* driver_data correspond to the lines in the structure above see also ISA probe function before you change something */ static const struct pci_device_id mxser_pcibrds[] = { - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C168), .driver_data = 3 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C168), .driver_data = 8 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C104), .driver_data = 4 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132), .driver_data = 8 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP114), .driver_data = 9 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CT114), .driver_data = 10 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102), .driver_data = 11 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104U), .driver_data = 12 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168U), .driver_data = 13 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132U), .driver_data = 14 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP134U), .driver_data = 15 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104JU),.driver_data = 16 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_RC7000), .driver_data = 17 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118U), .driver_data = 18 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102UL),.driver_data = 19 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102U), .driver_data = 20 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118EL),.driver_data = 21 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168EL),.driver_data = 22 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104EL),.driver_data = 23 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB108), .driver_data = 24 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB114), .driver_data = 25 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB134I), .driver_data = 26 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U), .driver_data = 27 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL), .driver_data = 28 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL), .driver_data = 29 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP102UF), .driver_data = 30 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP112UL), .driver_data = 31 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132), .driver_data = 2 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP114), .driver_data = 4 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CT114), .driver_data = 4 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102), .driver_data = 2 | MXSER_HIGHBAUD }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104U), .driver_data = 4 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168U), .driver_data = 8 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132U), .driver_data = 2 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP134U), .driver_data = 4 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104JU),.driver_data = 4 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_RC7000), .driver_data = 8 }, /* RC7000 */ + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118U), .driver_data = 8 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102UL),.driver_data = 2 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102U), .driver_data = 2 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118EL),.driver_data = 8 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168EL),.driver_data = 8 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104EL),.driver_data = 4 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB108), .driver_data = 8 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB114), .driver_data = 4 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB134I), .driver_data = 4 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U), .driver_data = 8 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL), .driver_data = 4 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL), .driver_data = 4 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP102UF), .driver_data = 2 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP112UL), .driver_data = 2 }, { } }; MODULE_DEVICE_TABLE(pci, mxser_pcibrds); -static unsigned long ioaddr[MXSER_BOARDS]; static int ttymajor = MXSERMAJOR; /* Variables for insmod */ MODULE_AUTHOR("Casper Yang"); MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); -module_param_hw_array(ioaddr, ulong, ioport, NULL, 0); -MODULE_PARM_DESC(ioaddr, "ISA io addresses to look for a moxa board"); module_param(ttymajor, int, 0); MODULE_LICENSE("GPL"); -struct mxser_log { - int tick; - unsigned long rxcnt[MXSER_PORTS]; - unsigned long txcnt[MXSER_PORTS]; -}; - -struct mxser_mon { - unsigned long rxcnt; - unsigned long txcnt; - unsigned long up_rxcnt; - unsigned long up_txcnt; - int modem_status; - unsigned char hold_reason; -}; - -struct mxser_mon_ext { - unsigned long rx_cnt[32]; - unsigned long tx_cnt[32]; - unsigned long up_rxcnt[32]; - unsigned long up_txcnt[32]; - int modem_status[32]; - - long baudrate[32]; - int databits[32]; - int stopbits[32]; - int parity[32]; - int flowctrl[32]; - int fifo[32]; - int iftype[32]; -}; - struct mxser_board; struct mxser_port { @@ -223,274 +241,147 @@ struct mxser_port { unsigned long ioaddr; unsigned long opmode_ioaddr; - int max_baud; - int rx_high_water; - int rx_trigger; /* Rx fifo trigger level */ - int rx_low_water; - int baud_base; /* max. speed */ + u8 rx_high_water; + u8 rx_low_water; int type; /* UART type */ - int x_char; /* xon/xoff character */ - int IER; /* Interrupt Enable Register */ - int MCR; /* Modem control register */ + unsigned char x_char; /* xon/xoff character */ + u8 IER; /* Interrupt Enable Register */ + u8 MCR; /* Modem control register */ - unsigned char stop_rx; unsigned char ldisc_stop_rx; - int custom_divisor; - unsigned char err_shadow; - struct async_icount icount; /* kernel counters for 4 input interrupts */ unsigned int timeout; - int read_status_mask; - int ignore_status_mask; - unsigned int xmit_fifo_size; - int xmit_head; - int xmit_tail; - int xmit_cnt; + u8 read_status_mask; + u8 ignore_status_mask; + u8 xmit_fifo_size; + unsigned int xmit_head; + unsigned int xmit_tail; + unsigned int xmit_cnt; int closing; - struct ktermios normal_termios; - - struct mxser_mon mon_data; - spinlock_t slock; }; struct mxser_board { unsigned int idx; + unsigned short nports; int irq; - const struct mxser_cardinfo *info; unsigned long vector; - unsigned long vector_mask; - - int chip_flag; - int uart_type; - struct mxser_port ports[MXSER_PORTS_PER_BOARD]; -}; + enum mxser_must_hwid must_hwid; + speed_t max_baud; -struct mxser_mstatus { - tcflag_t cflag; - int cts; - int dsr; - int ri; - int dcd; + struct mxser_port ports[]; }; -static struct mxser_board mxser_boards[MXSER_BOARDS]; +static DECLARE_BITMAP(mxser_boards, MXSER_BOARDS); static struct tty_driver *mxvar_sdriver; -static struct mxser_log mxvar_log; -static int mxser_set_baud_method[MXSER_PORTS + 1]; -static void mxser_enable_must_enchance_mode(unsigned long baseio) +static u8 __mxser_must_set_EFR(unsigned long baseio, u8 clear, u8 set, + bool restore_LCR) { - u8 oldlcr; - u8 efr; + u8 oldlcr, efr; oldlcr = inb(baseio + UART_LCR); - outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); + outb(MOXA_MUST_ENTER_ENHANCED, baseio + UART_LCR); efr = inb(baseio + MOXA_MUST_EFR_REGISTER); - efr |= MOXA_MUST_EFR_EFRB_ENABLE; + efr &= ~clear; + efr |= set; outb(efr, baseio + MOXA_MUST_EFR_REGISTER); - outb(oldlcr, baseio + UART_LCR); -} -#ifdef CONFIG_PCI -static void mxser_disable_must_enchance_mode(unsigned long baseio) -{ - u8 oldlcr; - u8 efr; + if (restore_LCR) + outb(oldlcr, baseio + UART_LCR); - oldlcr = inb(baseio + UART_LCR); - outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); - - efr = inb(baseio + MOXA_MUST_EFR_REGISTER); - efr &= ~MOXA_MUST_EFR_EFRB_ENABLE; + return oldlcr; +} - outb(efr, baseio + MOXA_MUST_EFR_REGISTER); - outb(oldlcr, baseio + UART_LCR); +static u8 mxser_must_select_bank(unsigned long baseio, u8 bank) +{ + return __mxser_must_set_EFR(baseio, MOXA_MUST_EFR_BANK_MASK, bank, + false); } -#endif static void mxser_set_must_xon1_value(unsigned long baseio, u8 value) { - u8 oldlcr; - u8 efr; - - oldlcr = inb(baseio + UART_LCR); - outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); - - efr = inb(baseio + MOXA_MUST_EFR_REGISTER); - efr &= ~MOXA_MUST_EFR_BANK_MASK; - efr |= MOXA_MUST_EFR_BANK0; - - outb(efr, baseio + MOXA_MUST_EFR_REGISTER); + u8 oldlcr = mxser_must_select_bank(baseio, MOXA_MUST_EFR_BANK0); outb(value, baseio + MOXA_MUST_XON1_REGISTER); outb(oldlcr, baseio + UART_LCR); } static void mxser_set_must_xoff1_value(unsigned long baseio, u8 value) { - u8 oldlcr; - u8 efr; - - oldlcr = inb(baseio + UART_LCR); - outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); - - efr = inb(baseio + MOXA_MUST_EFR_REGISTER); - efr &= ~MOXA_MUST_EFR_BANK_MASK; - efr |= MOXA_MUST_EFR_BANK0; - - outb(efr, baseio + MOXA_MUST_EFR_REGISTER); + u8 oldlcr = mxser_must_select_bank(baseio, MOXA_MUST_EFR_BANK0); outb(value, baseio + MOXA_MUST_XOFF1_REGISTER); outb(oldlcr, baseio + UART_LCR); } static void mxser_set_must_fifo_value(struct mxser_port *info) { - u8 oldlcr; - u8 efr; - - oldlcr = inb(info->ioaddr + UART_LCR); - outb(MOXA_MUST_ENTER_ENCHANCE, info->ioaddr + UART_LCR); - - efr = inb(info->ioaddr + MOXA_MUST_EFR_REGISTER); - efr &= ~MOXA_MUST_EFR_BANK_MASK; - efr |= MOXA_MUST_EFR_BANK1; - - outb(efr, info->ioaddr + MOXA_MUST_EFR_REGISTER); - outb((u8)info->rx_high_water, info->ioaddr + MOXA_MUST_RBRTH_REGISTER); - outb((u8)info->rx_trigger, info->ioaddr + MOXA_MUST_RBRTI_REGISTER); - outb((u8)info->rx_low_water, info->ioaddr + MOXA_MUST_RBRTL_REGISTER); + u8 oldlcr = mxser_must_select_bank(info->ioaddr, MOXA_MUST_EFR_BANK1); + outb(info->rx_high_water, info->ioaddr + MOXA_MUST_RBRTH_REGISTER); + outb(info->rx_high_water, info->ioaddr + MOXA_MUST_RBRTI_REGISTER); + outb(info->rx_low_water, info->ioaddr + MOXA_MUST_RBRTL_REGISTER); outb(oldlcr, info->ioaddr + UART_LCR); } static void mxser_set_must_enum_value(unsigned long baseio, u8 value) { - u8 oldlcr; - u8 efr; - - oldlcr = inb(baseio + UART_LCR); - outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); - - efr = inb(baseio + MOXA_MUST_EFR_REGISTER); - efr &= ~MOXA_MUST_EFR_BANK_MASK; - efr |= MOXA_MUST_EFR_BANK2; - - outb(efr, baseio + MOXA_MUST_EFR_REGISTER); + u8 oldlcr = mxser_must_select_bank(baseio, MOXA_MUST_EFR_BANK2); outb(value, baseio + MOXA_MUST_ENUM_REGISTER); outb(oldlcr, baseio + UART_LCR); } -#ifdef CONFIG_PCI -static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId) +static u8 mxser_get_must_hardware_id(unsigned long baseio) { - u8 oldlcr; - u8 efr; - - oldlcr = inb(baseio + UART_LCR); - outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); - - efr = inb(baseio + MOXA_MUST_EFR_REGISTER); - efr &= ~MOXA_MUST_EFR_BANK_MASK; - efr |= MOXA_MUST_EFR_BANK2; - - outb(efr, baseio + MOXA_MUST_EFR_REGISTER); - *pId = inb(baseio + MOXA_MUST_HWID_REGISTER); + u8 oldlcr = mxser_must_select_bank(baseio, MOXA_MUST_EFR_BANK2); + u8 id = inb(baseio + MOXA_MUST_HWID_REGISTER); outb(oldlcr, baseio + UART_LCR); + + return id; } -#endif -static void SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(unsigned long baseio) +static void mxser_must_set_EFR(unsigned long baseio, u8 clear, u8 set) { - u8 oldlcr; - u8 efr; - - oldlcr = inb(baseio + UART_LCR); - outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); - - efr = inb(baseio + MOXA_MUST_EFR_REGISTER); - efr &= ~MOXA_MUST_EFR_SF_MASK; - - outb(efr, baseio + MOXA_MUST_EFR_REGISTER); - outb(oldlcr, baseio + UART_LCR); + __mxser_must_set_EFR(baseio, clear, set, true); } -static void mxser_enable_must_tx_software_flow_control(unsigned long baseio) +static void mxser_must_set_enhance_mode(unsigned long baseio, bool enable) { - u8 oldlcr; - u8 efr; - - oldlcr = inb(baseio + UART_LCR); - outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); - - efr = inb(baseio + MOXA_MUST_EFR_REGISTER); - efr &= ~MOXA_MUST_EFR_SF_TX_MASK; - efr |= MOXA_MUST_EFR_SF_TX1; - - outb(efr, baseio + MOXA_MUST_EFR_REGISTER); - outb(oldlcr, baseio + UART_LCR); + mxser_must_set_EFR(baseio, + enable ? 0 : MOXA_MUST_EFR_EFRB_ENABLE, + enable ? MOXA_MUST_EFR_EFRB_ENABLE : 0); } -static void mxser_disable_must_tx_software_flow_control(unsigned long baseio) +static void mxser_must_no_sw_flow_control(unsigned long baseio) { - u8 oldlcr; - u8 efr; - - oldlcr = inb(baseio + UART_LCR); - outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); - - efr = inb(baseio + MOXA_MUST_EFR_REGISTER); - efr &= ~MOXA_MUST_EFR_SF_TX_MASK; - - outb(efr, baseio + MOXA_MUST_EFR_REGISTER); - outb(oldlcr, baseio + UART_LCR); + mxser_must_set_EFR(baseio, MOXA_MUST_EFR_SF_MASK, 0); } -static void mxser_enable_must_rx_software_flow_control(unsigned long baseio) +static void mxser_must_set_tx_sw_flow_control(unsigned long baseio, bool enable) { - u8 oldlcr; - u8 efr; - - oldlcr = inb(baseio + UART_LCR); - outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); - - efr = inb(baseio + MOXA_MUST_EFR_REGISTER); - efr &= ~MOXA_MUST_EFR_SF_RX_MASK; - efr |= MOXA_MUST_EFR_SF_RX1; - - outb(efr, baseio + MOXA_MUST_EFR_REGISTER); - outb(oldlcr, baseio + UART_LCR); + mxser_must_set_EFR(baseio, MOXA_MUST_EFR_SF_TX_MASK, + enable ? MOXA_MUST_EFR_SF_TX1 : 0); } -static void mxser_disable_must_rx_software_flow_control(unsigned long baseio) +static void mxser_must_set_rx_sw_flow_control(unsigned long baseio, bool enable) { - u8 oldlcr; - u8 efr; - - oldlcr = inb(baseio + UART_LCR); - outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR); - - efr = inb(baseio + MOXA_MUST_EFR_REGISTER); - efr &= ~MOXA_MUST_EFR_SF_RX_MASK; - - outb(efr, baseio + MOXA_MUST_EFR_REGISTER); - outb(oldlcr, baseio + UART_LCR); + mxser_must_set_EFR(baseio, MOXA_MUST_EFR_SF_RX_MASK, + enable ? MOXA_MUST_EFR_SF_RX1 : 0); } -#ifdef CONFIG_PCI -static int CheckIsMoxaMust(unsigned long io) +static enum mxser_must_hwid mxser_must_get_hwid(unsigned long io) { u8 oldmcr, hwid; int i; outb(0, io + UART_LCR); - mxser_disable_must_enchance_mode(io); + mxser_must_set_enhance_mode(io, false); oldmcr = inb(io + UART_MCR); outb(0, io + UART_MCR); mxser_set_must_xon1_value(io, 0x11); @@ -499,49 +390,59 @@ static int CheckIsMoxaMust(unsigned long io) return MOXA_OTHER_UART; } - mxser_get_must_hardware_id(io, &hwid); - for (i = 1; i < UART_INFO_NUM; i++) { /* 0 = OTHER_UART */ + hwid = mxser_get_must_hardware_id(io); + for (i = 1; i < UART_INFO_NUM; i++) /* 0 = OTHER_UART */ if (hwid == Gpci_uart_info[i].type) - return (int)hwid; - } + return hwid; + return MOXA_OTHER_UART; } -#endif -static void process_txrx_fifo(struct mxser_port *info) +static bool mxser_16550A_or_MUST(struct mxser_port *info) { - int i; + return info->type == PORT_16550A || info->board->must_hwid; +} - if ((info->type == PORT_16450) || (info->type == PORT_8250)) { - info->rx_trigger = 1; +static void mxser_process_txrx_fifo(struct mxser_port *info) +{ + unsigned int i; + + if (info->type == PORT_16450 || info->type == PORT_8250) { info->rx_high_water = 1; info->rx_low_water = 1; info->xmit_fifo_size = 1; - } else - for (i = 0; i < UART_INFO_NUM; i++) - if (info->board->chip_flag == Gpci_uart_info[i].type) { - info->rx_trigger = Gpci_uart_info[i].rx_trigger; - info->rx_low_water = Gpci_uart_info[i].rx_low_water; - info->rx_high_water = Gpci_uart_info[i].rx_high_water; - info->xmit_fifo_size = Gpci_uart_info[i].xmit_fifo_size; - break; - } + return; + } + + for (i = 0; i < UART_INFO_NUM; i++) + if (info->board->must_hwid == Gpci_uart_info[i].type) { + info->rx_low_water = Gpci_uart_info[i].rx_low_water; + info->rx_high_water = Gpci_uart_info[i].rx_high_water; + info->xmit_fifo_size = Gpci_uart_info[i].fifo_size; + break; + } } -static unsigned char mxser_get_msr(int baseaddr, int mode, int port) +static void __mxser_start_tx(struct mxser_port *info) { - static unsigned char mxser_msr[MXSER_PORTS + 1]; - unsigned char status = 0; + outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); +} - status = inb(baseaddr + UART_MSR); +static void mxser_start_tx(struct mxser_port *info) +{ + unsigned long flags; - mxser_msr[port] &= 0x0F; - mxser_msr[port] |= status; - status = mxser_msr[port]; - if (mode) - mxser_msr[port] = 0; + spin_lock_irqsave(&info->slock, flags); + __mxser_start_tx(info); + spin_unlock_irqrestore(&info->slock, flags); +} - return status; +static void __mxser_stop_tx(struct mxser_port *info) +{ + info->IER &= ~UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); } static int mxser_carrier_raised(struct tty_port *port) @@ -554,38 +455,36 @@ static void mxser_dtr_rts(struct tty_port *port, int on) { struct mxser_port *mp = container_of(port, struct mxser_port, port); unsigned long flags; + u8 mcr; spin_lock_irqsave(&mp->slock, flags); + mcr = inb(mp->ioaddr + UART_MCR); if (on) - outb(inb(mp->ioaddr + UART_MCR) | - UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR); + mcr |= UART_MCR_DTR | UART_MCR_RTS; else - outb(inb(mp->ioaddr + UART_MCR)&~(UART_MCR_DTR | UART_MCR_RTS), - mp->ioaddr + UART_MCR); + mcr &= ~(UART_MCR_DTR | UART_MCR_RTS); + outb(mcr, mp->ioaddr + UART_MCR); spin_unlock_irqrestore(&mp->slock, flags); } -static int mxser_set_baud(struct tty_struct *tty, long newspd) +static int mxser_set_baud(struct tty_struct *tty, speed_t newspd) { struct mxser_port *info = tty->driver_data; unsigned int quot = 0, baud; unsigned char cval; u64 timeout; - if (!info->ioaddr) - return -1; - - if (newspd > info->max_baud) + if (newspd > info->board->max_baud) return -1; if (newspd == 134) { - quot = 2 * info->baud_base / 269; + quot = 2 * MXSER_BAUD_BASE / 269; tty_encode_baud_rate(tty, 134, 134); } else if (newspd) { - quot = info->baud_base / newspd; + quot = MXSER_BAUD_BASE / newspd; if (quot == 0) quot = 1; - baud = info->baud_base/quot; + baud = MXSER_BAUD_BASE / quot; tty_encode_baud_rate(tty, baud, baud); } else { quot = 0; @@ -596,7 +495,7 @@ static int mxser_set_baud(struct tty_struct *tty, long newspd) * u64 domain */ timeout = (u64)info->xmit_fifo_size * HZ * 10 * quot; - do_div(timeout, info->baud_base); + do_div(timeout, MXSER_BAUD_BASE); info->timeout = timeout + HZ / 50; /* Add .02 seconds of slop */ if (quot) { @@ -618,7 +517,7 @@ static int mxser_set_baud(struct tty_struct *tty, long newspd) #ifdef BOTHER if (C_BAUD(tty) == BOTHER) { - quot = info->baud_base % newspd; + quot = MXSER_BAUD_BASE % newspd; quot *= 8; if (quot % newspd > newspd / 2) { quot /= newspd; @@ -634,6 +533,28 @@ static int mxser_set_baud(struct tty_struct *tty, long newspd) return 0; } +static void mxser_handle_cts(struct tty_struct *tty, struct mxser_port *info, + u8 msr) +{ + bool cts = msr & UART_MSR_CTS; + + if (tty->hw_stopped) { + if (cts) { + tty->hw_stopped = 0; + + if (!mxser_16550A_or_MUST(info)) + __mxser_start_tx(info); + tty_wakeup(tty); + } + return; + } else if (cts) + return; + + tty->hw_stopped = 1; + if (!mxser_16550A_or_MUST(info)) + __mxser_stop_tx(info); +} + /* * This routine is called to set the UART divisor registers to match * the specified baud rate for a serial port. @@ -642,35 +563,30 @@ static void mxser_change_speed(struct tty_struct *tty) { struct mxser_port *info = tty->driver_data; unsigned cflag, cval, fcr; - unsigned char status; cflag = tty->termios.c_cflag; - if (!info->ioaddr) - return; - if (mxser_set_baud_method[tty->index] == 0) - mxser_set_baud(tty, tty_get_baud_rate(tty)); + mxser_set_baud(tty, tty_get_baud_rate(tty)); /* byte size and parity */ switch (cflag & CSIZE) { + default: case CS5: - cval = 0x00; + cval = UART_LCR_WLEN5; break; case CS6: - cval = 0x01; + cval = UART_LCR_WLEN6; break; case CS7: - cval = 0x02; + cval = UART_LCR_WLEN7; break; case CS8: - cval = 0x03; + cval = UART_LCR_WLEN8; break; - default: - cval = 0x00; - break; /* too keep GCC shut... */ } + if (cflag & CSTOPB) - cval |= 0x04; + cval |= UART_LCR_STOP; if (cflag & PARENB) cval |= UART_LCR_PARITY; if (!(cflag & PARODD)) @@ -679,7 +595,7 @@ static void mxser_change_speed(struct tty_struct *tty) cval |= UART_LCR_SPAR; if ((info->type == PORT_8250) || (info->type == PORT_16450)) { - if (info->board->chip_flag) { + if (info->board->must_hwid) { fcr = UART_FCR_ENABLE_FIFO; fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE; mxser_set_must_fifo_value(info); @@ -687,11 +603,11 @@ static void mxser_change_speed(struct tty_struct *tty) fcr = 0; } else { fcr = UART_FCR_ENABLE_FIFO; - if (info->board->chip_flag) { + if (info->board->must_hwid) { fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE; mxser_set_must_fifo_value(info); } else { - switch (info->rx_trigger) { + switch (info->rx_high_water) { case 1: fcr |= UART_FCR_TRIGGER_1; break; @@ -714,35 +630,11 @@ static void mxser_change_speed(struct tty_struct *tty) tty_port_set_cts_flow(&info->port, cflag & CRTSCTS); if (cflag & CRTSCTS) { info->IER |= UART_IER_MSI; - if ((info->type == PORT_16550A) || (info->board->chip_flag)) { + if (mxser_16550A_or_MUST(info)) { info->MCR |= UART_MCR_AFE; } else { - status = inb(info->ioaddr + UART_MSR); - if (tty->hw_stopped) { - if (status & UART_MSR_CTS) { - tty->hw_stopped = 0; - if (info->type != PORT_16550A && - !info->board->chip_flag) { - outb(info->IER & ~UART_IER_THRI, - info->ioaddr + - UART_IER); - info->IER |= UART_IER_THRI; - outb(info->IER, info->ioaddr + - UART_IER); - } - tty_wakeup(tty); - } - } else { - if (!(status & UART_MSR_CTS)) { - tty->hw_stopped = 1; - if ((info->type != PORT_16550A) && - (!info->board->chip_flag)) { - info->IER &= ~UART_IER_THRI; - outb(info->IER, info->ioaddr + - UART_IER); - } - } - } + mxser_handle_cts(tty, info, + inb(info->ioaddr + UART_MSR)); } } outb(info->MCR, info->ioaddr + UART_MCR); @@ -780,23 +672,11 @@ static void mxser_change_speed(struct tty_struct *tty) UART_LSR_FE; } } - if (info->board->chip_flag) { + if (info->board->must_hwid) { mxser_set_must_xon1_value(info->ioaddr, START_CHAR(tty)); mxser_set_must_xoff1_value(info->ioaddr, STOP_CHAR(tty)); - if (I_IXON(tty)) { - mxser_enable_must_rx_software_flow_control( - info->ioaddr); - } else { - mxser_disable_must_rx_software_flow_control( - info->ioaddr); - } - if (I_IXOFF(tty)) { - mxser_enable_must_tx_software_flow_control( - info->ioaddr); - } else { - mxser_disable_must_tx_software_flow_control( - info->ioaddr); - } + mxser_must_set_rx_sw_flow_control(info->ioaddr, I_IXON(tty)); + mxser_must_set_tx_sw_flow_control(info->ioaddr, I_IXOFF(tty)); } @@ -816,7 +696,6 @@ static void mxser_check_modem_status(struct tty_struct *tty, port->icount.dcd++; if (status & UART_MSR_DCTS) port->icount.cts++; - port->mon_data.modem_status = status; wake_up_interruptible(&port->port.delta_msr_wait); if (tty_port_check_carrier(&port->port) && (status & UART_MSR_DDCD)) { @@ -824,33 +703,8 @@ static void mxser_check_modem_status(struct tty_struct *tty, wake_up_interruptible(&port->port.open_wait); } - if (tty_port_cts_enabled(&port->port)) { - if (tty->hw_stopped) { - if (status & UART_MSR_CTS) { - tty->hw_stopped = 0; - - if ((port->type != PORT_16550A) && - (!port->board->chip_flag)) { - outb(port->IER & ~UART_IER_THRI, - port->ioaddr + UART_IER); - port->IER |= UART_IER_THRI; - outb(port->IER, port->ioaddr + - UART_IER); - } - tty_wakeup(tty); - } - } else { - if (!(status & UART_MSR_CTS)) { - tty->hw_stopped = 1; - if (port->type != PORT_16550A && - !port->board->chip_flag) { - port->IER &= ~UART_IER_THRI; - outb(port->IER, port->ioaddr + - UART_IER); - } - } - } - } + if (tty_port_cts_enabled(&port->port)) + mxser_handle_cts(tty, port, status); } static int mxser_activate(struct tty_port *port, struct tty_struct *tty) @@ -865,7 +719,7 @@ static int mxser_activate(struct tty_port *port, struct tty_struct *tty) spin_lock_irqsave(&info->slock, flags); - if (!info->ioaddr || !info->type) { + if (!info->type) { set_bit(TTY_IO_ERROR, &tty->flags); free_page(page); spin_unlock_irqrestore(&info->slock, flags); @@ -877,7 +731,7 @@ static int mxser_activate(struct tty_port *port, struct tty_struct *tty) * Clear the FIFO buffers and disable them * (they will be reenabled in mxser_change_speed()) */ - if (info->board->chip_flag) + if (info->board->must_hwid) outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | MOXA_MUST_FCR_GDA_MODE_ENABLE), info->ioaddr + UART_FCR); @@ -919,7 +773,7 @@ static int mxser_activate(struct tty_port *port, struct tty_struct *tty) */ info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; - if (info->board->chip_flag) + if (info->board->must_hwid) info->IER |= MOXA_MUST_IER_EGDAI; outb(info->IER, info->ioaddr + UART_IER); /* enable interrupts */ @@ -971,7 +825,7 @@ static void mxser_shutdown_port(struct tty_port *port) outb(0x00, info->ioaddr + UART_IER); /* clear Rx/Tx FIFO's */ - if (info->board->chip_flag) + if (info->board->must_hwid) outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | MOXA_MUST_FCR_GDA_MODE_ENABLE, info->ioaddr + UART_FCR); @@ -983,8 +837,8 @@ static void mxser_shutdown_port(struct tty_port *port) (void) inb(info->ioaddr + UART_RX); - if (info->board->chip_flag) - SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr); + if (info->board->must_hwid) + mxser_must_no_sw_flow_control(info->ioaddr); spin_unlock_irqrestore(&info->slock, flags); } @@ -997,18 +851,12 @@ static void mxser_shutdown_port(struct tty_port *port) */ static int mxser_open(struct tty_struct *tty, struct file *filp) { - struct mxser_port *info; - int line; + struct tty_port *tport = tty->port; + struct mxser_port *port = container_of(tport, struct mxser_port, port); - line = tty->index; - if (line == MXSER_PORTS) - return 0; - info = &mxser_boards[line / MXSER_PORTS_PER_BOARD].ports[line % MXSER_PORTS_PER_BOARD]; - if (!info->ioaddr) - return -ENODEV; + tty->driver_data = port; - tty->driver_data = info; - return tty_port_open(&info->port, tty, filp); + return tty_port_open(tport, tty, filp); } static void mxser_flush_buffer(struct tty_struct *tty) @@ -1043,7 +891,7 @@ static void mxser_close_port(struct tty_port *port) * line status register. */ info->IER &= ~UART_IER_RLSI; - if (info->board->chip_flag) + if (info->board->must_hwid) info->IER &= ~MOXA_MUST_RECV_ISR; outb(info->IER, info->ioaddr + UART_IER); @@ -1071,7 +919,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) struct mxser_port *info = tty->driver_data; struct tty_port *port = &info->port; - if (tty->index == MXSER_PORTS || info == NULL) + if (info == NULL) return; if (tty_port_close_start(port, tty, filp) == 0) return; @@ -1118,18 +966,10 @@ static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int cou total += c; } - if (info->xmit_cnt && !tty->stopped) { - if (!tty->hw_stopped || - (info->type == PORT_16550A) || - (info->board->chip_flag)) { - spin_lock_irqsave(&info->slock, flags); - outb(info->IER & ~UART_IER_THRI, info->ioaddr + - UART_IER); - info->IER |= UART_IER_THRI; - outb(info->IER, info->ioaddr + UART_IER); - spin_unlock_irqrestore(&info->slock, flags); - } - } + if (info->xmit_cnt && !tty->flow.stopped) + if (!tty->hw_stopped || mxser_16550A_or_MUST(info)) + mxser_start_tx(info); + return total; } @@ -1149,17 +989,7 @@ static int mxser_put_char(struct tty_struct *tty, unsigned char ch) info->xmit_head &= SERIAL_XMIT_SIZE - 1; info->xmit_cnt++; spin_unlock_irqrestore(&info->slock, flags); - if (!tty->stopped) { - if (!tty->hw_stopped || - (info->type == PORT_16550A) || - info->board->chip_flag) { - spin_lock_irqsave(&info->slock, flags); - outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); - info->IER |= UART_IER_THRI; - outb(info->IER, info->ioaddr + UART_IER); - spin_unlock_irqrestore(&info->slock, flags); - } - } + return 1; } @@ -1167,23 +997,15 @@ static int mxser_put_char(struct tty_struct *tty, unsigned char ch) static void mxser_flush_chars(struct tty_struct *tty) { struct mxser_port *info = tty->driver_data; - unsigned long flags; - if (info->xmit_cnt <= 0 || tty->stopped || !info->port.xmit_buf || - (tty->hw_stopped && info->type != PORT_16550A && - !info->board->chip_flag)) + if (!info->xmit_cnt || tty->flow.stopped || !info->port.xmit_buf || + (tty->hw_stopped && !mxser_16550A_or_MUST(info))) return; - spin_lock_irqsave(&info->slock, flags); - - outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); - info->IER |= UART_IER_THRI; - outb(info->IER, info->ioaddr + UART_IER); - - spin_unlock_irqrestore(&info->slock, flags); + mxser_start_tx(info); } -static int mxser_write_room(struct tty_struct *tty) +static unsigned int mxser_write_room(struct tty_struct *tty) { struct mxser_port *info = tty->driver_data; int ret; @@ -1192,7 +1014,7 @@ static int mxser_write_room(struct tty_struct *tty) return ret < 0 ? 0 : ret; } -static int mxser_chars_in_buffer(struct tty_struct *tty) +static unsigned int mxser_chars_in_buffer(struct tty_struct *tty) { struct mxser_port *info = tty->driver_data; return info->xmit_cnt; @@ -1210,9 +1032,6 @@ static int mxser_get_serial_info(struct tty_struct *tty, struct tty_port *port = &info->port; unsigned int closing_wait, close_delay; - if (tty->index == MXSER_PORTS) - return -ENOTTY; - mutex_lock(&port->mutex); close_delay = jiffies_to_msecs(info->port.close_delay) / 10; @@ -1225,10 +1044,10 @@ static int mxser_get_serial_info(struct tty_struct *tty, ss->port = info->ioaddr, ss->irq = info->board->irq, ss->flags = info->port.flags, - ss->baud_base = info->baud_base, + ss->baud_base = MXSER_BAUD_BASE, ss->close_delay = close_delay; ss->closing_wait = closing_wait; - ss->custom_divisor = info->custom_divisor, + ss->custom_divisor = MXSER_CUSTOM_DIVISOR, mutex_unlock(&port->mutex); return 0; } @@ -1240,19 +1059,13 @@ static int mxser_set_serial_info(struct tty_struct *tty, struct tty_port *port = &info->port; speed_t baud; unsigned long sl_flags; - unsigned int flags, close_delay, closing_wait; + unsigned int old_speed, close_delay, closing_wait; int retval = 0; - if (tty->index == MXSER_PORTS) - return -ENOTTY; if (tty_io_error(tty)) return -EIO; mutex_lock(&port->mutex); - if (!info->ioaddr) { - mutex_unlock(&port->mutex); - return -ENODEV; - } if (ss->irq != info->board->irq || ss->port != info->ioaddr) { @@ -1260,7 +1073,7 @@ static int mxser_set_serial_info(struct tty_struct *tty, return -EINVAL; } - flags = port->flags & ASYNC_SPD_MASK; + old_speed = port->flags & ASYNC_SPD_MASK; close_delay = msecs_to_jiffies(ss->close_delay * 10); closing_wait = ss->closing_wait; @@ -1268,15 +1081,15 @@ static int mxser_set_serial_info(struct tty_struct *tty, closing_wait = msecs_to_jiffies(closing_wait * 10); if (!capable(CAP_SYS_ADMIN)) { - if ((ss->baud_base != info->baud_base) || - (close_delay != info->port.close_delay) || - (closing_wait != info->port.closing_wait) || - ((ss->flags & ~ASYNC_USR_MASK) != (info->port.flags & ~ASYNC_USR_MASK))) { + if ((ss->baud_base != MXSER_BAUD_BASE) || + (close_delay != port->close_delay) || + (closing_wait != port->closing_wait) || + ((ss->flags & ~ASYNC_USR_MASK) != (port->flags & ~ASYNC_USR_MASK))) { mutex_unlock(&port->mutex); return -EPERM; } - info->port.flags = ((info->port.flags & ~ASYNC_USR_MASK) | - (ss->flags & ASYNC_USR_MASK)); + port->flags = (port->flags & ~ASYNC_USR_MASK) | + (ss->flags & ASYNC_USR_MASK); } else { /* * OK, past this point, all the error checking has been done. @@ -1287,9 +1100,9 @@ static int mxser_set_serial_info(struct tty_struct *tty, port->close_delay = close_delay; port->closing_wait = closing_wait; if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && - (ss->baud_base != info->baud_base || + (ss->baud_base != MXSER_BAUD_BASE || ss->custom_divisor != - info->custom_divisor)) { + MXSER_CUSTOM_DIVISOR)) { if (ss->custom_divisor == 0) { mutex_unlock(&port->mutex); return -EINVAL; @@ -1300,11 +1113,11 @@ static int mxser_set_serial_info(struct tty_struct *tty, info->type = ss->type; - process_txrx_fifo(info); + mxser_process_txrx_fifo(info); } if (tty_port_initialized(port)) { - if (flags != (port->flags & ASYNC_SPD_MASK)) { + if (old_speed != (port->flags & ASYNC_SPD_MASK)) { spin_lock_irqsave(&info->slock, sl_flags); mxser_change_speed(tty); spin_unlock_irqrestore(&info->slock, sl_flags); @@ -1348,19 +1161,16 @@ static int mxser_tiocmget(struct tty_struct *tty) unsigned char control, status; unsigned long flags; - - if (tty->index == MXSER_PORTS) - return -ENOIOCTLCMD; if (tty_io_error(tty)) return -EIO; - control = info->MCR; - spin_lock_irqsave(&info->slock, flags); + control = info->MCR; status = inb(info->ioaddr + UART_MSR); if (status & UART_MSR_ANY_DELTA) mxser_check_modem_status(tty, info, status); spin_unlock_irqrestore(&info->slock, flags); + return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | @@ -1375,9 +1185,6 @@ static int mxser_tiocmset(struct tty_struct *tty, struct mxser_port *info = tty->driver_data; unsigned long flags; - - if (tty->index == MXSER_PORTS) - return -ENOIOCTLCMD; if (tty_io_error(tty)) return -EIO; @@ -1398,267 +1205,6 @@ static int mxser_tiocmset(struct tty_struct *tty, return 0; } -static int __init mxser_program_mode(int port) -{ - int id, i, j, n; - - outb(0, port); - outb(0, port); - outb(0, port); - (void)inb(port); - (void)inb(port); - outb(0, port); - (void)inb(port); - - id = inb(port + 1) & 0x1F; - if ((id != C168_ASIC_ID) && - (id != C104_ASIC_ID) && - (id != C102_ASIC_ID) && - (id != CI132_ASIC_ID) && - (id != CI134_ASIC_ID) && - (id != CI104J_ASIC_ID)) - return -1; - for (i = 0, j = 0; i < 4; i++) { - n = inb(port + 2); - if (n == 'M') { - j = 1; - } else if ((j == 1) && (n == 1)) { - j = 2; - break; - } else - j = 0; - } - if (j != 2) - id = -2; - return id; -} - -static void __init mxser_normal_mode(int port) -{ - int i, n; - - outb(0xA5, port + 1); - outb(0x80, port + 3); - outb(12, port + 0); /* 9600 bps */ - outb(0, port + 1); - outb(0x03, port + 3); /* 8 data bits */ - outb(0x13, port + 4); /* loop back mode */ - for (i = 0; i < 16; i++) { - n = inb(port + 5); - if ((n & 0x61) == 0x60) - break; - if ((n & 1) == 1) - (void)inb(port); - } - outb(0x00, port + 4); -} - -#define CHIP_SK 0x01 /* Serial Data Clock in Eprom */ -#define CHIP_DO 0x02 /* Serial Data Output in Eprom */ -#define CHIP_CS 0x04 /* Serial Chip Select in Eprom */ -#define CHIP_DI 0x08 /* Serial Data Input in Eprom */ -#define EN_CCMD 0x000 /* Chip's command register */ -#define EN0_RSARLO 0x008 /* Remote start address reg 0 */ -#define EN0_RSARHI 0x009 /* Remote start address reg 1 */ -#define EN0_RCNTLO 0x00A /* Remote byte count reg WR */ -#define EN0_RCNTHI 0x00B /* Remote byte count reg WR */ -#define EN0_DCFG 0x00E /* Data configuration reg WR */ -#define EN0_PORT 0x010 /* Rcv missed frame error counter RD */ -#define ENC_PAGE0 0x000 /* Select page 0 of chip registers */ -#define ENC_PAGE3 0x0C0 /* Select page 3 of chip registers */ -static int __init mxser_read_register(int port, unsigned short *regs) -{ - int i, k, value, id; - unsigned int j; - - id = mxser_program_mode(port); - if (id < 0) - return id; - for (i = 0; i < 14; i++) { - k = (i & 0x3F) | 0x180; - for (j = 0x100; j > 0; j >>= 1) { - outb(CHIP_CS, port); - if (k & j) { - outb(CHIP_CS | CHIP_DO, port); - outb(CHIP_CS | CHIP_DO | CHIP_SK, port); /* A? bit of read */ - } else { - outb(CHIP_CS, port); - outb(CHIP_CS | CHIP_SK, port); /* A? bit of read */ - } - } - (void)inb(port); - value = 0; - for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) { - outb(CHIP_CS, port); - outb(CHIP_CS | CHIP_SK, port); - if (inb(port) & CHIP_DI) - value |= j; - } - regs[i] = value; - outb(0, port); - } - mxser_normal_mode(port); - return id; -} - -static int mxser_ioctl_special(unsigned int cmd, void __user *argp) -{ - struct mxser_port *ip; - struct tty_port *port; - struct tty_struct *tty; - int result, status; - unsigned int i, j; - int ret = 0; - - switch (cmd) { - case MOXA_GET_MAJOR: - printk_ratelimited(KERN_WARNING "mxser: '%s' uses deprecated ioctl " - "%x (GET_MAJOR), fix your userspace\n", - current->comm, cmd); - return put_user(ttymajor, (int __user *)argp); - - case MOXA_CHKPORTENABLE: - result = 0; - for (i = 0; i < MXSER_BOARDS; i++) - for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) - if (mxser_boards[i].ports[j].ioaddr) - result |= (1 << i); - return put_user(result, (unsigned long __user *)argp); - case MOXA_GETDATACOUNT: - /* The receive side is locked by port->slock but it isn't - clear that an exact snapshot is worth copying here */ - if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) - ret = -EFAULT; - return ret; - case MOXA_GETMSTATUS: { - struct mxser_mstatus ms, __user *msu = argp; - for (i = 0; i < MXSER_BOARDS; i++) - for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { - ip = &mxser_boards[i].ports[j]; - port = &ip->port; - memset(&ms, 0, sizeof(ms)); - - mutex_lock(&port->mutex); - if (!ip->ioaddr) - goto copy; - - tty = tty_port_tty_get(port); - - if (!tty) - ms.cflag = ip->normal_termios.c_cflag; - else - ms.cflag = tty->termios.c_cflag; - tty_kref_put(tty); - spin_lock_irq(&ip->slock); - status = inb(ip->ioaddr + UART_MSR); - spin_unlock_irq(&ip->slock); - if (status & UART_MSR_DCD) - ms.dcd = 1; - if (status & UART_MSR_DSR) - ms.dsr = 1; - if (status & UART_MSR_CTS) - ms.cts = 1; - copy: - mutex_unlock(&port->mutex); - if (copy_to_user(msu, &ms, sizeof(ms))) - return -EFAULT; - msu++; - } - return 0; - } - case MOXA_ASPP_MON_EXT: { - struct mxser_mon_ext *me; /* it's 2k, stack unfriendly */ - unsigned int cflag, iflag, p; - u8 opmode; - - me = kzalloc(sizeof(*me), GFP_KERNEL); - if (!me) - return -ENOMEM; - - for (i = 0, p = 0; i < MXSER_BOARDS; i++) { - for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) { - if (p >= ARRAY_SIZE(me->rx_cnt)) { - i = MXSER_BOARDS; - break; - } - ip = &mxser_boards[i].ports[j]; - port = &ip->port; - - mutex_lock(&port->mutex); - if (!ip->ioaddr) { - mutex_unlock(&port->mutex); - continue; - } - - spin_lock_irq(&ip->slock); - status = mxser_get_msr(ip->ioaddr, 0, p); - - if (status & UART_MSR_TERI) - ip->icount.rng++; - if (status & UART_MSR_DDSR) - ip->icount.dsr++; - if (status & UART_MSR_DDCD) - ip->icount.dcd++; - if (status & UART_MSR_DCTS) - ip->icount.cts++; - - ip->mon_data.modem_status = status; - me->rx_cnt[p] = ip->mon_data.rxcnt; - me->tx_cnt[p] = ip->mon_data.txcnt; - me->up_rxcnt[p] = ip->mon_data.up_rxcnt; - me->up_txcnt[p] = ip->mon_data.up_txcnt; - me->modem_status[p] = - ip->mon_data.modem_status; - spin_unlock_irq(&ip->slock); - - tty = tty_port_tty_get(&ip->port); - - if (!tty) { - cflag = ip->normal_termios.c_cflag; - iflag = ip->normal_termios.c_iflag; - me->baudrate[p] = tty_termios_baud_rate(&ip->normal_termios); - } else { - cflag = tty->termios.c_cflag; - iflag = tty->termios.c_iflag; - me->baudrate[p] = tty_get_baud_rate(tty); - } - tty_kref_put(tty); - - me->databits[p] = cflag & CSIZE; - me->stopbits[p] = cflag & CSTOPB; - me->parity[p] = cflag & (PARENB | PARODD | - CMSPAR); - - if (cflag & CRTSCTS) - me->flowctrl[p] |= 0x03; - - if (iflag & (IXON | IXOFF)) - me->flowctrl[p] |= 0x0C; - - if (ip->type == PORT_16550A) - me->fifo[p] = 1; - - if (ip->board->chip_flag == MOXA_MUST_MU860_HWID) { - opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2); - opmode &= OP_MODE_MASK; - } else { - opmode = RS232_MODE; - } - me->iftype[p] = opmode; - mutex_unlock(&port->mutex); - } - } - if (copy_to_user(argp, me, sizeof(*me))) - ret = -EFAULT; - kfree(me); - return ret; - } - default: - return -ENOIOCTLCMD; - } - return 0; -} - static int mxser_cflags_changed(struct mxser_port *info, unsigned long arg, struct async_icount *cprev) { @@ -1680,6 +1226,41 @@ static int mxser_cflags_changed(struct mxser_port *info, unsigned long arg, return ret; } +/* We should likely switch to TIOCGRS485/TIOCSRS485. */ +static int mxser_ioctl_op_mode(struct mxser_port *port, int index, bool set, + int __user *u_opmode) +{ + int opmode, p = index % 4; + int shiftbit = p * 2; + u8 val; + + if (port->board->must_hwid != MOXA_MUST_MU860_HWID) + return -EFAULT; + + if (set) { + if (get_user(opmode, u_opmode)) + return -EFAULT; + + if (opmode & ~OP_MODE_MASK) + return -EINVAL; + + spin_lock_irq(&port->slock); + val = inb(port->opmode_ioaddr); + val &= ~(OP_MODE_MASK << shiftbit); + val |= (opmode << shiftbit); + outb(val, port->opmode_ioaddr); + spin_unlock_irq(&port->slock); + + return 0; + } + + spin_lock_irq(&port->slock); + opmode = inb(port->opmode_ioaddr) >> shiftbit; + spin_unlock_irq(&port->slock); + + return put_user(opmode & OP_MODE_MASK, u_opmode); +} + static int mxser_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { @@ -1688,47 +1269,9 @@ static int mxser_ioctl(struct tty_struct *tty, unsigned long flags; void __user *argp = (void __user *)arg; - if (tty->index == MXSER_PORTS) - return mxser_ioctl_special(cmd, argp); - - if (cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE) { - int p; - unsigned long opmode; - static unsigned char ModeMask[] = { 0xfc, 0xf3, 0xcf, 0x3f }; - int shiftbit; - unsigned char val, mask; - - if (info->board->chip_flag != MOXA_MUST_MU860_HWID) - return -EFAULT; - - p = tty->index % 4; - if (cmd == MOXA_SET_OP_MODE) { - if (get_user(opmode, (int __user *) argp)) - return -EFAULT; - if (opmode != RS232_MODE && - opmode != RS485_2WIRE_MODE && - opmode != RS422_MODE && - opmode != RS485_4WIRE_MODE) - return -EFAULT; - mask = ModeMask[p]; - shiftbit = p * 2; - spin_lock_irq(&info->slock); - val = inb(info->opmode_ioaddr); - val &= mask; - val |= (opmode << shiftbit); - outb(val, info->opmode_ioaddr); - spin_unlock_irq(&info->slock); - } else { - shiftbit = p * 2; - spin_lock_irq(&info->slock); - opmode = inb(info->opmode_ioaddr) >> shiftbit; - spin_unlock_irq(&info->slock); - opmode &= OP_MODE_MASK; - if (put_user(opmode, (int __user *)argp)) - return -EFAULT; - } - return 0; - } + if (cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE) + return mxser_ioctl_op_mode(info, tty->index, + cmd == MOXA_SET_OP_MODE, argp); if (cmd != TIOCMIWAIT && tty_io_error(tty)) return -EIO; @@ -1749,72 +1292,6 @@ static int mxser_ioctl(struct tty_struct *tty, return wait_event_interruptible(info->port.delta_msr_wait, mxser_cflags_changed(info, arg, &cnow)); - case MOXA_HighSpeedOn: - return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); - case MOXA_SDS_RSTICOUNTER: - spin_lock_irq(&info->slock); - info->mon_data.rxcnt = 0; - info->mon_data.txcnt = 0; - spin_unlock_irq(&info->slock); - return 0; - - case MOXA_ASPP_OQUEUE:{ - int len, lsr; - - len = mxser_chars_in_buffer(tty); - spin_lock_irq(&info->slock); - lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE; - spin_unlock_irq(&info->slock); - len += (lsr ? 0 : 1); - - return put_user(len, (int __user *)argp); - } - case MOXA_ASPP_MON: { - int mcr, status; - - spin_lock_irq(&info->slock); - status = mxser_get_msr(info->ioaddr, 1, tty->index); - mxser_check_modem_status(tty, info, status); - - mcr = inb(info->ioaddr + UART_MCR); - spin_unlock_irq(&info->slock); - - if (mcr & MOXA_MUST_MCR_XON_FLAG) - info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; - else - info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFHOLD; - - if (mcr & MOXA_MUST_MCR_TX_XON) - info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFXENT; - else - info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT; - - if (tty->hw_stopped) - info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; - else - info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; - - if (copy_to_user(argp, &info->mon_data, - sizeof(struct mxser_mon))) - return -EFAULT; - - return 0; - } - case MOXA_ASPP_LSTATUS: { - if (put_user(info->err_shadow, (unsigned char __user *)argp)) - return -EFAULT; - - info->err_shadow = 0; - return 0; - } - case MOXA_SET_BAUD_METHOD: { - int method; - - if (get_user(method, (int __user *)argp)) - return -EFAULT; - mxser_set_baud_method[tty->index] = method; - return put_user(method, (int __user *)argp); - } default: return -ENOIOCTLCMD; } @@ -1860,7 +1337,7 @@ static void mxser_stoprx(struct tty_struct *tty) info->ldisc_stop_rx = 1; if (I_IXOFF(tty)) { - if (info->board->chip_flag) { + if (info->board->must_hwid) { info->IER &= ~MOXA_MUST_RECV_ISR; outb(info->IER, info->ioaddr + UART_IER); } else { @@ -1896,7 +1373,7 @@ static void mxser_unthrottle(struct tty_struct *tty) if (info->x_char) info->x_char = 0; else { - if (info->board->chip_flag) { + if (info->board->must_hwid) { info->IER |= MOXA_MUST_RECV_ISR; outb(info->IER, info->ioaddr + UART_IER); } else { @@ -1917,7 +1394,7 @@ static void mxser_unthrottle(struct tty_struct *tty) /* * mxser_stop() and mxser_start() * - * This routines are called before setting or resetting tty->stopped. + * This routines are called before setting or resetting tty->flow.stopped. * They enable or disable transmitter interrupts, as necessary. */ static void mxser_stop(struct tty_struct *tty) @@ -1926,10 +1403,8 @@ static void mxser_stop(struct tty_struct *tty) unsigned long flags; spin_lock_irqsave(&info->slock, flags); - if (info->IER & UART_IER_THRI) { - info->IER &= ~UART_IER_THRI; - outb(info->IER, info->ioaddr + UART_IER); - } + if (info->IER & UART_IER_THRI) + __mxser_stop_tx(info); spin_unlock_irqrestore(&info->slock, flags); } @@ -1939,11 +1414,8 @@ static void mxser_start(struct tty_struct *tty) unsigned long flags; spin_lock_irqsave(&info->slock, flags); - if (info->xmit_cnt && info->port.xmit_buf) { - outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); - info->IER |= UART_IER_THRI; - outb(info->IER, info->ioaddr + UART_IER); - } + if (info->xmit_cnt && info->port.xmit_buf) + __mxser_start_tx(info); spin_unlock_irqrestore(&info->slock, flags); } @@ -1963,12 +1435,11 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi /* Handle sw stopped */ if ((old_termios->c_iflag & IXON) && !I_IXON(tty)) { - tty->stopped = 0; + tty->flow.stopped = 0; - if (info->board->chip_flag) { + if (info->board->must_hwid) { spin_lock_irqsave(&info->slock, flags); - mxser_disable_must_rx_software_flow_control( - info->ioaddr); + mxser_must_set_rx_sw_flow_control(info->ioaddr, false); spin_unlock_irqrestore(&info->slock, flags); } @@ -2051,88 +1522,92 @@ static int mxser_rs_break(struct tty_struct *tty, int break_state) { struct mxser_port *info = tty->driver_data; unsigned long flags; + u8 lcr; spin_lock_irqsave(&info->slock, flags); + lcr = inb(info->ioaddr + UART_LCR); if (break_state == -1) - outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC, - info->ioaddr + UART_LCR); + lcr |= UART_LCR_SBC; else - outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC, - info->ioaddr + UART_LCR); + lcr &= ~UART_LCR_SBC; + outb(lcr, info->ioaddr + UART_LCR); spin_unlock_irqrestore(&info->slock, flags); + return 0; } -static void mxser_receive_chars(struct tty_struct *tty, - struct mxser_port *port, int *status) +static bool mxser_receive_chars_new(struct tty_struct *tty, + struct mxser_port *port, u8 status) { - unsigned char ch, gdl; - int ignored = 0; - int cnt = 0; - int recv_room; - int max = 256; + enum mxser_must_hwid hwid = port->board->must_hwid; + u8 gdl; + + if (hwid == MOXA_OTHER_UART) + return false; + if (status & UART_LSR_BRK_ERROR_BITS) + return false; + if (hwid == MOXA_MUST_MU860_HWID && (status & MOXA_MUST_LSR_RERR)) + return false; + if (status & MOXA_MUST_LSR_RERR) + return false; - recv_room = tty->receive_room; - if (recv_room == 0 && !port->ldisc_stop_rx) + gdl = inb(port->ioaddr + MOXA_MUST_GDL_REGISTER); + if (hwid == MOXA_MUST_MU150_HWID) + gdl &= MOXA_MUST_GDL_MASK; + + if (gdl >= tty->receive_room && !port->ldisc_stop_rx) mxser_stoprx(tty); - if (port->board->chip_flag != MOXA_OTHER_UART) { - - if (*status & UART_LSR_SPECIAL) - goto intr_old; - if (port->board->chip_flag == MOXA_MUST_MU860_HWID && - (*status & MOXA_MUST_LSR_RERR)) - goto intr_old; - if (*status & MOXA_MUST_LSR_RERR) - goto intr_old; - - gdl = inb(port->ioaddr + MOXA_MUST_GDL_REGISTER); - - if (port->board->chip_flag == MOXA_MUST_MU150_HWID) - gdl &= MOXA_MUST_GDL_MASK; - if (gdl >= recv_room) { - if (!port->ldisc_stop_rx) - mxser_stoprx(tty); - } - while (gdl--) { - ch = inb(port->ioaddr + UART_RX); - tty_insert_flip_char(&port->port, ch, 0); - cnt++; - } - goto end_intr; + + while (gdl--) { + u8 ch = inb(port->ioaddr + UART_RX); + tty_insert_flip_char(&port->port, ch, 0); } -intr_old: + + return true; +} + +static u8 mxser_receive_chars_old(struct tty_struct *tty, + struct mxser_port *port, u8 status) +{ + enum mxser_must_hwid hwid = port->board->must_hwid; + int recv_room = tty->receive_room; + int ignored = 0; + int max = 256; + int cnt = 0; + u8 ch; do { if (max-- < 0) break; ch = inb(port->ioaddr + UART_RX); - if (port->board->chip_flag && (*status & UART_LSR_OE)) - outb(0x23, port->ioaddr + UART_FCR); - *status &= port->read_status_mask; - if (*status & port->ignore_status_mask) { + if (hwid && (status & UART_LSR_OE)) + outb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | + MOXA_MUST_FCR_GDA_MODE_ENABLE, + port->ioaddr + UART_FCR); + status &= port->read_status_mask; + if (status & port->ignore_status_mask) { if (++ignored > 100) break; } else { char flag = 0; - if (*status & UART_LSR_SPECIAL) { - if (*status & UART_LSR_BI) { + if (status & UART_LSR_BRK_ERROR_BITS) { + if (status & UART_LSR_BI) { flag = TTY_BREAK; port->icount.brk++; if (port->port.flags & ASYNC_SAK) do_SAK(tty); - } else if (*status & UART_LSR_PE) { + } else if (status & UART_LSR_PE) { flag = TTY_PARITY; port->icount.parity++; - } else if (*status & UART_LSR_FE) { + } else if (status & UART_LSR_FE) { flag = TTY_FRAME; port->icount.frame++; - } else if (*status & UART_LSR_OE) { + } else if (status & UART_LSR_OE) { flag = TTY_OVERRUN; port->icount.overrun++; - } else - flag = TTY_BREAK; + } } tty_insert_flip_char(&port->port, ch, flag); cnt++; @@ -2144,18 +1619,27 @@ intr_old: } - if (port->board->chip_flag) + if (hwid) break; - *status = inb(port->ioaddr + UART_LSR); - } while (*status & UART_LSR_DR); + status = inb(port->ioaddr + UART_LSR); + } while (status & UART_LSR_DR); + + return status; +} + +static u8 mxser_receive_chars(struct tty_struct *tty, + struct mxser_port *port, u8 status) +{ + if (tty->receive_room == 0 && !port->ldisc_stop_rx) + mxser_stoprx(tty); -end_intr: - mxvar_log.rxcnt[tty->index] += cnt; - port->mon_data.rxcnt += cnt; - port->mon_data.up_rxcnt += cnt; + if (!mxser_receive_chars_new(tty, port, status)) + status = mxser_receive_chars_old(tty, port, status); tty_flip_buffer_push(&port->port); + + return status; } static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port) @@ -2165,9 +1649,6 @@ static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port if (port->x_char) { outb(port->x_char, port->ioaddr + UART_TX); port->x_char = 0; - mxvar_log.txcnt[tty->index]++; - port->mon_data.txcnt++; - port->mon_data.up_txcnt++; port->icount.tx++; return; } @@ -2175,12 +1656,9 @@ static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port if (port->port.xmit_buf == NULL) return; - if (port->xmit_cnt <= 0 || tty->stopped || - (tty->hw_stopped && - (port->type != PORT_16550A) && - (!port->board->chip_flag))) { - port->IER &= ~UART_IER_THRI; - outb(port->IER, port->ioaddr + UART_IER); + if (!port->xmit_cnt || tty->flow.stopped || + (tty->hw_stopped && !mxser_16550A_or_MUST(port))) { + __mxser_stop_tx(port); return; } @@ -2190,22 +1668,72 @@ static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port outb(port->port.xmit_buf[port->xmit_tail++], port->ioaddr + UART_TX); port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1); - if (--port->xmit_cnt <= 0) + if (!--port->xmit_cnt) break; } while (--count > 0); - mxvar_log.txcnt[tty->index] += (cnt - port->xmit_cnt); - port->mon_data.txcnt += (cnt - port->xmit_cnt); - port->mon_data.up_txcnt += (cnt - port->xmit_cnt); port->icount.tx += (cnt - port->xmit_cnt); if (port->xmit_cnt < WAKEUP_CHARS) tty_wakeup(tty); - if (port->xmit_cnt <= 0) { - port->IER &= ~UART_IER_THRI; - outb(port->IER, port->ioaddr + UART_IER); + if (!port->xmit_cnt) + __mxser_stop_tx(port); +} + +static bool mxser_port_isr(struct mxser_port *port) +{ + struct tty_struct *tty; + u8 iir, msr, status; + bool error = false; + + iir = inb(port->ioaddr + UART_IIR); + if (iir & UART_IIR_NO_INT) + return true; + + iir &= MOXA_MUST_IIR_MASK; + tty = tty_port_tty_get(&port->port); + if (!tty || port->closing || !tty_port_initialized(&port->port)) { + status = inb(port->ioaddr + UART_LSR); + outb(MOXA_MUST_FCR_GDA_MODE_ENABLE | UART_FCR_ENABLE_FIFO | + UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, + port->ioaddr + UART_FCR); + inb(port->ioaddr + UART_MSR); + + error = true; + goto put_tty; + } + + status = inb(port->ioaddr + UART_LSR); + + if (port->board->must_hwid) { + if (iir == MOXA_MUST_IIR_GDA || + iir == MOXA_MUST_IIR_RDA || + iir == MOXA_MUST_IIR_RTO || + iir == MOXA_MUST_IIR_LSR) + status = mxser_receive_chars(tty, port, status); + } else { + status &= port->read_status_mask; + if (status & UART_LSR_DR) + status = mxser_receive_chars(tty, port, status); + } + + msr = inb(port->ioaddr + UART_MSR); + if (msr & UART_MSR_ANY_DELTA) + mxser_check_modem_status(tty, port, msr); + + if (port->board->must_hwid) { + if (iir == 0x02 && (status & UART_LSR_THRE)) + mxser_transmit_chars(tty, port); + } else { + if (status & UART_LSR_THRE) + mxser_transmit_chars(tty, port); } + +put_tty: + tty_kref_put(tty); + + return error; } /* @@ -2213,33 +1741,21 @@ static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port */ static irqreturn_t mxser_interrupt(int irq, void *dev_id) { - int status, iir, i; - struct mxser_board *brd = NULL; + struct mxser_board *brd = dev_id; struct mxser_port *port; - int max, irqbits, bits, msr; unsigned int int_cnt, pass_counter = 0; + unsigned int i, max = brd->nports; int handled = IRQ_NONE; - struct tty_struct *tty; - - for (i = 0; i < MXSER_BOARDS; i++) - if (dev_id == &mxser_boards[i]) { - brd = dev_id; - break; - } + u8 irqbits, bits, mask = BIT(max) - 1; - if (i == MXSER_BOARDS) - goto irq_stop; - if (brd == NULL) - goto irq_stop; - max = brd->info->nports; while (pass_counter++ < MXSER_ISR_PASS_LIMIT) { - irqbits = inb(brd->vector) & brd->vector_mask; - if (irqbits == brd->vector_mask) + irqbits = inb(brd->vector) & mask; + if (irqbits == mask) break; handled = IRQ_HANDLED; for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) { - if (irqbits == brd->vector_mask) + if (irqbits == mask) break; if (bits & irqbits) continue; @@ -2248,65 +1764,13 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id) int_cnt = 0; spin_lock(&port->slock); do { - iir = inb(port->ioaddr + UART_IIR); - if (iir & UART_IIR_NO_INT) + if (mxser_port_isr(port)) break; - iir &= MOXA_MUST_IIR_MASK; - tty = tty_port_tty_get(&port->port); - if (!tty || port->closing || - !tty_port_initialized(&port->port)) { - status = inb(port->ioaddr + UART_LSR); - outb(0x27, port->ioaddr + UART_FCR); - inb(port->ioaddr + UART_MSR); - tty_kref_put(tty); - break; - } - - status = inb(port->ioaddr + UART_LSR); - - if (status & UART_LSR_PE) - port->err_shadow |= NPPI_NOTIFY_PARITY; - if (status & UART_LSR_FE) - port->err_shadow |= NPPI_NOTIFY_FRAMING; - if (status & UART_LSR_OE) - port->err_shadow |= - NPPI_NOTIFY_HW_OVERRUN; - if (status & UART_LSR_BI) - port->err_shadow |= NPPI_NOTIFY_BREAK; - - if (port->board->chip_flag) { - if (iir == MOXA_MUST_IIR_GDA || - iir == MOXA_MUST_IIR_RDA || - iir == MOXA_MUST_IIR_RTO || - iir == MOXA_MUST_IIR_LSR) - mxser_receive_chars(tty, port, - &status); - - } else { - status &= port->read_status_mask; - if (status & UART_LSR_DR) - mxser_receive_chars(tty, port, - &status); - } - msr = inb(port->ioaddr + UART_MSR); - if (msr & UART_MSR_ANY_DELTA) - mxser_check_modem_status(tty, port, msr); - - if (port->board->chip_flag) { - if (iir == 0x02 && (status & - UART_LSR_THRE)) - mxser_transmit_chars(tty, port); - } else { - if (status & UART_LSR_THRE) - mxser_transmit_chars(tty, port); - } - tty_kref_put(tty); } while (int_cnt++ < MXSER_ISR_PASS_LIMIT); spin_unlock(&port->slock); } } -irq_stop: return handled; } @@ -2346,254 +1810,103 @@ static const struct tty_port_operations mxser_port_ops = { * The MOXA Smartio/Industio serial driver boot-time initialization code! */ -static bool allow_overlapping_vector; -module_param(allow_overlapping_vector, bool, S_IRUGO); -MODULE_PARM_DESC(allow_overlapping_vector, "whether we allow ISA cards to be configured such that vector overlabs IO ports (default=no)"); - -static bool mxser_overlapping_vector(struct mxser_board *brd) -{ - return allow_overlapping_vector && - brd->vector >= brd->ports[0].ioaddr && - brd->vector < brd->ports[0].ioaddr + 8 * brd->info->nports; -} - -static int mxser_request_vector(struct mxser_board *brd) +static void mxser_initbrd(struct mxser_board *brd, bool high_baud) { - if (mxser_overlapping_vector(brd)) - return 0; - return request_region(brd->vector, 1, "mxser(vector)") ? 0 : -EIO; -} + struct mxser_port *info; + unsigned int i; + bool is_mu860; -static void mxser_release_vector(struct mxser_board *brd) -{ - if (mxser_overlapping_vector(brd)) - return; - release_region(brd->vector, 1); -} + brd->must_hwid = mxser_must_get_hwid(brd->ports[0].ioaddr); + is_mu860 = brd->must_hwid == MOXA_MUST_MU860_HWID; -static void mxser_release_ISA_res(struct mxser_board *brd) -{ - release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); - mxser_release_vector(brd); -} + for (i = 0; i < UART_INFO_NUM; i++) { + if (Gpci_uart_info[i].type == brd->must_hwid) { + brd->max_baud = Gpci_uart_info[i].max_baud; -static int mxser_initbrd(struct mxser_board *brd) -{ - struct mxser_port *info; - unsigned int i; - int retval; + /* exception....CP-102 */ + if (high_baud) + brd->max_baud = 921600; + break; + } + } - printk(KERN_INFO "mxser: max. baud rate = %d bps\n", - brd->ports[0].max_baud); + if (is_mu860) { + /* set to RS232 mode by default */ + outb(0, brd->vector + 4); + outb(0, brd->vector + 0x0c); + } - for (i = 0; i < brd->info->nports; i++) { + for (i = 0; i < brd->nports; i++) { info = &brd->ports[i]; + if (is_mu860) { + if (i < 4) + info->opmode_ioaddr = brd->vector + 4; + else + info->opmode_ioaddr = brd->vector + 0x0c; + } tty_port_init(&info->port); info->port.ops = &mxser_port_ops; info->board = brd; - info->stop_rx = 0; info->ldisc_stop_rx = 0; /* Enhance mode enabled here */ - if (brd->chip_flag != MOXA_OTHER_UART) - mxser_enable_must_enchance_mode(info->ioaddr); + if (brd->must_hwid != MOXA_OTHER_UART) + mxser_must_set_enhance_mode(info->ioaddr, true); - info->type = brd->uart_type; + info->type = PORT_16550A; - process_txrx_fifo(info); + mxser_process_txrx_fifo(info); - info->custom_divisor = info->baud_base * 16; info->port.close_delay = 5 * HZ / 10; info->port.closing_wait = 30 * HZ; - info->normal_termios = mxvar_sdriver->init_termios; - memset(&info->mon_data, 0, sizeof(struct mxser_mon)); - info->err_shadow = 0; spin_lock_init(&info->slock); /* before set INT ISR, disable all int */ outb(inb(info->ioaddr + UART_IER) & 0xf0, info->ioaddr + UART_IER); } - - retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser", - brd); - if (retval) { - for (i = 0; i < brd->info->nports; i++) - tty_port_destroy(&brd->ports[i].port); - printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may " - "conflict with another device.\n", - brd->info->name, brd->irq); - } - - return retval; -} - -static void mxser_board_remove(struct mxser_board *brd) -{ - unsigned int i; - - for (i = 0; i < brd->info->nports; i++) { - tty_unregister_device(mxvar_sdriver, brd->idx + i); - tty_port_destroy(&brd->ports[i].port); - } - free_irq(brd->irq, brd); -} - -static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) -{ - int id, i, bits, ret; - unsigned short regs[16], irq; - unsigned char scratch, scratch2; - - brd->chip_flag = MOXA_OTHER_UART; - - id = mxser_read_register(cap, regs); - switch (id) { - case C168_ASIC_ID: - brd->info = &mxser_cards[0]; - break; - case C104_ASIC_ID: - brd->info = &mxser_cards[1]; - break; - case CI104J_ASIC_ID: - brd->info = &mxser_cards[2]; - break; - case C102_ASIC_ID: - brd->info = &mxser_cards[5]; - break; - case CI132_ASIC_ID: - brd->info = &mxser_cards[6]; - break; - case CI134_ASIC_ID: - brd->info = &mxser_cards[7]; - break; - default: - return 0; - } - - irq = 0; - /* some ISA cards have 2 ports, but we want to see them as 4-port (why?) - Flag-hack checks if configuration should be read as 2-port here. */ - if (brd->info->nports == 2 || (brd->info->flags & MXSER_HAS2)) { - irq = regs[9] & 0xF000; - irq = irq | (irq >> 4); - if (irq != (regs[9] & 0xFF00)) - goto err_irqconflict; - } else if (brd->info->nports == 4) { - irq = regs[9] & 0xF000; - irq = irq | (irq >> 4); - irq = irq | (irq >> 8); - if (irq != regs[9]) - goto err_irqconflict; - } else if (brd->info->nports == 8) { - irq = regs[9] & 0xF000; - irq = irq | (irq >> 4); - irq = irq | (irq >> 8); - if ((irq != regs[9]) || (irq != regs[10])) - goto err_irqconflict; - } - - if (!irq) { - printk(KERN_ERR "mxser: interrupt number unset\n"); - return -EIO; - } - brd->irq = ((int)(irq & 0xF000) >> 12); - for (i = 0; i < 8; i++) - brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8; - if ((regs[12] & 0x80) == 0) { - printk(KERN_ERR "mxser: invalid interrupt vector\n"); - return -EIO; - } - brd->vector = (int)regs[11]; /* interrupt vector */ - if (id == 1) - brd->vector_mask = 0x00FF; - else - brd->vector_mask = 0x000F; - for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) { - if (regs[12] & bits) { - brd->ports[i].baud_base = 921600; - brd->ports[i].max_baud = 921600; - } else { - brd->ports[i].baud_base = 115200; - brd->ports[i].max_baud = 115200; - } - } - scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB); - outb(scratch2 | UART_LCR_DLAB, cap + UART_LCR); - outb(0, cap + UART_EFR); /* EFR is the same as FCR */ - outb(scratch2, cap + UART_LCR); - outb(UART_FCR_ENABLE_FIFO, cap + UART_FCR); - scratch = inb(cap + UART_IIR); - - if (scratch & 0xC0) - brd->uart_type = PORT_16550A; - else - brd->uart_type = PORT_16450; - if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports, - "mxser(IO)")) { - printk(KERN_ERR "mxser: can't request ports I/O region: " - "0x%.8lx-0x%.8lx\n", - brd->ports[0].ioaddr, brd->ports[0].ioaddr + - 8 * brd->info->nports - 1); - return -EIO; - } - - ret = mxser_request_vector(brd); - if (ret) { - release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); - printk(KERN_ERR "mxser: can't request interrupt vector region: " - "0x%.8lx-0x%.8lx\n", - brd->ports[0].ioaddr, brd->ports[0].ioaddr + - 8 * brd->info->nports - 1); - return ret; - } - return brd->info->nports; - -err_irqconflict: - printk(KERN_ERR "mxser: invalid interrupt number\n"); - return -EIO; } static int mxser_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { -#ifdef CONFIG_PCI struct mxser_board *brd; - unsigned int i, j; + unsigned int i, base; unsigned long ioaddress; + unsigned short nports = MXSER_NPORTS(ent->driver_data); struct device *tty_dev; int retval = -EINVAL; - for (i = 0; i < MXSER_BOARDS; i++) - if (mxser_boards[i].info == NULL) - break; - + i = find_first_zero_bit(mxser_boards, MXSER_BOARDS); if (i >= MXSER_BOARDS) { dev_err(&pdev->dev, "too many boards found (maximum %d), board " "not configured\n", MXSER_BOARDS); goto err; } - brd = &mxser_boards[i]; - brd->idx = i * MXSER_PORTS_PER_BOARD; - dev_info(&pdev->dev, "found MOXA %s board (BusNo=%d, DevNo=%d)\n", - mxser_cards[ent->driver_data].name, - pdev->bus->number, PCI_SLOT(pdev->devfn)); + brd = devm_kzalloc(&pdev->dev, struct_size(brd, ports, nports), + GFP_KERNEL); + if (!brd) + goto err; + + brd->idx = i; + __set_bit(brd->idx, mxser_boards); + base = i * MXSER_PORTS_PER_BOARD; - retval = pci_enable_device(pdev); + retval = pcim_enable_device(pdev); if (retval) { dev_err(&pdev->dev, "PCI enable failed\n"); - goto err; + goto err_zero; } /* io address */ ioaddress = pci_resource_start(pdev, 2); retval = pci_request_region(pdev, 2, "mxser(IO)"); if (retval) - goto err_dis; + goto err_zero; - brd->info = &mxser_cards[ent->driver_data]; - for (i = 0; i < brd->info->nports; i++) + brd->nports = nports; + for (i = 0; i < nports; i++) brd->ports[i].ioaddr = ioaddress + 8 * i; /* vector */ @@ -2606,53 +1919,23 @@ static int mxser_probe(struct pci_dev *pdev, /* irq */ brd->irq = pdev->irq; - brd->chip_flag = CheckIsMoxaMust(brd->ports[0].ioaddr); - brd->uart_type = PORT_16550A; - brd->vector_mask = 0; - - for (i = 0; i < brd->info->nports; i++) { - for (j = 0; j < UART_INFO_NUM; j++) { - if (Gpci_uart_info[j].type == brd->chip_flag) { - brd->ports[i].max_baud = - Gpci_uart_info[j].max_baud; - - /* exception....CP-102 */ - if (brd->info->flags & MXSER_HIGHBAUD) - brd->ports[i].max_baud = 921600; - break; - } - } - } - - if (brd->chip_flag == MOXA_MUST_MU860_HWID) { - for (i = 0; i < brd->info->nports; i++) { - if (i < 4) - brd->ports[i].opmode_ioaddr = ioaddress + 4; - else - brd->ports[i].opmode_ioaddr = ioaddress + 0x0c; - } - outb(0, ioaddress + 4); /* default set to RS232 mode */ - outb(0, ioaddress + 0x0c); /* default set to RS232 mode */ - } + mxser_initbrd(brd, ent->driver_data & MXSER_HIGHBAUD); - for (i = 0; i < brd->info->nports; i++) { - brd->vector_mask |= (1 << i); - brd->ports[i].baud_base = 921600; + retval = devm_request_irq(&pdev->dev, brd->irq, mxser_interrupt, + IRQF_SHARED, "mxser", brd); + if (retval) { + dev_err(&pdev->dev, "request irq failed"); + goto err_relbrd; } - /* mxser_initbrd will hook ISR. */ - retval = mxser_initbrd(brd); - if (retval) - goto err_rel3; - - for (i = 0; i < brd->info->nports; i++) { + for (i = 0; i < nports; i++) { tty_dev = tty_port_register_device(&brd->ports[i].port, - mxvar_sdriver, brd->idx + i, &pdev->dev); + mxvar_sdriver, base + i, &pdev->dev); if (IS_ERR(tty_dev)) { retval = PTR_ERR(tty_dev); for (; i > 0; i--) tty_unregister_device(mxvar_sdriver, - brd->idx + i - 1); + base + i - 1); goto err_relbrd; } } @@ -2661,35 +1944,25 @@ static int mxser_probe(struct pci_dev *pdev, return 0; err_relbrd: - for (i = 0; i < brd->info->nports; i++) + for (i = 0; i < nports; i++) tty_port_destroy(&brd->ports[i].port); - free_irq(brd->irq, brd); -err_rel3: - pci_release_region(pdev, 3); err_zero: - brd->info = NULL; - pci_release_region(pdev, 2); -err_dis: - pci_disable_device(pdev); + __clear_bit(brd->idx, mxser_boards); err: return retval; -#else - return -ENODEV; -#endif } static void mxser_remove(struct pci_dev *pdev) { -#ifdef CONFIG_PCI struct mxser_board *brd = pci_get_drvdata(pdev); + unsigned int i, base = brd->idx * MXSER_PORTS_PER_BOARD; - mxser_board_remove(brd); + for (i = 0; i < brd->nports; i++) { + tty_unregister_device(mxvar_sdriver, base + i); + tty_port_destroy(&brd->ports[i].port); + } - pci_release_region(pdev, 2); - pci_release_region(pdev, 3); - pci_disable_device(pdev); - brd->info = NULL; -#endif + __clear_bit(brd->idx, mxser_boards); } static struct pci_driver mxser_driver = { @@ -2701,18 +1974,12 @@ static struct pci_driver mxser_driver = { static int __init mxser_module_init(void) { - struct mxser_board *brd; - struct device *tty_dev; - unsigned int b, i, m; int retval; - mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); + mxvar_sdriver = alloc_tty_driver(MXSER_PORTS); if (!mxvar_sdriver) return -ENOMEM; - printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n", - MXSER_VERSION); - /* Initialize the tty_driver structure */ mxvar_sdriver->name = "ttyMI"; mxvar_sdriver->major = ttymajor; @@ -2731,57 +1998,10 @@ static int __init mxser_module_init(void) goto err_put; } - /* Start finding ISA boards here */ - for (m = 0, b = 0; b < MXSER_BOARDS; b++) { - if (!ioaddr[b]) - continue; - - brd = &mxser_boards[m]; - retval = mxser_get_ISA_conf(ioaddr[b], brd); - if (retval <= 0) { - brd->info = NULL; - continue; - } - - printk(KERN_INFO "mxser: found MOXA %s board (CAP=0x%lx)\n", - brd->info->name, ioaddr[b]); - - /* mxser_initbrd will hook ISR. */ - if (mxser_initbrd(brd) < 0) { - mxser_release_ISA_res(brd); - brd->info = NULL; - continue; - } - - brd->idx = m * MXSER_PORTS_PER_BOARD; - for (i = 0; i < brd->info->nports; i++) { - tty_dev = tty_port_register_device(&brd->ports[i].port, - mxvar_sdriver, brd->idx + i, NULL); - if (IS_ERR(tty_dev)) { - for (; i > 0; i--) - tty_unregister_device(mxvar_sdriver, - brd->idx + i - 1); - for (i = 0; i < brd->info->nports; i++) - tty_port_destroy(&brd->ports[i].port); - free_irq(brd->irq, brd); - mxser_release_ISA_res(brd); - brd->info = NULL; - break; - } - } - if (brd->info == NULL) - continue; - - m++; - } - retval = pci_register_driver(&mxser_driver); if (retval) { printk(KERN_ERR "mxser: can't register pci driver\n"); - if (!m) { - retval = -ENODEV; - goto err_unr; - } /* else: we have some ISA cards under control */ + goto err_unr; } return 0; @@ -2794,19 +2014,9 @@ err_put: static void __exit mxser_module_exit(void) { - unsigned int i; - pci_unregister_driver(&mxser_driver); - - for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */ - if (mxser_boards[i].info != NULL) - mxser_board_remove(&mxser_boards[i]); tty_unregister_driver(mxvar_sdriver); put_tty_driver(mxvar_sdriver); - - for (i = 0; i < MXSER_BOARDS; i++) - if (mxser_boards[i].info != NULL) - mxser_release_ISA_res(&mxser_boards[i]); } module_init(mxser_module_init); diff --git a/drivers/tty/mxser.h b/drivers/tty/mxser.h deleted file mode 100644 index e6cb15626567..000000000000 --- a/drivers/tty/mxser.h +++ /dev/null @@ -1,151 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _MXSER_H -#define _MXSER_H - -/* - * Semi-public control interfaces - */ - -/* - * MOXA ioctls - */ - -#define MOXA 0x400 -#define MOXA_GETDATACOUNT (MOXA + 23) -#define MOXA_DIAGNOSE (MOXA + 50) -#define MOXA_CHKPORTENABLE (MOXA + 60) -#define MOXA_HighSpeedOn (MOXA + 61) -#define MOXA_GET_MAJOR (MOXA + 63) -#define MOXA_GETMSTATUS (MOXA + 65) -#define MOXA_SET_OP_MODE (MOXA + 66) -#define MOXA_GET_OP_MODE (MOXA + 67) - -#define RS232_MODE 0 -#define RS485_2WIRE_MODE 1 -#define RS422_MODE 2 -#define RS485_4WIRE_MODE 3 -#define OP_MODE_MASK 3 - -#define MOXA_SDS_RSTICOUNTER (MOXA + 69) -#define MOXA_ASPP_OQUEUE (MOXA + 70) -#define MOXA_ASPP_MON (MOXA + 73) -#define MOXA_ASPP_LSTATUS (MOXA + 74) -#define MOXA_ASPP_MON_EXT (MOXA + 75) -#define MOXA_SET_BAUD_METHOD (MOXA + 76) - -/* --------------------------------------------------- */ - -#define NPPI_NOTIFY_PARITY 0x01 -#define NPPI_NOTIFY_FRAMING 0x02 -#define NPPI_NOTIFY_HW_OVERRUN 0x04 -#define NPPI_NOTIFY_SW_OVERRUN 0x08 -#define NPPI_NOTIFY_BREAK 0x10 - -#define NPPI_NOTIFY_CTSHOLD 0x01 /* Tx hold by CTS low */ -#define NPPI_NOTIFY_DSRHOLD 0x02 /* Tx hold by DSR low */ -#define NPPI_NOTIFY_XOFFHOLD 0x08 /* Tx hold by Xoff received */ -#define NPPI_NOTIFY_XOFFXENT 0x10 /* Xoff Sent */ - -/* follow just for Moxa Must chip define. */ -/* */ -/* when LCR register (offset 0x03) write following value, */ -/* the Must chip will enter enchance mode. And write value */ -/* on EFR (offset 0x02) bit 6,7 to change bank. */ -#define MOXA_MUST_ENTER_ENCHANCE 0xBF - -/* when enhance mode enable, access on general bank register */ -#define MOXA_MUST_GDL_REGISTER 0x07 -#define MOXA_MUST_GDL_MASK 0x7F -#define MOXA_MUST_GDL_HAS_BAD_DATA 0x80 - -#define MOXA_MUST_LSR_RERR 0x80 /* error in receive FIFO */ -/* enchance register bank select and enchance mode setting register */ -/* when LCR register equal to 0xBF */ -#define MOXA_MUST_EFR_REGISTER 0x02 -/* enchance mode enable */ -#define MOXA_MUST_EFR_EFRB_ENABLE 0x10 -/* enchance reister bank set 0, 1, 2 */ -#define MOXA_MUST_EFR_BANK0 0x00 -#define MOXA_MUST_EFR_BANK1 0x40 -#define MOXA_MUST_EFR_BANK2 0x80 -#define MOXA_MUST_EFR_BANK3 0xC0 -#define MOXA_MUST_EFR_BANK_MASK 0xC0 - -/* set XON1 value register, when LCR=0xBF and change to bank0 */ -#define MOXA_MUST_XON1_REGISTER 0x04 - -/* set XON2 value register, when LCR=0xBF and change to bank0 */ -#define MOXA_MUST_XON2_REGISTER 0x05 - -/* set XOFF1 value register, when LCR=0xBF and change to bank0 */ -#define MOXA_MUST_XOFF1_REGISTER 0x06 - -/* set XOFF2 value register, when LCR=0xBF and change to bank0 */ -#define MOXA_MUST_XOFF2_REGISTER 0x07 - -#define MOXA_MUST_RBRTL_REGISTER 0x04 -#define MOXA_MUST_RBRTH_REGISTER 0x05 -#define MOXA_MUST_RBRTI_REGISTER 0x06 -#define MOXA_MUST_THRTL_REGISTER 0x07 -#define MOXA_MUST_ENUM_REGISTER 0x04 -#define MOXA_MUST_HWID_REGISTER 0x05 -#define MOXA_MUST_ECR_REGISTER 0x06 -#define MOXA_MUST_CSR_REGISTER 0x07 - -/* good data mode enable */ -#define MOXA_MUST_FCR_GDA_MODE_ENABLE 0x20 -/* only good data put into RxFIFO */ -#define MOXA_MUST_FCR_GDA_ONLY_ENABLE 0x10 - -/* enable CTS interrupt */ -#define MOXA_MUST_IER_ECTSI 0x80 -/* enable RTS interrupt */ -#define MOXA_MUST_IER_ERTSI 0x40 -/* enable Xon/Xoff interrupt */ -#define MOXA_MUST_IER_XINT 0x20 -/* enable GDA interrupt */ -#define MOXA_MUST_IER_EGDAI 0x10 - -#define MOXA_MUST_RECV_ISR (UART_IER_RDI | MOXA_MUST_IER_EGDAI) - -/* GDA interrupt pending */ -#define MOXA_MUST_IIR_GDA 0x1C -#define MOXA_MUST_IIR_RDA 0x04 -#define MOXA_MUST_IIR_RTO 0x0C -#define MOXA_MUST_IIR_LSR 0x06 - -/* received Xon/Xoff or specical interrupt pending */ -#define MOXA_MUST_IIR_XSC 0x10 - -/* RTS/CTS change state interrupt pending */ -#define MOXA_MUST_IIR_RTSCTS 0x20 -#define MOXA_MUST_IIR_MASK 0x3E - -#define MOXA_MUST_MCR_XON_FLAG 0x40 -#define MOXA_MUST_MCR_XON_ANY 0x80 -#define MOXA_MUST_MCR_TX_XON 0x08 - -/* software flow control on chip mask value */ -#define MOXA_MUST_EFR_SF_MASK 0x0F -/* send Xon1/Xoff1 */ -#define MOXA_MUST_EFR_SF_TX1 0x08 -/* send Xon2/Xoff2 */ -#define MOXA_MUST_EFR_SF_TX2 0x04 -/* send Xon1,Xon2/Xoff1,Xoff2 */ -#define MOXA_MUST_EFR_SF_TX12 0x0C -/* don't send Xon/Xoff */ -#define MOXA_MUST_EFR_SF_TX_NO 0x00 -/* Tx software flow control mask */ -#define MOXA_MUST_EFR_SF_TX_MASK 0x0C -/* don't receive Xon/Xoff */ -#define MOXA_MUST_EFR_SF_RX_NO 0x00 -/* receive Xon1/Xoff1 */ -#define MOXA_MUST_EFR_SF_RX1 0x02 -/* receive Xon2/Xoff2 */ -#define MOXA_MUST_EFR_SF_RX2 0x01 -/* receive Xon1,Xon2/Xoff1,Xoff2 */ -#define MOXA_MUST_EFR_SF_RX12 0x03 -/* Rx software flow control mask */ -#define MOXA_MUST_EFR_SF_RX_MASK 0x03 - -#endif diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 5fea02cfb0cc..e907b7a5cab5 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -512,7 +512,7 @@ static void gsm_print_packet(const char *hdr, int addr, int cr, */ /** - * gsm_stuff_packet - bytestuff a packet + * gsm_stuff_frame - bytestuff a packet * @input: input buffer * @output: output buffer * @len: length of input @@ -1594,7 +1594,7 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, const u8 *data, int clen) } /** - * gsm_dlci_control - data arrived on control channel + * gsm_dlci_command - data arrived on control channel * @dlci: channel * @data: block of bytes received * @len: length of received block @@ -2424,7 +2424,7 @@ static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) } static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) + const char *fp, int count) { struct gsm_mux *gsm = tty->disc_data; char flags = TTY_NORMAL; @@ -2557,6 +2557,8 @@ static void gsmld_write_wakeup(struct tty_struct *tty) * @file: file object * @buf: userspace buffer pointer * @nr: size of I/O + * @cookie: unused + * @offset: unused * * Perform reads for the line discipline. We are guaranteed that the * line discipline will not be closed under us but we may get multiple @@ -2857,6 +2859,7 @@ static int gsm_create_network(struct gsm_dlci *dlci, struct gsm_netconfig *nc) /* Line discipline for real tty */ static struct tty_ldisc_ops tty_ldisc_packet = { .owner = THIS_MODULE, + .num = N_GSM0710, .name = "n_gsm", .open = gsmld_open, .close = gsmld_close, @@ -3055,7 +3058,7 @@ static int gsmtty_write(struct tty_struct *tty, const unsigned char *buf, return sent; } -static int gsmtty_write_room(struct tty_struct *tty) +static unsigned int gsmtty_write_room(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; if (dlci->state == DLCI_CLOSED) @@ -3063,7 +3066,7 @@ static int gsmtty_write_room(struct tty_struct *tty) return TX_SIZE - kfifo_len(&dlci->fifo); } -static int gsmtty_chars_in_buffer(struct tty_struct *tty) +static unsigned int gsmtty_chars_in_buffer(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; if (dlci->state == DLCI_CLOSED) @@ -3242,7 +3245,7 @@ static const struct tty_operations gsmtty_ops = { static int __init gsm_init(void) { /* Fill in our line protocol discipline, and register it */ - int status = tty_register_ldisc(N_GSM0710, &tty_ldisc_packet); + int status = tty_register_ldisc(&tty_ldisc_packet); if (status != 0) { pr_err("n_gsm: can't register line discipline (err = %d)\n", status); @@ -3251,9 +3254,9 @@ static int __init gsm_init(void) gsm_tty_driver = alloc_tty_driver(256); if (!gsm_tty_driver) { - tty_unregister_ldisc(N_GSM0710); pr_err("gsm_init: tty allocation failed.\n"); - return -EINVAL; + status = -ENOMEM; + goto err_unreg_ldisc; } gsm_tty_driver->driver_name = "gsmtty"; gsm_tty_driver->name = "gsmtty"; @@ -3269,22 +3272,23 @@ static int __init gsm_init(void) tty_set_operations(gsm_tty_driver, &gsmtty_ops); if (tty_register_driver(gsm_tty_driver)) { - put_tty_driver(gsm_tty_driver); - tty_unregister_ldisc(N_GSM0710); pr_err("gsm_init: tty registration failed.\n"); - return -EBUSY; + status = -EBUSY; + goto err_put_driver; } pr_debug("gsm_init: loaded as %d,%d.\n", gsm_tty_driver->major, gsm_tty_driver->minor_start); return 0; +err_put_driver: + put_tty_driver(gsm_tty_driver); +err_unreg_ldisc: + tty_unregister_ldisc(&tty_ldisc_packet); + return status; } static void __exit gsm_exit(void) { - int status = tty_unregister_ldisc(N_GSM0710); - if (status != 0) - pr_err("n_gsm: can't unregister line discipline (err = %d)\n", - status); + tty_unregister_ldisc(&tty_ldisc_packet); tty_unregister_driver(gsm_tty_driver); put_tty_driver(gsm_tty_driver); } diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index b0f33e8ac819..580a37b3fe1b 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -358,7 +358,7 @@ static void n_hdlc_tty_wakeup(struct tty_struct *tty) * interpreted as one HDLC frame. */ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data, - char *flags, int count) + const char *flags, int count) { register struct n_hdlc *n_hdlc = tty->disc_data; register struct n_hdlc_buf *buf; @@ -411,8 +411,10 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data, * n_hdlc_tty_read - Called to retrieve one frame of data (if available) * @tty: pointer to tty instance data * @file: pointer to open file object - * @buf: pointer to returned data buffer + * @kbuf: pointer to returned data buffer * @nr: size of returned data buffer + * @cookie: stored rbuf from previous run + * @offset: offset into the data buffer * * Returns the number of bytes returned or error code. */ @@ -788,6 +790,7 @@ static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *buf_list) static struct tty_ldisc_ops n_hdlc_ldisc = { .owner = THIS_MODULE, + .num = N_HDLC, .name = "hdlc", .open = n_hdlc_tty_open, .close = n_hdlc_tty_close, @@ -807,7 +810,7 @@ static int __init n_hdlc_init(void) /* range check maxframe arg */ maxframe = clamp(maxframe, 4096, MAX_HDLC_FRAME_SIZE); - status = tty_register_ldisc(N_HDLC, &n_hdlc_ldisc); + status = tty_register_ldisc(&n_hdlc_ldisc); if (!status) pr_info("N_HDLC line discipline registered with maxframe=%d\n", maxframe); @@ -821,14 +824,7 @@ static int __init n_hdlc_init(void) static void __exit n_hdlc_exit(void) { - /* Release tty registration of line discipline */ - int status = tty_unregister_ldisc(N_HDLC); - - if (status) - pr_err("N_HDLC: can't unregister line discipline (err = %d)\n", - status); - else - pr_info("N_HDLC: line discipline unregistered\n"); + tty_unregister_ldisc(&n_hdlc_ldisc); } module_init(n_hdlc_init); diff --git a/drivers/tty/n_null.c b/drivers/tty/n_null.c index b8f67b5f1ef8..f913b665af72 100644 --- a/drivers/tty/n_null.c +++ b/drivers/tty/n_null.c @@ -33,13 +33,14 @@ static ssize_t n_null_write(struct tty_struct *tty, struct file *file, } static void n_null_receivebuf(struct tty_struct *tty, - const unsigned char *cp, char *fp, + const unsigned char *cp, const char *fp, int cnt) { } static struct tty_ldisc_ops null_ldisc = { .owner = THIS_MODULE, + .num = N_NULL, .name = "n_null", .open = n_null_open, .close = n_null_close, @@ -50,13 +51,13 @@ static struct tty_ldisc_ops null_ldisc = { static int __init n_null_init(void) { - BUG_ON(tty_register_ldisc(N_NULL, &null_ldisc)); + BUG_ON(tty_register_ldisc(&null_ldisc)); return 0; } static void __exit n_null_exit(void) { - tty_unregister_ldisc(N_NULL); + tty_unregister_ldisc(&null_ldisc); } module_init(n_null_init); diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c deleted file mode 100644 index 2eb76ea1d88d..000000000000 --- a/drivers/tty/n_r3964.c +++ /dev/null @@ -1,1283 +0,0 @@ -// SPDX-License-Identifier: GPL-1.0+ -/* r3964 linediscipline for linux - * - * ----------------------------------------------------------- - * Copyright by - * Philips Automation Projects - * Kassel (Germany) - * ----------------------------------------------------------- - * Author: - * L. Haag - * - * $Log: n_r3964.c,v $ - * Revision 1.10 2001/03/18 13:02:24 dwmw2 - * Fix timer usage, use spinlocks properly. - * - * Revision 1.9 2001/03/18 12:52:14 dwmw2 - * Merge changes in 2.4.2 - * - * Revision 1.8 2000/03/23 14:14:54 dwmw2 - * Fix race in sleeping in r3964_read() - * - * Revision 1.7 1999/28/08 11:41:50 dwmw2 - * Port to 2.3 kernel - * - * Revision 1.6 1998/09/30 00:40:40 dwmw2 - * Fixed compilation on 2.0.x kernels - * Updated to newly registered tty-ldisc number 9 - * - * Revision 1.5 1998/09/04 21:57:36 dwmw2 - * Signal handling bug fixes, port to 2.1.x. - * - * Revision 1.4 1998/04/02 20:26:59 lhaag - * select, blocking, ... - * - * Revision 1.3 1998/02/12 18:58:43 root - * fixed some memory leaks - * calculation of checksum characters - * - * Revision 1.2 1998/02/07 13:03:34 root - * ioctl read_telegram - * - * Revision 1.1 1998/02/06 19:21:03 root - * Initial revision - * - * - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/interrupt.h> -#include <linux/ptrace.h> -#include <linux/ioport.h> -#include <linux/in.h> -#include <linux/slab.h> -#include <linux/tty.h> -#include <linux/errno.h> -#include <linux/string.h> /* used in new tty drivers */ -#include <linux/signal.h> /* used in new tty drivers */ -#include <linux/ioctl.h> -#include <linux/n_r3964.h> -#include <linux/poll.h> -#include <linux/init.h> -#include <linux/uaccess.h> - -/*#define DEBUG_QUEUE*/ - -/* Log successful handshake and protocol operations */ -/*#define DEBUG_PROTO_S*/ - -/* Log handshake and protocol errors: */ -/*#define DEBUG_PROTO_E*/ - -/* Log Linediscipline operations (open, close, read, write...): */ -/*#define DEBUG_LDISC*/ - -/* Log module and memory operations (init, cleanup; kmalloc, kfree): */ -/*#define DEBUG_MODUL*/ - -/* Macro helpers for debug output: */ -#define TRACE(format, args...) printk("r3964: " format "\n" , ## args) - -#ifdef DEBUG_MODUL -#define TRACE_M(format, args...) printk("r3964: " format "\n" , ## args) -#else -#define TRACE_M(fmt, arg...) do {} while (0) -#endif -#ifdef DEBUG_PROTO_S -#define TRACE_PS(format, args...) printk("r3964: " format "\n" , ## args) -#else -#define TRACE_PS(fmt, arg...) do {} while (0) -#endif -#ifdef DEBUG_PROTO_E -#define TRACE_PE(format, args...) printk("r3964: " format "\n" , ## args) -#else -#define TRACE_PE(fmt, arg...) do {} while (0) -#endif -#ifdef DEBUG_LDISC -#define TRACE_L(format, args...) printk("r3964: " format "\n" , ## args) -#else -#define TRACE_L(fmt, arg...) do {} while (0) -#endif -#ifdef DEBUG_QUEUE -#define TRACE_Q(format, args...) printk("r3964: " format "\n" , ## args) -#else -#define TRACE_Q(fmt, arg...) do {} while (0) -#endif -static void add_tx_queue(struct r3964_info *, struct r3964_block_header *); -static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code); -static void put_char(struct r3964_info *pInfo, unsigned char ch); -static void trigger_transmit(struct r3964_info *pInfo); -static void retry_transmit(struct r3964_info *pInfo); -static void transmit_block(struct r3964_info *pInfo); -static void receive_char(struct r3964_info *pInfo, const unsigned char c); -static void receive_error(struct r3964_info *pInfo, const char flag); -static void on_timeout(struct timer_list *t); -static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg); -static int read_telegram(struct r3964_info *pInfo, struct pid *pid, - unsigned char __user * buf); -static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, - int error_code, struct r3964_block_header *pBlock); -static struct r3964_message *remove_msg(struct r3964_info *pInfo, - struct r3964_client_info *pClient); -static void remove_client_block(struct r3964_info *pInfo, - struct r3964_client_info *pClient); - -static int r3964_open(struct tty_struct *tty); -static void r3964_close(struct tty_struct *tty); -static ssize_t r3964_read(struct tty_struct *tty, struct file *file, - void *cookie, unsigned char *buf, size_t nr); -static ssize_t r3964_write(struct tty_struct *tty, struct file *file, - const unsigned char *buf, size_t nr); -static int r3964_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg); -#ifdef CONFIG_COMPAT -static int r3964_compat_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg); -#endif -static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old); -static __poll_t r3964_poll(struct tty_struct *tty, struct file *file, - struct poll_table_struct *wait); -static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count); - -static struct tty_ldisc_ops tty_ldisc_N_R3964 = { - .owner = THIS_MODULE, - .name = "R3964", - .open = r3964_open, - .close = r3964_close, - .read = r3964_read, - .write = r3964_write, - .ioctl = r3964_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = r3964_compat_ioctl, -#endif - .set_termios = r3964_set_termios, - .poll = r3964_poll, - .receive_buf = r3964_receive_buf, -}; - -static void dump_block(const unsigned char *block, unsigned int length) -{ - unsigned int i, j; - char linebuf[16 * 3 + 1]; - - for (i = 0; i < length; i += 16) { - for (j = 0; (j < 16) && (j + i < length); j++) { - sprintf(linebuf + 3 * j, "%02x ", block[i + j]); - } - linebuf[3 * j] = '\0'; - TRACE_PS("%s", linebuf); - } -} - -/************************************************************* - * Driver initialisation - *************************************************************/ - -/************************************************************* - * Module support routines - *************************************************************/ - -static void __exit r3964_exit(void) -{ - int status; - - TRACE_M("cleanup_module()"); - - status = tty_unregister_ldisc(N_R3964); - - if (status != 0) { - printk(KERN_ERR "r3964: error unregistering linediscipline: " - "%d\n", status); - } else { - TRACE_L("linediscipline successfully unregistered"); - } -} - -static int __init r3964_init(void) -{ - int status; - - printk("r3964: Philips r3964 Driver $Revision: 1.10 $\n"); - - /* - * Register the tty line discipline - */ - - status = tty_register_ldisc(N_R3964, &tty_ldisc_N_R3964); - if (status == 0) { - TRACE_L("line discipline %d registered", N_R3964); - TRACE_L("flags=%x num=%x", tty_ldisc_N_R3964.flags, - tty_ldisc_N_R3964.num); - TRACE_L("open=%p", tty_ldisc_N_R3964.open); - TRACE_L("tty_ldisc_N_R3964 = %p", &tty_ldisc_N_R3964); - } else { - printk(KERN_ERR "r3964: error registering line discipline: " - "%d\n", status); - } - return status; -} - -module_init(r3964_init); -module_exit(r3964_exit); - -/************************************************************* - * Protocol implementation routines - *************************************************************/ - -static void add_tx_queue(struct r3964_info *pInfo, - struct r3964_block_header *pHeader) -{ - unsigned long flags; - - spin_lock_irqsave(&pInfo->lock, flags); - - pHeader->next = NULL; - - if (pInfo->tx_last == NULL) { - pInfo->tx_first = pInfo->tx_last = pHeader; - } else { - pInfo->tx_last->next = pHeader; - pInfo->tx_last = pHeader; - } - - spin_unlock_irqrestore(&pInfo->lock, flags); - - TRACE_Q("add_tx_queue %p, length %d, tx_first = %p", - pHeader, pHeader->length, pInfo->tx_first); -} - -static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code) -{ - struct r3964_block_header *pHeader; - unsigned long flags; -#ifdef DEBUG_QUEUE - struct r3964_block_header *pDump; -#endif - - pHeader = pInfo->tx_first; - - if (pHeader == NULL) - return; - -#ifdef DEBUG_QUEUE - printk("r3964: remove_from_tx_queue: %p, length %u - ", - pHeader, pHeader->length); - for (pDump = pHeader; pDump; pDump = pDump->next) - printk("%p ", pDump); - printk("\n"); -#endif - - if (pHeader->owner) { - if (error_code) { - add_msg(pHeader->owner, R3964_MSG_ACK, 0, - error_code, NULL); - } else { - add_msg(pHeader->owner, R3964_MSG_ACK, pHeader->length, - error_code, NULL); - } - wake_up_interruptible(&pInfo->tty->read_wait); - } - - spin_lock_irqsave(&pInfo->lock, flags); - - pInfo->tx_first = pHeader->next; - if (pInfo->tx_first == NULL) { - pInfo->tx_last = NULL; - } - - spin_unlock_irqrestore(&pInfo->lock, flags); - - kfree(pHeader); - TRACE_M("remove_from_tx_queue - kfree %p", pHeader); - - TRACE_Q("remove_from_tx_queue: tx_first = %p, tx_last = %p", - pInfo->tx_first, pInfo->tx_last); -} - -static void add_rx_queue(struct r3964_info *pInfo, - struct r3964_block_header *pHeader) -{ - unsigned long flags; - - spin_lock_irqsave(&pInfo->lock, flags); - - pHeader->next = NULL; - - if (pInfo->rx_last == NULL) { - pInfo->rx_first = pInfo->rx_last = pHeader; - } else { - pInfo->rx_last->next = pHeader; - pInfo->rx_last = pHeader; - } - pInfo->blocks_in_rx_queue++; - - spin_unlock_irqrestore(&pInfo->lock, flags); - - TRACE_Q("add_rx_queue: %p, length = %d, rx_first = %p, count = %d", - pHeader, pHeader->length, - pInfo->rx_first, pInfo->blocks_in_rx_queue); -} - -static void remove_from_rx_queue(struct r3964_info *pInfo, - struct r3964_block_header *pHeader) -{ - unsigned long flags; - struct r3964_block_header *pFind; - - if (pHeader == NULL) - return; - - TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d", - pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue); - TRACE_Q("remove_from_rx_queue: %p, length %u", - pHeader, pHeader->length); - - spin_lock_irqsave(&pInfo->lock, flags); - - if (pInfo->rx_first == pHeader) { - /* Remove the first block in the linked list: */ - pInfo->rx_first = pHeader->next; - - if (pInfo->rx_first == NULL) { - pInfo->rx_last = NULL; - } - pInfo->blocks_in_rx_queue--; - } else { - /* Find block to remove: */ - for (pFind = pInfo->rx_first; pFind; pFind = pFind->next) { - if (pFind->next == pHeader) { - /* Got it. */ - pFind->next = pHeader->next; - pInfo->blocks_in_rx_queue--; - if (pFind->next == NULL) { - /* Oh, removed the last one! */ - pInfo->rx_last = pFind; - } - break; - } - } - } - - spin_unlock_irqrestore(&pInfo->lock, flags); - - kfree(pHeader); - TRACE_M("remove_from_rx_queue - kfree %p", pHeader); - - TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d", - pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue); -} - -static void put_char(struct r3964_info *pInfo, unsigned char ch) -{ - struct tty_struct *tty = pInfo->tty; - /* FIXME: put_char should not be called from an IRQ */ - tty_put_char(tty, ch); - pInfo->bcc ^= ch; -} - -static void flush(struct r3964_info *pInfo) -{ - struct tty_struct *tty = pInfo->tty; - - if (tty == NULL || tty->ops->flush_chars == NULL) - return; - tty->ops->flush_chars(tty); -} - -static void trigger_transmit(struct r3964_info *pInfo) -{ - unsigned long flags; - - spin_lock_irqsave(&pInfo->lock, flags); - - if ((pInfo->state == R3964_IDLE) && (pInfo->tx_first != NULL)) { - pInfo->state = R3964_TX_REQUEST; - pInfo->nRetry = 0; - pInfo->flags &= ~R3964_ERROR; - mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); - - spin_unlock_irqrestore(&pInfo->lock, flags); - - TRACE_PS("trigger_transmit - sent STX"); - - put_char(pInfo, STX); - flush(pInfo); - - pInfo->bcc = 0; - } else { - spin_unlock_irqrestore(&pInfo->lock, flags); - } -} - -static void retry_transmit(struct r3964_info *pInfo) -{ - if (pInfo->nRetry < R3964_MAX_RETRIES) { - TRACE_PE("transmission failed. Retry #%d", pInfo->nRetry); - pInfo->bcc = 0; - put_char(pInfo, STX); - flush(pInfo); - pInfo->state = R3964_TX_REQUEST; - pInfo->nRetry++; - mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); - } else { - TRACE_PE("transmission failed after %d retries", - R3964_MAX_RETRIES); - - remove_from_tx_queue(pInfo, R3964_TX_FAIL); - - put_char(pInfo, NAK); - flush(pInfo); - pInfo->state = R3964_IDLE; - - trigger_transmit(pInfo); - } -} - -static void transmit_block(struct r3964_info *pInfo) -{ - struct tty_struct *tty = pInfo->tty; - struct r3964_block_header *pBlock = pInfo->tx_first; - int room = 0; - - if (tty == NULL || pBlock == NULL) { - return; - } - - room = tty_write_room(tty); - - TRACE_PS("transmit_block %p, room %d, length %d", - pBlock, room, pBlock->length); - - while (pInfo->tx_position < pBlock->length) { - if (room < 2) - break; - - if (pBlock->data[pInfo->tx_position] == DLE) { - /* send additional DLE char: */ - put_char(pInfo, DLE); - } - put_char(pInfo, pBlock->data[pInfo->tx_position++]); - - room--; - } - - if ((pInfo->tx_position == pBlock->length) && (room >= 3)) { - put_char(pInfo, DLE); - put_char(pInfo, ETX); - if (pInfo->flags & R3964_BCC) { - put_char(pInfo, pInfo->bcc); - } - pInfo->state = R3964_WAIT_FOR_TX_ACK; - mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); - } - flush(pInfo); -} - -static void on_receive_block(struct r3964_info *pInfo) -{ - unsigned int length; - struct r3964_client_info *pClient; - struct r3964_block_header *pBlock; - - length = pInfo->rx_position; - - /* compare byte checksum characters: */ - if (pInfo->flags & R3964_BCC) { - if (pInfo->bcc != pInfo->last_rx) { - TRACE_PE("checksum error - got %x but expected %x", - pInfo->last_rx, pInfo->bcc); - pInfo->flags |= R3964_CHECKSUM; - } - } - - /* check for errors (parity, overrun,...): */ - if (pInfo->flags & R3964_ERROR) { - TRACE_PE("on_receive_block - transmission failed error %x", - pInfo->flags & R3964_ERROR); - - put_char(pInfo, NAK); - flush(pInfo); - if (pInfo->nRetry < R3964_MAX_RETRIES) { - pInfo->state = R3964_WAIT_FOR_RX_REPEAT; - pInfo->nRetry++; - mod_timer(&pInfo->tmr, jiffies + R3964_TO_RX_PANIC); - } else { - TRACE_PE("on_receive_block - failed after max retries"); - pInfo->state = R3964_IDLE; - } - return; - } - - /* received block; submit DLE: */ - put_char(pInfo, DLE); - flush(pInfo); - del_timer_sync(&pInfo->tmr); - TRACE_PS(" rx success: got %d chars", length); - - /* prepare struct r3964_block_header: */ - pBlock = kmalloc(length + sizeof(struct r3964_block_header), - GFP_KERNEL); - TRACE_M("on_receive_block - kmalloc %p", pBlock); - - if (pBlock == NULL) - return; - - pBlock->length = length; - pBlock->data = ((unsigned char *)pBlock) + - sizeof(struct r3964_block_header); - pBlock->locks = 0; - pBlock->next = NULL; - pBlock->owner = NULL; - - memcpy(pBlock->data, pInfo->rx_buf, length); - - /* queue block into rx_queue: */ - add_rx_queue(pInfo, pBlock); - - /* notify attached client processes: */ - for (pClient = pInfo->firstClient; pClient; pClient = pClient->next) { - if (pClient->sig_flags & R3964_SIG_DATA) { - add_msg(pClient, R3964_MSG_DATA, length, R3964_OK, - pBlock); - } - } - wake_up_interruptible(&pInfo->tty->read_wait); - - pInfo->state = R3964_IDLE; - - trigger_transmit(pInfo); -} - -static void receive_char(struct r3964_info *pInfo, const unsigned char c) -{ - switch (pInfo->state) { - case R3964_TX_REQUEST: - if (c == DLE) { - TRACE_PS("TX_REQUEST - got DLE"); - - pInfo->state = R3964_TRANSMITTING; - pInfo->tx_position = 0; - - transmit_block(pInfo); - } else if (c == STX) { - if (pInfo->nRetry == 0) { - TRACE_PE("TX_REQUEST - init conflict"); - if (pInfo->priority == R3964_SLAVE) { - goto start_receiving; - } - } else { - TRACE_PE("TX_REQUEST - secondary init " - "conflict!? Switching to SLAVE mode " - "for next rx."); - goto start_receiving; - } - } else { - TRACE_PE("TX_REQUEST - char != DLE: %x", c); - retry_transmit(pInfo); - } - break; - case R3964_TRANSMITTING: - if (c == NAK) { - TRACE_PE("TRANSMITTING - got NAK"); - retry_transmit(pInfo); - } else { - TRACE_PE("TRANSMITTING - got invalid char"); - - pInfo->state = R3964_WAIT_ZVZ_BEFORE_TX_RETRY; - mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); - } - break; - case R3964_WAIT_FOR_TX_ACK: - if (c == DLE) { - TRACE_PS("WAIT_FOR_TX_ACK - got DLE"); - remove_from_tx_queue(pInfo, R3964_OK); - - pInfo->state = R3964_IDLE; - trigger_transmit(pInfo); - } else { - retry_transmit(pInfo); - } - break; - case R3964_WAIT_FOR_RX_REPEAT: - case R3964_IDLE: - if (c == STX) { - /* Prevent rx_queue from overflow: */ - if (pInfo->blocks_in_rx_queue >= - R3964_MAX_BLOCKS_IN_RX_QUEUE) { - TRACE_PE("IDLE - got STX but no space in " - "rx_queue!"); - pInfo->state = R3964_WAIT_FOR_RX_BUF; - mod_timer(&pInfo->tmr, - jiffies + R3964_TO_NO_BUF); - break; - } -start_receiving: - /* Ok, start receiving: */ - TRACE_PS("IDLE - got STX"); - pInfo->rx_position = 0; - pInfo->last_rx = 0; - pInfo->flags &= ~R3964_ERROR; - pInfo->state = R3964_RECEIVING; - mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); - pInfo->nRetry = 0; - put_char(pInfo, DLE); - flush(pInfo); - pInfo->bcc = 0; - } - break; - case R3964_RECEIVING: - if (pInfo->rx_position < RX_BUF_SIZE) { - pInfo->bcc ^= c; - - if (c == DLE) { - if (pInfo->last_rx == DLE) { - pInfo->last_rx = 0; - goto char_to_buf; - } - pInfo->last_rx = DLE; - break; - } else if ((c == ETX) && (pInfo->last_rx == DLE)) { - if (pInfo->flags & R3964_BCC) { - pInfo->state = R3964_WAIT_FOR_BCC; - mod_timer(&pInfo->tmr, - jiffies + R3964_TO_ZVZ); - } else { - on_receive_block(pInfo); - } - } else { - pInfo->last_rx = c; -char_to_buf: - pInfo->rx_buf[pInfo->rx_position++] = c; - mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); - } - } - /* else: overflow-msg? BUF_SIZE>MTU; should not happen? */ - break; - case R3964_WAIT_FOR_BCC: - pInfo->last_rx = c; - on_receive_block(pInfo); - break; - } -} - -static void receive_error(struct r3964_info *pInfo, const char flag) -{ - switch (flag) { - case TTY_NORMAL: - break; - case TTY_BREAK: - TRACE_PE("received break"); - pInfo->flags |= R3964_BREAK; - break; - case TTY_PARITY: - TRACE_PE("parity error"); - pInfo->flags |= R3964_PARITY; - break; - case TTY_FRAME: - TRACE_PE("frame error"); - pInfo->flags |= R3964_FRAME; - break; - case TTY_OVERRUN: - TRACE_PE("frame overrun"); - pInfo->flags |= R3964_OVERRUN; - break; - default: - TRACE_PE("receive_error - unknown flag %d", flag); - pInfo->flags |= R3964_UNKNOWN; - break; - } -} - -static void on_timeout(struct timer_list *t) -{ - struct r3964_info *pInfo = from_timer(pInfo, t, tmr); - - switch (pInfo->state) { - case R3964_TX_REQUEST: - TRACE_PE("TX_REQUEST - timeout"); - retry_transmit(pInfo); - break; - case R3964_WAIT_ZVZ_BEFORE_TX_RETRY: - put_char(pInfo, NAK); - flush(pInfo); - retry_transmit(pInfo); - break; - case R3964_WAIT_FOR_TX_ACK: - TRACE_PE("WAIT_FOR_TX_ACK - timeout"); - retry_transmit(pInfo); - break; - case R3964_WAIT_FOR_RX_BUF: - TRACE_PE("WAIT_FOR_RX_BUF - timeout"); - put_char(pInfo, NAK); - flush(pInfo); - pInfo->state = R3964_IDLE; - break; - case R3964_RECEIVING: - TRACE_PE("RECEIVING - timeout after %d chars", - pInfo->rx_position); - put_char(pInfo, NAK); - flush(pInfo); - pInfo->state = R3964_IDLE; - break; - case R3964_WAIT_FOR_RX_REPEAT: - TRACE_PE("WAIT_FOR_RX_REPEAT - timeout"); - pInfo->state = R3964_IDLE; - break; - case R3964_WAIT_FOR_BCC: - TRACE_PE("WAIT_FOR_BCC - timeout"); - put_char(pInfo, NAK); - flush(pInfo); - pInfo->state = R3964_IDLE; - break; - } -} - -static struct r3964_client_info *findClient(struct r3964_info *pInfo, - struct pid *pid) -{ - struct r3964_client_info *pClient; - - for (pClient = pInfo->firstClient; pClient; pClient = pClient->next) { - if (pClient->pid == pid) { - return pClient; - } - } - return NULL; -} - -static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg) -{ - struct r3964_client_info *pClient; - struct r3964_client_info **ppClient; - struct r3964_message *pMsg; - - if ((arg & R3964_SIG_ALL) == 0) { - /* Remove client from client list */ - for (ppClient = &pInfo->firstClient; *ppClient; - ppClient = &(*ppClient)->next) { - pClient = *ppClient; - - if (pClient->pid == pid) { - TRACE_PS("removing client %d from client list", - pid_nr(pid)); - *ppClient = pClient->next; - while (pClient->msg_count) { - pMsg = remove_msg(pInfo, pClient); - if (pMsg) { - kfree(pMsg); - TRACE_M("enable_signals - msg " - "kfree %p", pMsg); - } - } - put_pid(pClient->pid); - kfree(pClient); - TRACE_M("enable_signals - kfree %p", pClient); - return 0; - } - } - return -EINVAL; - } else { - pClient = findClient(pInfo, pid); - if (pClient) { - /* update signal options */ - pClient->sig_flags = arg; - } else { - /* add client to client list */ - pClient = kmalloc(sizeof(struct r3964_client_info), - GFP_KERNEL); - TRACE_M("enable_signals - kmalloc %p", pClient); - if (pClient == NULL) - return -ENOMEM; - - TRACE_PS("add client %d to client list", pid_nr(pid)); - spin_lock_init(&pClient->lock); - pClient->sig_flags = arg; - pClient->pid = get_pid(pid); - pClient->next = pInfo->firstClient; - pClient->first_msg = NULL; - pClient->last_msg = NULL; - pClient->next_block_to_read = NULL; - pClient->msg_count = 0; - pInfo->firstClient = pClient; - } - } - - return 0; -} - -static int read_telegram(struct r3964_info *pInfo, struct pid *pid, - unsigned char __user * buf) -{ - struct r3964_client_info *pClient; - struct r3964_block_header *block; - - if (!buf) { - return -EINVAL; - } - - pClient = findClient(pInfo, pid); - if (pClient == NULL) { - return -EINVAL; - } - - block = pClient->next_block_to_read; - if (!block) { - return 0; - } else { - if (copy_to_user(buf, block->data, block->length)) - return -EFAULT; - - remove_client_block(pInfo, pClient); - return block->length; - } - - return -EINVAL; -} - -static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, - int error_code, struct r3964_block_header *pBlock) -{ - struct r3964_message *pMsg; - unsigned long flags; - - if (pClient->msg_count < R3964_MAX_MSG_COUNT - 1) { -queue_the_message: - - pMsg = kmalloc(sizeof(struct r3964_message), - error_code ? GFP_ATOMIC : GFP_KERNEL); - TRACE_M("add_msg - kmalloc %p", pMsg); - if (pMsg == NULL) { - return; - } - - spin_lock_irqsave(&pClient->lock, flags); - - pMsg->msg_id = msg_id; - pMsg->arg = arg; - pMsg->error_code = error_code; - pMsg->block = pBlock; - pMsg->next = NULL; - - if (pClient->last_msg == NULL) { - pClient->first_msg = pClient->last_msg = pMsg; - } else { - pClient->last_msg->next = pMsg; - pClient->last_msg = pMsg; - } - - pClient->msg_count++; - - if (pBlock != NULL) { - pBlock->locks++; - } - spin_unlock_irqrestore(&pClient->lock, flags); - } else { - if ((pClient->last_msg->msg_id == R3964_MSG_ACK) - && (pClient->last_msg->error_code == R3964_OVERFLOW)) { - pClient->last_msg->arg++; - TRACE_PE("add_msg - inc prev OVERFLOW-msg"); - } else { - msg_id = R3964_MSG_ACK; - arg = 0; - error_code = R3964_OVERFLOW; - pBlock = NULL; - TRACE_PE("add_msg - queue OVERFLOW-msg"); - goto queue_the_message; - } - } - /* Send SIGIO signal to client process: */ - if (pClient->sig_flags & R3964_USE_SIGIO) { - kill_pid(pClient->pid, SIGIO, 1); - } -} - -static struct r3964_message *remove_msg(struct r3964_info *pInfo, - struct r3964_client_info *pClient) -{ - struct r3964_message *pMsg = NULL; - unsigned long flags; - - if (pClient->first_msg) { - spin_lock_irqsave(&pClient->lock, flags); - - pMsg = pClient->first_msg; - pClient->first_msg = pMsg->next; - if (pClient->first_msg == NULL) { - pClient->last_msg = NULL; - } - - pClient->msg_count--; - if (pMsg->block) { - remove_client_block(pInfo, pClient); - pClient->next_block_to_read = pMsg->block; - } - spin_unlock_irqrestore(&pClient->lock, flags); - } - return pMsg; -} - -static void remove_client_block(struct r3964_info *pInfo, - struct r3964_client_info *pClient) -{ - struct r3964_block_header *block; - - TRACE_PS("remove_client_block PID %d", pid_nr(pClient->pid)); - - block = pClient->next_block_to_read; - if (block) { - block->locks--; - if (block->locks == 0) { - remove_from_rx_queue(pInfo, block); - } - } - pClient->next_block_to_read = NULL; -} - -/************************************************************* - * Line discipline routines - *************************************************************/ - -static int r3964_open(struct tty_struct *tty) -{ - struct r3964_info *pInfo; - - TRACE_L("open"); - TRACE_L("tty=%p, PID=%d, disc_data=%p", - tty, current->pid, tty->disc_data); - - pInfo = kmalloc(sizeof(struct r3964_info), GFP_KERNEL); - TRACE_M("r3964_open - info kmalloc %p", pInfo); - - if (!pInfo) { - printk(KERN_ERR "r3964: failed to alloc info structure\n"); - return -ENOMEM; - } - - pInfo->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL); - TRACE_M("r3964_open - rx_buf kmalloc %p", pInfo->rx_buf); - - if (!pInfo->rx_buf) { - printk(KERN_ERR "r3964: failed to alloc receive buffer\n"); - kfree(pInfo); - TRACE_M("r3964_open - info kfree %p", pInfo); - return -ENOMEM; - } - - pInfo->tx_buf = kmalloc(TX_BUF_SIZE, GFP_KERNEL); - TRACE_M("r3964_open - tx_buf kmalloc %p", pInfo->tx_buf); - - if (!pInfo->tx_buf) { - printk(KERN_ERR "r3964: failed to alloc transmit buffer\n"); - kfree(pInfo->rx_buf); - TRACE_M("r3964_open - rx_buf kfree %p", pInfo->rx_buf); - kfree(pInfo); - TRACE_M("r3964_open - info kfree %p", pInfo); - return -ENOMEM; - } - - spin_lock_init(&pInfo->lock); - mutex_init(&pInfo->read_lock); - pInfo->tty = tty; - pInfo->priority = R3964_MASTER; - pInfo->rx_first = pInfo->rx_last = NULL; - pInfo->tx_first = pInfo->tx_last = NULL; - pInfo->rx_position = 0; - pInfo->tx_position = 0; - pInfo->last_rx = 0; - pInfo->blocks_in_rx_queue = 0; - pInfo->firstClient = NULL; - pInfo->state = R3964_IDLE; - pInfo->flags = R3964_DEBUG; - pInfo->nRetry = 0; - - tty->disc_data = pInfo; - tty->receive_room = 65536; - - timer_setup(&pInfo->tmr, on_timeout, 0); - - return 0; -} - -static void r3964_close(struct tty_struct *tty) -{ - struct r3964_info *pInfo = tty->disc_data; - struct r3964_client_info *pClient, *pNext; - struct r3964_message *pMsg; - struct r3964_block_header *pHeader, *pNextHeader; - unsigned long flags; - - TRACE_L("close"); - - /* - * Make sure that our task queue isn't activated. If it - * is, take it out of the linked list. - */ - del_timer_sync(&pInfo->tmr); - - /* Remove client-structs and message queues: */ - pClient = pInfo->firstClient; - while (pClient) { - pNext = pClient->next; - while (pClient->msg_count) { - pMsg = remove_msg(pInfo, pClient); - if (pMsg) { - kfree(pMsg); - TRACE_M("r3964_close - msg kfree %p", pMsg); - } - } - put_pid(pClient->pid); - kfree(pClient); - TRACE_M("r3964_close - client kfree %p", pClient); - pClient = pNext; - } - /* Remove jobs from tx_queue: */ - spin_lock_irqsave(&pInfo->lock, flags); - pHeader = pInfo->tx_first; - pInfo->tx_first = pInfo->tx_last = NULL; - spin_unlock_irqrestore(&pInfo->lock, flags); - - while (pHeader) { - pNextHeader = pHeader->next; - kfree(pHeader); - pHeader = pNextHeader; - } - - /* Free buffers: */ - kfree(pInfo->rx_buf); - TRACE_M("r3964_close - rx_buf kfree %p", pInfo->rx_buf); - kfree(pInfo->tx_buf); - TRACE_M("r3964_close - tx_buf kfree %p", pInfo->tx_buf); - kfree(pInfo); - TRACE_M("r3964_close - info kfree %p", pInfo); -} - -static ssize_t r3964_read(struct tty_struct *tty, struct file *file, - unsigned char *kbuf, size_t nr, - void **cookie, unsigned long offset) -{ - struct r3964_info *pInfo = tty->disc_data; - struct r3964_client_info *pClient; - struct r3964_message *pMsg; - struct r3964_client_message theMsg; - int ret; - - TRACE_L("read()"); - - /* - * Internal serialization of reads. - */ - if (file->f_flags & O_NONBLOCK) { - if (!mutex_trylock(&pInfo->read_lock)) - return -EAGAIN; - } else { - if (mutex_lock_interruptible(&pInfo->read_lock)) - return -ERESTARTSYS; - } - - pClient = findClient(pInfo, task_pid(current)); - if (pClient) { - pMsg = remove_msg(pInfo, pClient); - if (pMsg == NULL) { - /* no messages available. */ - if (tty_io_nonblock(tty, file)) { - ret = -EAGAIN; - goto unlock; - } - /* block until there is a message: */ - wait_event_interruptible(tty->read_wait, - (pMsg = remove_msg(pInfo, pClient))); - } - - /* If we still haven't got a message, we must have been signalled */ - - if (!pMsg) { - ret = -EINTR; - goto unlock; - } - - /* deliver msg to client process: */ - theMsg.msg_id = pMsg->msg_id; - theMsg.arg = pMsg->arg; - theMsg.error_code = pMsg->error_code; - ret = sizeof(struct r3964_client_message); - - kfree(pMsg); - TRACE_M("r3964_read - msg kfree %p", pMsg); - - memcpy(kbuf, &theMsg, ret); - - TRACE_PS("read - return %d", ret); - goto unlock; - } - ret = -EPERM; -unlock: - mutex_unlock(&pInfo->read_lock); - return ret; -} - -static ssize_t r3964_write(struct tty_struct *tty, struct file *file, - const unsigned char *data, size_t count) -{ - struct r3964_info *pInfo = tty->disc_data; - struct r3964_block_header *pHeader; - struct r3964_client_info *pClient; - unsigned char *new_data; - - TRACE_L("write request, %d characters", count); -/* - * Verify the pointers - */ - - if (!pInfo) - return -EIO; - -/* - * Ensure that the caller does not wish to send too much. - */ - if (count > R3964_MTU) { - if (pInfo->flags & R3964_DEBUG) { - TRACE_L(KERN_WARNING "r3964_write: truncating user " - "packet from %u to mtu %d", count, R3964_MTU); - } - count = R3964_MTU; - } -/* - * Allocate a buffer for the data and copy it from the buffer with header prepended - */ - new_data = kmalloc(count + sizeof(struct r3964_block_header), - GFP_KERNEL); - TRACE_M("r3964_write - kmalloc %p", new_data); - if (new_data == NULL) { - if (pInfo->flags & R3964_DEBUG) { - printk(KERN_ERR "r3964_write: no memory\n"); - } - return -ENOSPC; - } - - pHeader = (struct r3964_block_header *)new_data; - pHeader->data = new_data + sizeof(struct r3964_block_header); - pHeader->length = count; - pHeader->locks = 0; - pHeader->owner = NULL; - - pClient = findClient(pInfo, task_pid(current)); - if (pClient) { - pHeader->owner = pClient; - } - - memcpy(pHeader->data, data, count); /* We already verified this */ - - if (pInfo->flags & R3964_DEBUG) { - dump_block(pHeader->data, count); - } - -/* - * Add buffer to transmit-queue: - */ - add_tx_queue(pInfo, pHeader); - trigger_transmit(pInfo); - - return 0; -} - -static int r3964_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct r3964_info *pInfo = tty->disc_data; - if (pInfo == NULL) - return -EINVAL; - switch (cmd) { - case R3964_ENABLE_SIGNALS: - return enable_signals(pInfo, task_pid(current), arg); - case R3964_SETPRIORITY: - if (arg < R3964_MASTER || arg > R3964_SLAVE) - return -EINVAL; - pInfo->priority = arg & 0xff; - return 0; - case R3964_USE_BCC: - if (arg) - pInfo->flags |= R3964_BCC; - else - pInfo->flags &= ~R3964_BCC; - return 0; - case R3964_READ_TELEGRAM: - return read_telegram(pInfo, task_pid(current), - (unsigned char __user *)arg); - default: - return -ENOIOCTLCMD; - } -} - -#ifdef CONFIG_COMPAT -static int r3964_compat_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case R3964_ENABLE_SIGNALS: - case R3964_SETPRIORITY: - case R3964_USE_BCC: - return r3964_ioctl(tty, file, cmd, arg); - default: - return -ENOIOCTLCMD; - } -} -#endif - -static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old) -{ - TRACE_L("set_termios"); -} - -/* Called without the kernel lock held - fine */ -static __poll_t r3964_poll(struct tty_struct *tty, struct file *file, - struct poll_table_struct *wait) -{ - struct r3964_info *pInfo = tty->disc_data; - struct r3964_client_info *pClient; - struct r3964_message *pMsg = NULL; - unsigned long flags; - __poll_t result = EPOLLOUT; - - TRACE_L("POLL"); - - pClient = findClient(pInfo, task_pid(current)); - if (pClient) { - poll_wait(file, &tty->read_wait, wait); - spin_lock_irqsave(&pInfo->lock, flags); - pMsg = pClient->first_msg; - spin_unlock_irqrestore(&pInfo->lock, flags); - if (pMsg) - result |= EPOLLIN | EPOLLRDNORM; - } else { - result = -EINVAL; - } - return result; -} - -static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) -{ - struct r3964_info *pInfo = tty->disc_data; - const unsigned char *p; - char *f, flags = TTY_NORMAL; - int i; - - for (i = count, p = cp, f = fp; i; i--, p++) { - if (f) - flags = *f++; - if (flags == TTY_NORMAL) { - receive_char(pInfo, *p); - } else { - receive_error(pInfo, flags); - } - - } -} - -MODULE_LICENSE("GPL"); -MODULE_ALIAS_LDISC(N_R3964); diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 9686c5d10571..0ec93f1a61f5 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -342,10 +342,10 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty) { unsigned long flags; - if (tty->link->packet) { - spin_lock_irqsave(&tty->ctrl_lock, flags); - tty->ctrl_status |= TIOCPKT_FLUSHREAD; - spin_unlock_irqrestore(&tty->ctrl_lock, flags); + if (tty->link->ctrl.packet) { + spin_lock_irqsave(&tty->ctrl.lock, flags); + tty->ctrl.pktstatus |= TIOCPKT_FLUSHREAD; + spin_unlock_irqrestore(&tty->ctrl.lock, flags); wake_up_interruptible(&tty->link->read_wait); } } @@ -361,7 +361,7 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty) * Holds termios_rwsem to exclude producer/consumer while * buffer indices are reset. * - * Locking: ctrl_lock, exclusive termios_rwsem + * Locking: ctrl.lock, exclusive termios_rwsem */ static void n_tty_flush_buffer(struct tty_struct *tty) @@ -1103,7 +1103,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) * buffer is 'output'. The signal is processed first to alert any current * readers or writers to discontinue and exit their i/o loops. * - * Locking: ctrl_lock + * Locking: ctrl.lock */ static void __isig(int sig, struct tty_struct *tty) @@ -1245,7 +1245,6 @@ n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c) commit_echoes(tty); } else process_echoes(tty); - return; } /** @@ -1260,12 +1259,8 @@ n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c) * n_tty_receive_buf()/producer path: * caller holds non-exclusive termios_rwsem * publishes canon_head if canonical mode is active - * - * Returns 1 if LNEXT was received, else returns 0 */ - -static int -n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) +static void n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; @@ -1273,35 +1268,35 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) if (c == START_CHAR(tty)) { start_tty(tty); process_echoes(tty); - return 0; + return; } if (c == STOP_CHAR(tty)) { stop_tty(tty); - return 0; + return; } } if (L_ISIG(tty)) { if (c == INTR_CHAR(tty)) { n_tty_receive_signal_char(tty, SIGINT, c); - return 0; + return; } else if (c == QUIT_CHAR(tty)) { n_tty_receive_signal_char(tty, SIGQUIT, c); - return 0; + return; } else if (c == SUSP_CHAR(tty)) { n_tty_receive_signal_char(tty, SIGTSTP, c); - return 0; + return; } } - if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) { + if (tty->flow.stopped && !tty->flow.tco_stopped && I_IXON(tty) && I_IXANY(tty)) { start_tty(tty); process_echoes(tty); } if (c == '\r') { if (I_IGNCR(tty)) - return 0; + return; if (I_ICRNL(tty)) c = '\n'; } else if (c == '\n' && I_INLCR(tty)) @@ -1312,7 +1307,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) { eraser(c, tty); commit_echoes(tty); - return 0; + return; } if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) { ldata->lnext = 1; @@ -1324,7 +1319,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) commit_echoes(tty); } } - return 1; + return; } if (c == REPRINT_CHAR(tty) && L_ECHO(tty) && L_IEXTEN(tty)) { size_t tail = ldata->canon_head; @@ -1337,7 +1332,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) tail++; } commit_echoes(tty); - return 0; + return; } if (c == '\n') { if (L_ECHO(tty) || L_ECHONL(tty)) { @@ -1375,7 +1370,7 @@ handle_newline: smp_store_release(&ldata->canon_head, ldata->read_head); kill_fasync(&tty->fasync, SIGIO, POLL_IN); wake_up_interruptible_poll(&tty->read_wait, EPOLLIN); - return 0; + return; } } @@ -1397,15 +1392,13 @@ handle_newline: put_tty_queue(c, ldata); put_tty_queue(c, ldata); - return 0; } -static inline void -n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c) +static void n_tty_receive_char(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; - if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) { + if (tty->flow.stopped && !tty->flow.tco_stopped && I_IXON(tty) && I_IXANY(tty)) { start_tty(tty); process_echoes(tty); } @@ -1423,31 +1416,6 @@ n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c) put_tty_queue(c, ldata); } -static void n_tty_receive_char(struct tty_struct *tty, unsigned char c) -{ - n_tty_receive_char_inline(tty, c); -} - -static inline void -n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c) -{ - struct n_tty_data *ldata = tty->disc_data; - - if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) { - start_tty(tty); - process_echoes(tty); - } - if (L_ECHO(tty)) { - finish_erasing(ldata); - /* Record the column of first canon char. */ - if (ldata->canon_head == ldata->read_head) - echo_set_canon_col(ldata); - echo_char(c, tty); - commit_echoes(tty); - } - put_tty_queue(c, ldata); -} - static void n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c) { if (I_ISTRIP(tty)) @@ -1459,7 +1427,7 @@ static void n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c) if (c == STOP_CHAR(tty)) stop_tty(tty); else if (c == START_CHAR(tty) || - (tty->stopped && !tty->flow_stopped && I_IXANY(tty) && + (tty->flow.stopped && !tty->flow.tco_stopped && I_IXANY(tty) && c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty))) { start_tty(tty); @@ -1506,7 +1474,7 @@ n_tty_receive_char_lnext(struct tty_struct *tty, unsigned char c, char flag) static void n_tty_receive_buf_real_raw(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) + const char *fp, int count) { struct n_tty_data *ldata = tty->disc_data; size_t n, head; @@ -1526,7 +1494,7 @@ n_tty_receive_buf_real_raw(struct tty_struct *tty, const unsigned char *cp, static void n_tty_receive_buf_raw(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) + const char *fp, int count) { struct n_tty_data *ldata = tty->disc_data; char flag = TTY_NORMAL; @@ -1543,7 +1511,7 @@ n_tty_receive_buf_raw(struct tty_struct *tty, const unsigned char *cp, static void n_tty_receive_buf_closing(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) + const char *fp, int count) { char flag = TTY_NORMAL; @@ -1555,68 +1523,46 @@ n_tty_receive_buf_closing(struct tty_struct *tty, const unsigned char *cp, } } -static void -n_tty_receive_buf_standard(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) +static void n_tty_receive_buf_standard(struct tty_struct *tty, + const unsigned char *cp, const char *fp, int count) { struct n_tty_data *ldata = tty->disc_data; char flag = TTY_NORMAL; while (count--) { + unsigned char c = *cp++; + if (fp) flag = *fp++; - if (likely(flag == TTY_NORMAL)) { - unsigned char c = *cp++; - - if (I_ISTRIP(tty)) - c &= 0x7f; - if (I_IUCLC(tty) && L_IEXTEN(tty)) - c = tolower(c); - if (L_EXTPROC(tty)) { - put_tty_queue(c, ldata); - continue; - } - if (!test_bit(c, ldata->char_map)) - n_tty_receive_char_inline(tty, c); - else if (n_tty_receive_char_special(tty, c) && count) { - if (fp) - flag = *fp++; - n_tty_receive_char_lnext(tty, *cp++, flag); - count--; - } - } else - n_tty_receive_char_flagged(tty, *cp++, flag); - } -} -static void -n_tty_receive_buf_fast(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) -{ - struct n_tty_data *ldata = tty->disc_data; - char flag = TTY_NORMAL; + if (ldata->lnext) { + n_tty_receive_char_lnext(tty, c, flag); + continue; + } - while (count--) { - if (fp) - flag = *fp++; - if (likely(flag == TTY_NORMAL)) { - unsigned char c = *cp++; - - if (!test_bit(c, ldata->char_map)) - n_tty_receive_char_fast(tty, c); - else if (n_tty_receive_char_special(tty, c) && count) { - if (fp) - flag = *fp++; - n_tty_receive_char_lnext(tty, *cp++, flag); - count--; - } - } else - n_tty_receive_char_flagged(tty, *cp++, flag); + if (unlikely(flag != TTY_NORMAL)) { + n_tty_receive_char_flagged(tty, c, flag); + continue; + } + + if (I_ISTRIP(tty)) + c &= 0x7f; + if (I_IUCLC(tty) && L_IEXTEN(tty)) + c = tolower(c); + if (L_EXTPROC(tty)) { + put_tty_queue(c, ldata); + continue; + } + + if (test_bit(c, ldata->char_map)) + n_tty_receive_char_special(tty, c); + else + n_tty_receive_char(tty, c); } } static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) + const char *fp, int count) { struct n_tty_data *ldata = tty->disc_data; bool preops = I_ISTRIP(tty) || (I_IUCLC(tty) && L_IEXTEN(tty)); @@ -1628,19 +1574,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, else if (tty->closing && !L_EXTPROC(tty)) n_tty_receive_buf_closing(tty, cp, fp, count); else { - if (ldata->lnext) { - char flag = TTY_NORMAL; - - if (fp) - flag = *fp++; - n_tty_receive_char_lnext(tty, *cp++, flag); - count--; - } - - if (!preops && !I_PARMRK(tty)) - n_tty_receive_buf_fast(tty, cp, fp, count); - else - n_tty_receive_buf_standard(tty, cp, fp, count); + n_tty_receive_buf_standard(tty, cp, fp, count); flush_echoes(tty); if (tty->ops->flush_chars) @@ -1695,7 +1629,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, */ static int n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count, int flow) + const char *fp, int count, int flow) { struct n_tty_data *ldata = tty->disc_data; int room, n, rcvd = 0, overflow; @@ -1764,13 +1698,13 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, } static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) + const char *fp, int count) { n_tty_receive_buf_common(tty, cp, fp, count, 0); } static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) + const char *fp, int count) { return n_tty_receive_buf_common(tty, cp, fp, count, 1); } @@ -1863,7 +1797,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) * Fix tty hang when I_IXON(tty) is cleared, but the tty * been stopped by STOP_CHAR(tty) before it. */ - if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped) { + if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow.tco_stopped) { start_tty(tty); process_echoes(tty); } @@ -2091,7 +2025,7 @@ static bool canon_copy_from_read_buf(struct tty_struct *tty, * * Locking: redirected write test is safe * current->signal->tty check is safe - * ctrl_lock to safely reference tty->pgrp + * ctrl.lock to safely reference tty->ctrl.pgrp */ static int job_control(struct tty_struct *tty, struct file *file) @@ -2138,7 +2072,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, int minimum, time; ssize_t retval = 0; long timeout; - int packet; + bool packet; size_t tail; /* @@ -2194,20 +2128,20 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, } } - packet = tty->packet; + packet = tty->ctrl.packet; tail = ldata->read_tail; add_wait_queue(&tty->read_wait, &wait); while (nr) { /* First test for status change. */ - if (packet && tty->link->ctrl_status) { + if (packet && tty->link->ctrl.pktstatus) { unsigned char cs; if (kb != kbuf) break; - spin_lock_irq(&tty->link->ctrl_lock); - cs = tty->link->ctrl_status; - tty->link->ctrl_status = 0; - spin_unlock_irq(&tty->link->ctrl_lock); + spin_lock_irq(&tty->link->ctrl.lock); + cs = tty->link->ctrl.pktstatus; + tty->link->ctrl.pktstatus = 0; + spin_unlock_irq(&tty->link->ctrl.lock); *kb++ = cs; nr--; break; @@ -2434,7 +2368,7 @@ static __poll_t n_tty_poll(struct tty_struct *tty, struct file *file, if (input_available_p(tty, 1)) mask |= EPOLLIN | EPOLLRDNORM; } - if (tty->packet && tty->link->ctrl_status) + if (tty->ctrl.packet && tty->link->ctrl.pktstatus) mask |= EPOLLPRI | EPOLLIN | EPOLLRDNORM; if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) mask |= EPOLLHUP; @@ -2490,6 +2424,7 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file, static struct tty_ldisc_ops n_tty_ops = { .owner = THIS_MODULE, + .num = N_TTY, .name = "n_tty", .open = n_tty_open, .close = n_tty_close, @@ -2515,11 +2450,11 @@ void n_tty_inherit_ops(struct tty_ldisc_ops *ops) { *ops = n_tty_ops; ops->owner = NULL; - ops->refcount = ops->flags = 0; + ops->flags = 0; } EXPORT_SYMBOL_GPL(n_tty_inherit_ops); void __init n_tty_init(void) { - tty_register_ldisc(N_TTY, &n_tty_ops); + tty_register_ldisc(&n_tty_ops); } diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c index 9a2d78ace49b..0c80f25c8c3d 100644 --- a/drivers/tty/nozomi.c +++ b/drivers/tty/nozomi.c @@ -1378,7 +1378,7 @@ static int nozomi_card_init(struct pci_dev *pdev, NOZOMI_NAME, dc); if (unlikely(ret)) { dev_err(&pdev->dev, "can't request irq %d\n", pdev->irq); - goto err_free_kfifo; + goto err_free_all_kfifo; } DBG1("base_addr: %p", dc->base_addr); @@ -1416,12 +1416,15 @@ static int nozomi_card_init(struct pci_dev *pdev, return 0; err_free_tty: - for (i = 0; i < MAX_PORT; ++i) { + for (i--; i >= 0; i--) { tty_unregister_device(ntty_driver, dc->index_start + i); tty_port_destroy(&dc->port[i].port); } + free_irq(pdev->irq, dc); +err_free_all_kfifo: + i = MAX_PORT; err_free_kfifo: - for (i = 0; i < MAX_PORT; i++) + for (i--; i >= PORT_MDM; i--) kfifo_free(&dc->port[i].fifo_ul); err_free_sbuf: kfree(dc->send_buf); @@ -1636,10 +1639,10 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, * If the port is unplugged report lots of room and let the bits * dribble away so we don't block anything. */ -static int ntty_write_room(struct tty_struct *tty) +static unsigned int ntty_write_room(struct tty_struct *tty) { struct port *port = tty->driver_data; - int room = 4096; + unsigned int room = 4096; const struct nozomi *dc = get_dc_by_tty(tty); if (dc) @@ -1776,20 +1779,15 @@ static void ntty_throttle(struct tty_struct *tty) } /* Returns number of chars in buffer, called by tty layer */ -static s32 ntty_chars_in_buffer(struct tty_struct *tty) +static unsigned int ntty_chars_in_buffer(struct tty_struct *tty) { struct port *port = tty->driver_data; struct nozomi *dc = get_dc_by_tty(tty); - s32 rval = 0; - if (unlikely(!dc || !port)) { - goto exit_in_buffer; - } - - rval = kfifo_len(&port->fifo_ul); + if (unlikely(!dc || !port)) + return 0; -exit_in_buffer: - return rval; + return kfifo_len(&port->fifo_ul); } static const struct tty_port_operations noz_tty_port_ops = { diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 9b5d4ae5d8f2..74bfabe5b453 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -57,9 +57,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp) set_bit(TTY_IO_ERROR, &tty->flags); wake_up_interruptible(&tty->read_wait); wake_up_interruptible(&tty->write_wait); - spin_lock_irq(&tty->ctrl_lock); - tty->packet = 0; - spin_unlock_irq(&tty->ctrl_lock); + spin_lock_irq(&tty->ctrl.lock); + tty->ctrl.packet = false; + spin_unlock_irq(&tty->ctrl.lock); /* Review - krefs on tty_link ?? */ if (!tty->link) return; @@ -113,7 +113,7 @@ static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c) struct tty_struct *to = tty->link; unsigned long flags; - if (tty->stopped) + if (tty->flow.stopped) return 0; if (c > 0) { @@ -136,26 +136,13 @@ static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c) * the other device. */ -static int pty_write_room(struct tty_struct *tty) +static unsigned int pty_write_room(struct tty_struct *tty) { - if (tty->stopped) + if (tty->flow.stopped) return 0; return tty_buffer_space_avail(tty->link->port); } -/** - * pty_chars_in_buffer - characters currently in our tx queue - * @tty: our tty - * - * Report how much we have in the transmit queue. As everything is - * instantly at the other end this is easy to implement. - */ - -static int pty_chars_in_buffer(struct tty_struct *tty) -{ - return 0; -} - /* Set the lock flag on a pty */ static int pty_set_lock(struct tty_struct *tty, int __user *arg) { @@ -185,16 +172,16 @@ static int pty_set_pktmode(struct tty_struct *tty, int __user *arg) if (get_user(pktmode, arg)) return -EFAULT; - spin_lock_irq(&tty->ctrl_lock); + spin_lock_irq(&tty->ctrl.lock); if (pktmode) { - if (!tty->packet) { - tty->link->ctrl_status = 0; + if (!tty->ctrl.packet) { + tty->link->ctrl.pktstatus = 0; smp_mb(); - tty->packet = 1; + tty->ctrl.packet = true; } } else - tty->packet = 0; - spin_unlock_irq(&tty->ctrl_lock); + tty->ctrl.packet = false; + spin_unlock_irq(&tty->ctrl.lock); return 0; } @@ -202,7 +189,7 @@ static int pty_set_pktmode(struct tty_struct *tty, int __user *arg) /* Get the packet mode of a pty */ static int pty_get_pktmode(struct tty_struct *tty, int __user *arg) { - int pktmode = tty->packet; + int pktmode = tty->ctrl.packet; return put_user(pktmode, arg); } @@ -232,11 +219,11 @@ static void pty_flush_buffer(struct tty_struct *tty) return; tty_buffer_flush(to, NULL); - if (to->packet) { - spin_lock_irq(&tty->ctrl_lock); - tty->ctrl_status |= TIOCPKT_FLUSHWRITE; + if (to->ctrl.packet) { + spin_lock_irq(&tty->ctrl.lock); + tty->ctrl.pktstatus |= TIOCPKT_FLUSHWRITE; wake_up_interruptible(&to->read_wait); - spin_unlock_irq(&tty->ctrl_lock); + spin_unlock_irq(&tty->ctrl.lock); } } @@ -266,7 +253,7 @@ static void pty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { /* See if packet mode change of state. */ - if (tty->link && tty->link->packet) { + if (tty->link && tty->link->ctrl.packet) { int extproc = (old_termios->c_lflag & EXTPROC) | L_EXTPROC(tty); int old_flow = ((old_termios->c_iflag & IXON) && (old_termios->c_cc[VSTOP] == '\023') && @@ -275,17 +262,17 @@ static void pty_set_termios(struct tty_struct *tty, STOP_CHAR(tty) == '\023' && START_CHAR(tty) == '\021'); if ((old_flow != new_flow) || extproc) { - spin_lock_irq(&tty->ctrl_lock); + spin_lock_irq(&tty->ctrl.lock); if (old_flow != new_flow) { - tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); + tty->ctrl.pktstatus &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); if (new_flow) - tty->ctrl_status |= TIOCPKT_DOSTOP; + tty->ctrl.pktstatus |= TIOCPKT_DOSTOP; else - tty->ctrl_status |= TIOCPKT_NOSTOP; + tty->ctrl.pktstatus |= TIOCPKT_NOSTOP; } if (extproc) - tty->ctrl_status |= TIOCPKT_IOCTL; - spin_unlock_irq(&tty->ctrl_lock); + tty->ctrl.pktstatus |= TIOCPKT_IOCTL; + spin_unlock_irq(&tty->ctrl.lock); wake_up_interruptible(&tty->link->read_wait); } } @@ -295,7 +282,7 @@ static void pty_set_termios(struct tty_struct *tty, } /** - * pty_do_resize - resize event + * pty_resize - resize event * @tty: tty being resized * @ws: window size being set. * @@ -346,11 +333,11 @@ static void pty_start(struct tty_struct *tty) { unsigned long flags; - if (tty->link && tty->link->packet) { - spin_lock_irqsave(&tty->ctrl_lock, flags); - tty->ctrl_status &= ~TIOCPKT_STOP; - tty->ctrl_status |= TIOCPKT_START; - spin_unlock_irqrestore(&tty->ctrl_lock, flags); + if (tty->link && tty->link->ctrl.packet) { + spin_lock_irqsave(&tty->ctrl.lock, flags); + tty->ctrl.pktstatus &= ~TIOCPKT_STOP; + tty->ctrl.pktstatus |= TIOCPKT_START; + spin_unlock_irqrestore(&tty->ctrl.lock, flags); wake_up_interruptible_poll(&tty->link->read_wait, EPOLLIN); } } @@ -359,11 +346,11 @@ static void pty_stop(struct tty_struct *tty) { unsigned long flags; - if (tty->link && tty->link->packet) { - spin_lock_irqsave(&tty->ctrl_lock, flags); - tty->ctrl_status &= ~TIOCPKT_START; - tty->ctrl_status |= TIOCPKT_STOP; - spin_unlock_irqrestore(&tty->ctrl_lock, flags); + if (tty->link && tty->link->ctrl.packet) { + spin_lock_irqsave(&tty->ctrl.lock, flags); + tty->ctrl.pktstatus &= ~TIOCPKT_START; + tty->ctrl.pktstatus |= TIOCPKT_STOP; + spin_unlock_irqrestore(&tty->ctrl.lock, flags); wake_up_interruptible_poll(&tty->link->read_wait, EPOLLIN); } } @@ -525,7 +512,6 @@ static const struct tty_operations master_pty_ops_bsd = { .write = pty_write, .write_room = pty_write_room, .flush_buffer = pty_flush_buffer, - .chars_in_buffer = pty_chars_in_buffer, .unthrottle = pty_unthrottle, .ioctl = pty_bsd_ioctl, .compat_ioctl = pty_bsd_compat_ioctl, @@ -541,7 +527,6 @@ static const struct tty_operations slave_pty_ops_bsd = { .write = pty_write, .write_room = pty_write_room, .flush_buffer = pty_flush_buffer, - .chars_in_buffer = pty_chars_in_buffer, .unthrottle = pty_unthrottle, .set_termios = pty_set_termios, .cleanup = pty_cleanup, @@ -626,7 +611,7 @@ static struct cdev ptmx_cdev; */ int ptm_open_peer(struct file *master, struct tty_struct *tty, int flags) { - int fd = -1; + int fd; struct file *filp; int retval = -EINVAL; struct path path; @@ -776,7 +761,6 @@ static const struct tty_operations ptm_unix98_ops = { .write = pty_write, .write_room = pty_write_room, .flush_buffer = pty_flush_buffer, - .chars_in_buffer = pty_chars_in_buffer, .unthrottle = pty_unthrottle, .ioctl = pty_unix98_ioctl, .compat_ioctl = pty_unix98_compat_ioctl, @@ -794,7 +778,6 @@ static const struct tty_operations pty_unix98_ops = { .write = pty_write, .write_room = pty_write_room, .flush_buffer = pty_flush_buffer, - .chars_in_buffer = pty_chars_in_buffer, .unthrottle = pty_unthrottle, .set_termios = pty_set_termios, .start = pty_start, diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index aead0c0c9796..9cdfcfe07e87 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -798,7 +798,7 @@ void serdev_controller_remove(struct serdev_controller *ctrl) EXPORT_SYMBOL_GPL(serdev_controller_remove); /** - * serdev_driver_register() - Register client driver with serdev core + * __serdev_device_driver_register() - Register client driver with serdev core * @sdrv: client driver to be associated with client-device. * @owner: client driver owner to set. * diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c index d035d08cb987..4caab8714e2c 100644 --- a/drivers/tty/serial/8250/8250_aspeed_vuart.c +++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c @@ -34,7 +34,6 @@ struct aspeed_vuart { struct device *dev; - void __iomem *regs; struct clk *clk; int line; struct timer_list unthrottle_timer; @@ -64,14 +63,24 @@ static const int unthrottle_timeout = HZ/10; * different system (though most of them use 3f8/4). */ +static inline u8 aspeed_vuart_readb(struct aspeed_vuart *vuart, u8 reg) +{ + return readb(vuart->port->port.membase + reg); +} + +static inline void aspeed_vuart_writeb(struct aspeed_vuart *vuart, u8 val, u8 reg) +{ + writeb(val, vuart->port->port.membase + reg); +} + static ssize_t lpc_address_show(struct device *dev, struct device_attribute *attr, char *buf) { struct aspeed_vuart *vuart = dev_get_drvdata(dev); u16 addr; - addr = (readb(vuart->regs + ASPEED_VUART_ADDRH) << 8) | - (readb(vuart->regs + ASPEED_VUART_ADDRL)); + addr = (aspeed_vuart_readb(vuart, ASPEED_VUART_ADDRH) << 8) | + (aspeed_vuart_readb(vuart, ASPEED_VUART_ADDRL)); return snprintf(buf, PAGE_SIZE - 1, "0x%x\n", addr); } @@ -81,8 +90,8 @@ static int aspeed_vuart_set_lpc_address(struct aspeed_vuart *vuart, u32 addr) if (addr > U16_MAX) return -EINVAL; - writeb(addr >> 8, vuart->regs + ASPEED_VUART_ADDRH); - writeb(addr >> 0, vuart->regs + ASPEED_VUART_ADDRL); + aspeed_vuart_writeb(vuart, addr >> 8, ASPEED_VUART_ADDRH); + aspeed_vuart_writeb(vuart, addr >> 0, ASPEED_VUART_ADDRL); return 0; } @@ -111,7 +120,7 @@ static ssize_t sirq_show(struct device *dev, struct aspeed_vuart *vuart = dev_get_drvdata(dev); u8 reg; - reg = readb(vuart->regs + ASPEED_VUART_GCRB); + reg = aspeed_vuart_readb(vuart, ASPEED_VUART_GCRB); reg &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK; reg >>= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT; @@ -128,10 +137,10 @@ static int aspeed_vuart_set_sirq(struct aspeed_vuart *vuart, u32 sirq) sirq <<= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT; sirq &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK; - reg = readb(vuart->regs + ASPEED_VUART_GCRB); + reg = aspeed_vuart_readb(vuart, ASPEED_VUART_GCRB); reg &= ~ASPEED_VUART_GCRB_HOST_SIRQ_MASK; reg |= sirq; - writeb(reg, vuart->regs + ASPEED_VUART_GCRB); + aspeed_vuart_writeb(vuart, reg, ASPEED_VUART_GCRB); return 0; } @@ -159,7 +168,7 @@ static ssize_t sirq_polarity_show(struct device *dev, struct aspeed_vuart *vuart = dev_get_drvdata(dev); u8 reg; - reg = readb(vuart->regs + ASPEED_VUART_GCRA); + reg = aspeed_vuart_readb(vuart, ASPEED_VUART_GCRA); reg &= ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY; return snprintf(buf, PAGE_SIZE - 1, "%u\n", reg ? 1 : 0); @@ -168,14 +177,14 @@ static ssize_t sirq_polarity_show(struct device *dev, static void aspeed_vuart_set_sirq_polarity(struct aspeed_vuart *vuart, bool polarity) { - u8 reg = readb(vuart->regs + ASPEED_VUART_GCRA); + u8 reg = aspeed_vuart_readb(vuart, ASPEED_VUART_GCRA); if (polarity) reg |= ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY; else reg &= ~ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY; - writeb(reg, vuart->regs + ASPEED_VUART_GCRA); + aspeed_vuart_writeb(vuart, reg, ASPEED_VUART_GCRA); } static ssize_t sirq_polarity_store(struct device *dev, @@ -210,14 +219,14 @@ static const struct attribute_group aspeed_vuart_attr_group = { static void aspeed_vuart_set_enabled(struct aspeed_vuart *vuart, bool enabled) { - u8 reg = readb(vuart->regs + ASPEED_VUART_GCRA); + u8 reg = aspeed_vuart_readb(vuart, ASPEED_VUART_GCRA); if (enabled) reg |= ASPEED_VUART_GCRA_VUART_EN; else reg &= ~ASPEED_VUART_GCRA_VUART_EN; - writeb(reg, vuart->regs + ASPEED_VUART_GCRA); + aspeed_vuart_writeb(vuart, reg, ASPEED_VUART_GCRA); } static void aspeed_vuart_set_host_tx_discard(struct aspeed_vuart *vuart, @@ -225,7 +234,7 @@ static void aspeed_vuart_set_host_tx_discard(struct aspeed_vuart *vuart, { u8 reg; - reg = readb(vuart->regs + ASPEED_VUART_GCRA); + reg = aspeed_vuart_readb(vuart, ASPEED_VUART_GCRA); /* If the DISABLE_HOST_TX_DISCARD bit is set, discard is disabled */ if (!discard) @@ -233,7 +242,7 @@ static void aspeed_vuart_set_host_tx_discard(struct aspeed_vuart *vuart, else reg &= ~ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD; - writeb(reg, vuart->regs + ASPEED_VUART_GCRA); + aspeed_vuart_writeb(vuart, reg, ASPEED_VUART_GCRA); } static int aspeed_vuart_startup(struct uart_port *uart_port) @@ -320,7 +329,7 @@ static int aspeed_vuart_handle_irq(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); unsigned int iir, lsr; - int space, count; + unsigned int space, count; iir = serial_port_in(port, UART_IIR); @@ -339,14 +348,12 @@ static int aspeed_vuart_handle_irq(struct uart_port *port) struct aspeed_vuart *vuart = port->private_data; __aspeed_vuart_set_throttle(up, true); - if (!timer_pending(&vuart->unthrottle_timer)) { - vuart->port = up; + if (!timer_pending(&vuart->unthrottle_timer)) mod_timer(&vuart->unthrottle_timer, jiffies + unthrottle_timeout); - } } else { - count = min(space, 256); + count = min(space, 256U); do { serial8250_read_char(up, lsr); @@ -421,13 +428,9 @@ static int aspeed_vuart_probe(struct platform_device *pdev) timer_setup(&vuart->unthrottle_timer, aspeed_vuart_unthrottle_exp, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - vuart->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(vuart->regs)) - return PTR_ERR(vuart->regs); memset(&port, 0, sizeof(port)); port.port.private_data = vuart; - port.port.membase = vuart->regs; port.port.mapbase = res->start; port.port.mapsize = resource_size(res); port.port.startup = aspeed_vuart_startup; @@ -485,7 +488,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev) port.port.iotype = UPIO_MEM; port.port.type = PORT_16550A; port.port.uartclk = clk; - port.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF + port.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_NO_THRE_TEST; if (of_property_read_bool(np, "no-loopback-test")) @@ -502,6 +505,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev) goto err_clk_disable; vuart->line = rc; + vuart->port = serial8250_get_port(vuart->line); rc = of_parse_phandle_with_fixed_args( np, "aspeed,sirq-polarity-sense", 2, 0, diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index cae61d1ebec5..1ce193daea7f 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -172,7 +172,6 @@ static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up) static int serial_link_irq_chain(struct uart_8250_port *up) { struct hlist_head *h; - struct hlist_node *n; struct irq_info *i; int ret; @@ -180,13 +179,11 @@ static int serial_link_irq_chain(struct uart_8250_port *up) h = &irq_lists[up->port.irq % NR_IRQ_HASH]; - hlist_for_each(n, h) { - i = hlist_entry(n, struct irq_info, node); + hlist_for_each_entry(i, h, node) if (i->irq == up->port.irq) break; - } - if (n == NULL) { + if (i == NULL) { i = kzalloc(sizeof(struct irq_info), GFP_KERNEL); if (i == NULL) { mutex_unlock(&hash_mutex); @@ -220,25 +217,18 @@ static int serial_link_irq_chain(struct uart_8250_port *up) static void serial_unlink_irq_chain(struct uart_8250_port *up) { - /* - * yes, some broken gcc emit "warning: 'i' may be used uninitialized" - * but no, we are not going to take a patch that assigns NULL below. - */ struct irq_info *i; - struct hlist_node *n; struct hlist_head *h; mutex_lock(&hash_mutex); h = &irq_lists[up->port.irq % NR_IRQ_HASH]; - hlist_for_each(n, h) { - i = hlist_entry(n, struct irq_info, node); + hlist_for_each_entry(i, h, node) if (i->irq == up->port.irq) break; - } - BUG_ON(n == NULL); + BUG_ON(i == NULL); BUG_ON(i->head == NULL); if (list_empty(i->head)) @@ -331,9 +321,9 @@ static int univ8250_setup_irq(struct uart_8250_port *up) * hardware interrupt, we use a timer-based system. The original * driver used to do this with IRQ0. */ - if (!port->irq) { + if (!port->irq) mod_timer(&up->timer, jiffies + uart_poll_timeout(port)); - } else + else retval = serial_link_irq_chain(up); return retval; @@ -762,6 +752,7 @@ void serial8250_suspend_port(int line) if (!console_suspend_enabled && uart_console(port) && port->type != PORT_8250) { unsigned char canary = 0xa5; + serial_out(up, UART_SCR, canary); if (serial_in(up, UART_SCR) == canary) up->canary = canary; @@ -915,7 +906,7 @@ static struct platform_device *serial8250_isa_devs; */ static DEFINE_MUTEX(serial_mutex); -static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *port) +static struct uart_8250_port *serial8250_find_match_or_unused(const struct uart_port *port) { int i; @@ -980,7 +971,7 @@ static void serial_8250_overrun_backoff_work(struct work_struct *work) * * On success the port is ready to use and the line number is returned. */ -int serial8250_register_8250_port(struct uart_8250_port *up) +int serial8250_register_8250_port(const struct uart_8250_port *up) { struct uart_8250_port *uart; int ret = -ENOSPC; diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index bd4e9f6ac29c..3ffeedc29c83 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -501,23 +501,27 @@ static const struct dmi_system_id exar_platforms[] = { {} }; +static const struct exar8250_platform *exar_get_platform(void) +{ + const struct dmi_system_id *dmi_match; + + dmi_match = dmi_first_match(exar_platforms); + if (dmi_match) + return dmi_match->driver_data; + + return &exar8250_default_platform; +} + static int pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev, struct uart_8250_port *port, int idx) { - const struct exar8250_platform *platform; - const struct dmi_system_id *dmi_match; + const struct exar8250_platform *platform = exar_get_platform(); unsigned int offset = idx * 0x400; unsigned int baud = 7812500; u8 __iomem *p; int ret; - dmi_match = dmi_first_match(exar_platforms); - if (dmi_match) - platform = dmi_match->driver_data; - else - platform = &exar8250_default_platform; - port->port.uartclk = baud * 16; port->port.rs485_config = platform->rs485_config; diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 0b077b45d6a9..bce28729dd7b 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -192,6 +192,10 @@ static int of_platform_serial_probe(struct platform_device *ofdev) u32 tx_threshold; int ret; + if (IS_ENABLED(CONFIG_SERIAL_8250_BCM7271) && + of_device_is_compatible(ofdev->dev.of_node, "brcm,bcm7271-uart")) + return -ENODEV; + port_type = (unsigned long)of_device_get_match_data(&ofdev->dev); if (port_type == PORT_UNKNOWN) return -EINVAL; diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 8ac11eaeca51..79418d4beb48 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -43,6 +43,7 @@ #define UART_ERRATA_CLOCK_DISABLE (1 << 3) #define UART_HAS_EFR2 BIT(4) #define UART_HAS_RHR_IT_DIS BIT(5) +#define UART_RX_TIMEOUT_QUIRK BIT(6) #define OMAP_UART_FCR_RX_TRIG 6 #define OMAP_UART_FCR_TX_TRIG 4 @@ -104,6 +105,9 @@ #define UART_OMAP_EFR2 0x23 #define UART_OMAP_EFR2_TIMEOUT_BEHAVE BIT(6) +/* RX FIFO occupancy indicator */ +#define UART_OMAP_RX_LVL 0x64 + struct omap8250_priv { int line; u8 habit; @@ -611,6 +615,7 @@ static int omap_8250_dma_handle_irq(struct uart_port *port); static irqreturn_t omap8250_irq(int irq, void *dev_id) { struct uart_port *port = dev_id; + struct omap8250_priv *priv = port->private_data; struct uart_8250_port *up = up_to_u8250p(port); unsigned int iir; int ret; @@ -625,6 +630,18 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id) serial8250_rpm_get(up); iir = serial_port_in(port, UART_IIR); ret = serial8250_handle_irq(port, iir); + + /* + * On K3 SoCs, it is observed that RX TIMEOUT is signalled after + * FIFO has been drained, in which case a dummy read of RX FIFO + * is required to clear RX TIMEOUT condition. + */ + if (priv->habit & UART_RX_TIMEOUT_QUIRK && + (iir & UART_IIR_RX_TIMEOUT) == UART_IIR_RX_TIMEOUT && + serial_port_in(port, UART_OMAP_RX_LVL) == 0) { + serial_port_in(port, UART_RX); + } + serial8250_rpm_put(up); return IRQ_RETVAL(ret); @@ -813,7 +830,7 @@ static void __dma_rx_do_complete(struct uart_8250_port *p) poll_count--) cpu_relax(); - if (!poll_count) + if (poll_count == -1) dev_err(p->port.dev, "teardown incomplete\n"); } } @@ -1218,7 +1235,8 @@ static struct omap8250_dma_params am33xx_dma = { static struct omap8250_platdata am654_platdata = { .dma_params = &am654_dma, - .habit = UART_HAS_EFR2 | UART_HAS_RHR_IT_DIS, + .habit = UART_HAS_EFR2 | UART_HAS_RHR_IT_DIS | + UART_RX_TIMEOUT_QUIRK, }; static struct omap8250_platdata am33xx_platdata = { diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 780cc99732b6..75827b608fdb 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -2851,7 +2851,7 @@ enum pci_board_num_t { pbn_b0_2_1843200, pbn_b0_4_1843200, - pbn_b0_1_4000000, + pbn_b0_1_3906250, pbn_b0_bt_1_115200, pbn_b0_bt_2_115200, @@ -2931,10 +2931,10 @@ enum pci_board_num_t { pbn_plx_romulus, pbn_endrun_2_4000000, pbn_oxsemi, - pbn_oxsemi_1_4000000, - pbn_oxsemi_2_4000000, - pbn_oxsemi_4_4000000, - pbn_oxsemi_8_4000000, + pbn_oxsemi_1_3906250, + pbn_oxsemi_2_3906250, + pbn_oxsemi_4_3906250, + pbn_oxsemi_8_3906250, pbn_intel_i960, pbn_sgi_ioc3, pbn_computone_4, @@ -2972,6 +2972,10 @@ enum pci_board_num_t { pbn_sunix_pci_4s, pbn_sunix_pci_8s, pbn_sunix_pci_16s, + pbn_titan_1_4000000, + pbn_titan_2_4000000, + pbn_titan_4_4000000, + pbn_titan_8_4000000, pbn_moxa8250_2p, pbn_moxa8250_4p, pbn_moxa8250_8p, @@ -3077,10 +3081,10 @@ static struct pciserial_board pci_boards[] = { .uart_offset = 8, }, - [pbn_b0_1_4000000] = { + [pbn_b0_1_3906250] = { .flags = FL_BASE0, .num_ports = 1, - .base_baud = 4000000, + .base_baud = 3906250, .uart_offset = 8, }, @@ -3475,31 +3479,31 @@ static struct pciserial_board pci_boards[] = { .base_baud = 115200, .uart_offset = 8, }, - [pbn_oxsemi_1_4000000] = { + [pbn_oxsemi_1_3906250] = { .flags = FL_BASE0, .num_ports = 1, - .base_baud = 4000000, + .base_baud = 3906250, .uart_offset = 0x200, .first_offset = 0x1000, }, - [pbn_oxsemi_2_4000000] = { + [pbn_oxsemi_2_3906250] = { .flags = FL_BASE0, .num_ports = 2, - .base_baud = 4000000, + .base_baud = 3906250, .uart_offset = 0x200, .first_offset = 0x1000, }, - [pbn_oxsemi_4_4000000] = { + [pbn_oxsemi_4_3906250] = { .flags = FL_BASE0, .num_ports = 4, - .base_baud = 4000000, + .base_baud = 3906250, .uart_offset = 0x200, .first_offset = 0x1000, }, - [pbn_oxsemi_8_4000000] = { + [pbn_oxsemi_8_3906250] = { .flags = FL_BASE0, .num_ports = 8, - .base_baud = 4000000, + .base_baud = 3906250, .uart_offset = 0x200, .first_offset = 0x1000, }, @@ -3759,6 +3763,34 @@ static struct pciserial_board pci_boards[] = { .base_baud = 921600, .uart_offset = 0x8, }, + [pbn_titan_1_4000000] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 4000000, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, + [pbn_titan_2_4000000] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 4000000, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, + [pbn_titan_4_4000000] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 4000000, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, + [pbn_titan_8_4000000] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 4000000, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, [pbn_moxa8250_2p] = { .flags = FL_BASE1, .num_ports = 2, @@ -4478,158 +4510,158 @@ static const struct pci_device_id serial_pci_tbl[] = { */ { PCI_VENDOR_ID_OXSEMI, 0xc101, /* OXPCIe952 1 Legacy UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_4000000 }, + pbn_b0_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc105, /* OXPCIe952 1 Legacy UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_4000000 }, + pbn_b0_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc11b, /* OXPCIe952 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc11f, /* OXPCIe952 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc120, /* OXPCIe952 1 Legacy UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_4000000 }, + pbn_b0_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc124, /* OXPCIe952 1 Legacy UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_4000000 }, + pbn_b0_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc138, /* OXPCIe952 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc13d, /* OXPCIe952 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc140, /* OXPCIe952 1 Legacy UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_4000000 }, + pbn_b0_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc141, /* OXPCIe952 1 Legacy UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_4000000 }, + pbn_b0_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc144, /* OXPCIe952 1 Legacy UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_4000000 }, + pbn_b0_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc145, /* OXPCIe952 1 Legacy UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_4000000 }, + pbn_b0_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc158, /* OXPCIe952 2 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_2_4000000 }, + pbn_oxsemi_2_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc15d, /* OXPCIe952 2 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_2_4000000 }, + pbn_oxsemi_2_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc208, /* OXPCIe954 4 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_4_4000000 }, + pbn_oxsemi_4_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc20d, /* OXPCIe954 4 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_4_4000000 }, + pbn_oxsemi_4_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc308, /* OXPCIe958 8 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_8_4000000 }, + pbn_oxsemi_8_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc30d, /* OXPCIe958 8 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_8_4000000 }, + pbn_oxsemi_8_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc40b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc40f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc41b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc41f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc42b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc42f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc43b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc43f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc44b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc44f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc45b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc45f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc46b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc46f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc47b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc47f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc48b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc48f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc49b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc49f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc4ab, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc4af, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc4bb, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc4bf, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc4cb, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_OXSEMI, 0xc4cf, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, /* * Mainpine Inc. IQ Express "Rev3" utilizing OxSemi Tornado */ { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 1 Port V.34 Super-G3 Fax */ PCI_VENDOR_ID_MAINPINE, 0x4001, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_oxsemi_1_3906250 }, { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 2 Port V.34 Super-G3 Fax */ PCI_VENDOR_ID_MAINPINE, 0x4002, 0, 0, - pbn_oxsemi_2_4000000 }, + pbn_oxsemi_2_3906250 }, { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 4 Port V.34 Super-G3 Fax */ PCI_VENDOR_ID_MAINPINE, 0x4004, 0, 0, - pbn_oxsemi_4_4000000 }, + pbn_oxsemi_4_3906250 }, { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */ PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0, - pbn_oxsemi_8_4000000 }, + pbn_oxsemi_8_3906250 }, /* * Digi/IBM PCIe 2-port Async EIA-232 Adapter utilizing OxSemi Tornado */ { PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM, PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0, - pbn_oxsemi_2_4000000 }, + pbn_oxsemi_2_3906250 }, /* * SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards, @@ -4703,22 +4735,22 @@ static const struct pci_device_id serial_pci_tbl[] = { pbn_b0_4_921600 }, { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_4000000 }, + pbn_titan_1_4000000 }, { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_2_4000000 }, + pbn_titan_2_4000000 }, { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_4_4000000 }, + pbn_titan_4_4000000 }, { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_8_4000000 }, + pbn_titan_8_4000000 }, { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EI, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_2_4000000 }, + pbn_titan_2_4000000 }, { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EISI, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_2_4000000 }, + pbn_titan_2_4000000 }, { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200V3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_2_921600 }, diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index fc5ab2032282..2164290cbd31 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2512,19 +2512,45 @@ static unsigned int serial8250_do_get_divisor(struct uart_port *port, unsigned int baud, unsigned int *frac) { + upf_t magic_multiplier = port->flags & UPF_MAGIC_MULTIPLIER; struct uart_8250_port *up = up_to_u8250p(port); unsigned int quot; /* - * Handle magic divisors for baud rates above baud_base on - * SMSC SuperIO chips. + * Handle magic divisors for baud rates above baud_base on SMSC + * Super I/O chips. We clamp custom rates from clk/6 and clk/12 + * up to clk/4 (0x8001) and clk/8 (0x8002) respectively. These + * magic divisors actually reprogram the baud rate generator's + * reference clock derived from chips's 14.318MHz clock input. * + * Documentation claims that with these magic divisors the base + * frequencies of 7.3728MHz and 3.6864MHz are used respectively + * for the extra baud rates of 460800bps and 230400bps rather + * than the usual base frequency of 1.8462MHz. However empirical + * evidence contradicts that. + * + * Instead bit 7 of the DLM register (bit 15 of the divisor) is + * effectively used as a clock prescaler selection bit for the + * base frequency of 7.3728MHz, always used. If set to 0, then + * the base frequency is divided by 4 for use by the Baud Rate + * Generator, for the usual arrangement where the value of 1 of + * the divisor produces the baud rate of 115200bps. Conversely, + * if set to 1 and high-speed operation has been enabled with the + * Serial Port Mode Register in the Device Configuration Space, + * then the base frequency is supplied directly to the Baud Rate + * Generator, so for the divisor values of 0x8001, 0x8002, 0x8003, + * 0x8004, etc. the respective baud rates produced are 460800bps, + * 230400bps, 153600bps, 115200bps, etc. + * + * In all cases only low 15 bits of the divisor are used to divide + * the baud base and therefore 32767 is the maximum divisor value + * possible, even though documentation says that the programmable + * Baud Rate Generator is capable of dividing the internal PLL + * clock by any divisor from 1 to 65535. */ - if ((port->flags & UPF_MAGIC_MULTIPLIER) && - baud == (port->uartclk/4)) + if (magic_multiplier && baud >= port->uartclk / 6) quot = 0x8001; - else if ((port->flags & UPF_MAGIC_MULTIPLIER) && - baud == (port->uartclk/8)) + else if (magic_multiplier && baud >= port->uartclk / 12) quot = 0x8002; else if (up->port.type == PORT_NPCM) quot = npcm_get_divisor(up, baud); @@ -2629,6 +2655,21 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port, struct ktermios *old) { unsigned int tolerance = port->uartclk / 100; + unsigned int min; + unsigned int max; + + /* + * Handle magic divisors for baud rates above baud_base on SMSC + * Super I/O chips. Enable custom rates of clk/4 and clk/8, but + * disable divisor values beyond 32767, which are unavailable. + */ + if (port->flags & UPF_MAGIC_MULTIPLIER) { + min = port->uartclk / 16 / UART_DIV_MAX >> 1; + max = (port->uartclk + tolerance) / 4; + } else { + min = port->uartclk / 16 / UART_DIV_MAX; + max = (port->uartclk + tolerance) / 16; + } /* * Ask the core to calculate the divisor for us. @@ -2636,9 +2677,7 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port, * slower than nominal still match standard baud rates without * causing transmission errors. */ - return uart_get_baud_rate(port, termios, old, - port->uartclk / 16 / UART_DIV_MAX, - (port->uartclk + tolerance) / 16); + return uart_get_baud_rate(port, termios, old, min, max); } /* diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c index 63ea9c4da3d5..dc2ef05a10eb 100644 --- a/drivers/tty/serial/8250/serial_cs.c +++ b/drivers/tty/serial/8250/serial_cs.c @@ -306,6 +306,7 @@ static int serial_resume(struct pcmcia_device *link) static int serial_probe(struct pcmcia_device *link) { struct serial_info *info; + int ret; dev_dbg(&link->dev, "serial_attach()\n"); @@ -320,7 +321,15 @@ static int serial_probe(struct pcmcia_device *link) if (do_sound) link->config_flags |= CONF_ENABLE_SPKR; - return serial_config(link); + ret = serial_config(link); + if (ret) + goto free_info; + + return 0; + +free_info: + kfree(info); + return ret; } static void serial_detach(struct pcmcia_device *link) @@ -777,6 +786,7 @@ static const struct pcmcia_device_id serial_ids[] = { PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT2834LT", 0x5f73be51, 0x4cd7c09e), PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a), PCMCIA_DEVICE_PROD_ID12("Option International", "V34bis GSM/PSTN Data/Fax Modem", 0x9d7cd6f5, 0x5cb8bf41), + PCMCIA_DEVICE_PROD_ID12("Option International", "GSM-Ready 56K/ISDN", 0x9d7cd6f5, 0xb23844aa), PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab), PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f), PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d), @@ -804,7 +814,6 @@ static const struct pcmcia_device_id serial_ids[] = { PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "cis/COMpad4.cis"), PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "cis/COMpad2.cis"), PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "cis/RS-COM-2P.cis"), - PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "cis/GLOBETROTTER.cis"), PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL100 1.00.", 0x19ca78af, 0xf964f42b), PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL100", 0x19ca78af, 0x71d98e83), PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL232 1.00.", 0x19ca78af, 0x69fb7490), diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 682f9171c82c..24282ad99d85 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1553,6 +1553,7 @@ config SERIAL_LITEUART_CONSOLE bool "LiteUART serial port console support" depends on SERIAL_LITEUART=y select SERIAL_CORE_CONSOLE + select SERIAL_EARLYCON help Say 'Y' or 'M' here if you wish to use the FPGA-based LiteUART serial controller from LiteX SoC builder as the system console diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 78682c12156a..e14f3378b8a0 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1062,7 +1062,7 @@ static void pl011_dma_rx_poll(struct timer_list *t) struct tty_port *port = &uap->port.state->port; struct pl011_dmarx_data *dmarx = &uap->dmarx; struct dma_chan *rxchan = uap->dmarx.chan; - unsigned long flags = 0; + unsigned long flags; unsigned int dmataken = 0; unsigned int size = 0; struct pl011_sgbuf *sgbuf; diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c index 1a9444b6b57e..596217d10d5c 100644 --- a/drivers/tty/serial/arc_uart.c +++ b/drivers/tty/serial/arc_uart.c @@ -149,7 +149,7 @@ static unsigned int arc_serial_tx_empty(struct uart_port *port) /* * Driver internal routine, used by both tty(serial core) as well as tx-isr * -Called under spinlock in either cases - * -also tty->stopped has already been checked + * -also tty->flow.stopped has already been checked * = by uart_start( ) before calling us * = tx_ist checks that too before calling */ diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 058886d9045b..249ea35088d2 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -30,9 +30,9 @@ #include <linux/irq.h> #include <linux/suspend.h> #include <linux/mm.h> +#include <linux/io.h> #include <asm/div64.h> -#include <asm/io.h> #include <asm/ioctls.h> #define PDC_BUFFER_SIZE 512 diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c index 58aaa533203b..c719aa2b1832 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c @@ -524,24 +524,7 @@ static void cpm_uart_set_termios(struct uart_port *port, scval = 0; /* byte size */ - switch (termios->c_cflag & CSIZE) { - case CS5: - bits = 5; - break; - case CS6: - bits = 6; - break; - case CS7: - bits = 7; - break; - case CS8: - bits = 8; - break; - /* Never happens, but GCC is too dumb to figure it out */ - default: - bits = 8; - break; - } + bits = tty_get_char_size(termios->c_cflag); sbits = bits - 5; if (termios->c_cflag & CSTOPB) { diff --git a/drivers/tty/serial/dz.c b/drivers/tty/serial/dz.c index 4552742c3859..e9edabc5a211 100644 --- a/drivers/tty/serial/dz.c +++ b/drivers/tty/serial/dz.c @@ -47,8 +47,8 @@ #include <linux/tty_flip.h> #include <linux/atomic.h> +#include <linux/io.h> #include <asm/bootinfo.h> -#include <asm/io.h> #include <asm/dec/interrupts.h> #include <asm/dec/kn01.h> @@ -115,7 +115,7 @@ static void dz_out(struct dz_port *dport, unsigned offset, u16 value) * rs_stop () and rs_start () * * These routines are called before setting or resetting - * tty->stopped. They enable or disable transmitter interrupts, + * tty->flow.stopped. They enable or disable transmitter interrupts, * as necessary. * ------------------------------------------------------------ */ diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 794035041744..508128ddfa01 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -824,21 +824,18 @@ static unsigned int lpuart32_tx_empty(struct uart_port *port) static void lpuart_txint(struct lpuart_port *sport) { - unsigned long flags; - - spin_lock_irqsave(&sport->port.lock, flags); + spin_lock(&sport->port.lock); lpuart_transmit_buffer(sport); - spin_unlock_irqrestore(&sport->port.lock, flags); + spin_unlock(&sport->port.lock); } static void lpuart_rxint(struct lpuart_port *sport) { unsigned int flg, ignored = 0, overrun = 0; struct tty_port *port = &sport->port.state->port; - unsigned long flags; unsigned char rx, sr; - spin_lock_irqsave(&sport->port.lock, flags); + spin_lock(&sport->port.lock); while (!(readb(sport->port.membase + UARTSFIFO) & UARTSFIFO_RXEMPT)) { flg = TTY_NORMAL; @@ -850,7 +847,7 @@ static void lpuart_rxint(struct lpuart_port *sport) sr = readb(sport->port.membase + UARTSR1); rx = readb(sport->port.membase + UARTDR); - if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx)) + if (uart_prepare_sysrq_char(&sport->port, rx)) continue; if (sr & (UARTSR1_PE | UARTSR1_OR | UARTSR1_FE)) { @@ -896,28 +893,26 @@ out: writeb(UARTSFIFO_RXOF, sport->port.membase + UARTSFIFO); } - spin_unlock_irqrestore(&sport->port.lock, flags); + uart_unlock_and_check_sysrq(&sport->port); tty_flip_buffer_push(port); } static void lpuart32_txint(struct lpuart_port *sport) { - unsigned long flags; - - spin_lock_irqsave(&sport->port.lock, flags); + spin_lock(&sport->port.lock); lpuart32_transmit_buffer(sport); - spin_unlock_irqrestore(&sport->port.lock, flags); + spin_unlock(&sport->port.lock); } static void lpuart32_rxint(struct lpuart_port *sport) { unsigned int flg, ignored = 0; struct tty_port *port = &sport->port.state->port; - unsigned long flags; unsigned long rx, sr; + bool is_break; - spin_lock_irqsave(&sport->port.lock, flags); + spin_lock(&sport->port.lock); while (!(lpuart32_read(&sport->port, UARTFIFO) & UARTFIFO_RXEMPT)) { flg = TTY_NORMAL; @@ -928,16 +923,29 @@ static void lpuart32_rxint(struct lpuart_port *sport) */ sr = lpuart32_read(&sport->port, UARTSTAT); rx = lpuart32_read(&sport->port, UARTDATA); - rx &= 0x3ff; + rx &= UARTDATA_MASK; + + /* + * The LPUART can't distinguish between a break and a framing error, + * thus we assume it is a break if the received data is zero. + */ + is_break = (sr & UARTSTAT_FE) && !rx; - if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx)) + if (is_break && uart_handle_break(&sport->port)) + continue; + + if (uart_prepare_sysrq_char(&sport->port, rx)) continue; if (sr & (UARTSTAT_PE | UARTSTAT_OR | UARTSTAT_FE)) { - if (sr & UARTSTAT_PE) - sport->port.icount.parity++; - else if (sr & UARTSTAT_FE) + if (sr & UARTSTAT_PE) { + if (is_break) + sport->port.icount.brk++; + else + sport->port.icount.parity++; + } else if (sr & UARTSTAT_FE) { sport->port.icount.frame++; + } if (sr & UARTSTAT_OR) sport->port.icount.overrun++; @@ -950,22 +958,24 @@ static void lpuart32_rxint(struct lpuart_port *sport) sr &= sport->port.read_status_mask; - if (sr & UARTSTAT_PE) - flg = TTY_PARITY; - else if (sr & UARTSTAT_FE) + if (sr & UARTSTAT_PE) { + if (is_break) + flg = TTY_BREAK; + else + flg = TTY_PARITY; + } else if (sr & UARTSTAT_FE) { flg = TTY_FRAME; + } if (sr & UARTSTAT_OR) flg = TTY_OVERRUN; - - sport->port.sysrq = 0; } tty_insert_flip_char(port, rx, flg); } out: - spin_unlock_irqrestore(&sport->port.lock, flags); + uart_unlock_and_check_sysrq(&sport->port); tty_flip_buffer_push(port); } @@ -1393,58 +1403,54 @@ static int lpuart32_config_rs485(struct uart_port *port, static unsigned int lpuart_get_mctrl(struct uart_port *port) { - unsigned int temp = 0; - unsigned char reg; - - reg = readb(port->membase + UARTMODEM); - if (reg & UARTMODEM_TXCTSE) - temp |= TIOCM_CTS; + unsigned int mctrl = 0; + u8 reg; - if (reg & UARTMODEM_RXRTSE) - temp |= TIOCM_RTS; + reg = readb(port->membase + UARTCR1); + if (reg & UARTCR1_LOOPS) + mctrl |= TIOCM_LOOP; - return temp; + return mctrl; } static unsigned int lpuart32_get_mctrl(struct uart_port *port) { - unsigned int temp = 0; - unsigned long reg; - - reg = lpuart32_read(port, UARTMODIR); - if (reg & UARTMODIR_TXCTSE) - temp |= TIOCM_CTS; + unsigned int mctrl = 0; + u32 reg; - if (reg & UARTMODIR_RXRTSE) - temp |= TIOCM_RTS; + reg = lpuart32_read(port, UARTCTRL); + if (reg & UARTCTRL_LOOPS) + mctrl |= TIOCM_LOOP; - return temp; + return mctrl; } static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl) { - unsigned char temp; - struct lpuart_port *sport = container_of(port, - struct lpuart_port, port); + u8 reg; - /* Make sure RXRTSE bit is not set when RS485 is enabled */ - if (!(sport->port.rs485.flags & SER_RS485_ENABLED)) { - temp = readb(sport->port.membase + UARTMODEM) & - ~(UARTMODEM_RXRTSE | UARTMODEM_TXCTSE); + reg = readb(port->membase + UARTCR1); - if (mctrl & TIOCM_RTS) - temp |= UARTMODEM_RXRTSE; + /* for internal loopback we need LOOPS=1 and RSRC=0 */ + reg &= ~(UARTCR1_LOOPS | UARTCR1_RSRC); + if (mctrl & TIOCM_LOOP) + reg |= UARTCR1_LOOPS; - if (mctrl & TIOCM_CTS) - temp |= UARTMODEM_TXCTSE; - - writeb(temp, port->membase + UARTMODEM); - } + writeb(reg, port->membase + UARTCR1); } static void lpuart32_set_mctrl(struct uart_port *port, unsigned int mctrl) { + u32 reg; + + reg = lpuart32_read(port, UARTCTRL); + /* for internal loopback we need LOOPS=1 and RSRC=0 */ + reg &= ~(UARTCTRL_LOOPS | UARTCTRL_RSRC); + if (mctrl & TIOCM_LOOP) + reg |= UARTCTRL_LOOPS; + + lpuart32_write(port, reg, UARTCTRL); } static void lpuart_break_ctl(struct uart_port *port, int break_state) @@ -1581,6 +1587,9 @@ static void lpuart_tx_dma_startup(struct lpuart_port *sport) u32 uartbaud; int ret; + if (uart_console(&sport->port)) + goto err; + if (!sport->dma_tx_chan) goto err; @@ -1610,6 +1619,9 @@ static void lpuart_rx_dma_startup(struct lpuart_port *sport) int ret; unsigned char cr3; + if (uart_console(&sport->port)) + goto err; + if (!sport->dma_rx_chan) goto err; @@ -1625,7 +1637,7 @@ static void lpuart_rx_dma_startup(struct lpuart_port *sport) sport->lpuart_dma_rx_use = true; rx_dma_timer_init(sport); - if (sport->port.has_sysrq) { + if (sport->port.has_sysrq && !lpuart_is_32(sport)) { cr3 = readb(sport->port.membase + UARTCR3); cr3 |= UARTCR3_FEIE; writeb(cr3, sport->port.membase + UARTCR3); @@ -2278,7 +2290,7 @@ lpuart_console_write(struct console *co, const char *s, unsigned int count) unsigned long flags; int locked = 1; - if (sport->port.sysrq || oops_in_progress) + if (oops_in_progress) locked = spin_trylock_irqsave(&sport->port.lock, flags); else spin_lock_irqsave(&sport->port.lock, flags); @@ -2308,7 +2320,7 @@ lpuart32_console_write(struct console *co, const char *s, unsigned int count) unsigned long flags; int locked = 1; - if (sport->port.sysrq || oops_in_progress) + if (oops_in_progress) locked = spin_trylock_irqsave(&sport->port.lock, flags); else spin_lock_irqsave(&sport->port.lock, flags); @@ -2414,6 +2426,9 @@ lpuart32_console_get_options(struct lpuart_port *sport, int *baud, bd = lpuart32_read(&sport->port, UARTBAUD); bd &= UARTBAUD_SBR_MASK; + if (!bd) + return; + sbr = bd; uartclk = lpuart_get_baud_clk_rate(sport); /* diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c index 9e9abfc4824a..03a2fe9f4c9a 100644 --- a/drivers/tty/serial/icom.c +++ b/drivers/tty/serial/icom.c @@ -37,7 +37,7 @@ #include <linux/firmware.h> #include <linux/bitops.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/irq.h> #include <linux/uaccess.h> diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 7d5a8dfa3e91..8b121cd869e9 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -225,6 +225,8 @@ struct imx_port { struct scatterlist rx_sgl, tx_sgl[2]; void *rx_buf; struct circ_buf rx_ring; + unsigned int rx_buf_size; + unsigned int rx_period_length; unsigned int rx_periods; dma_cookie_t rx_cookie; unsigned int tx_bytes; @@ -1183,10 +1185,6 @@ static void imx_uart_dma_rx_callback(void *data) } } -/* RX DMA buffer periods */ -#define RX_DMA_PERIODS 16 -#define RX_BUF_SIZE (RX_DMA_PERIODS * PAGE_SIZE / 4) - static int imx_uart_start_rx_dma(struct imx_port *sport) { struct scatterlist *sgl = &sport->rx_sgl; @@ -1197,9 +1195,8 @@ static int imx_uart_start_rx_dma(struct imx_port *sport) sport->rx_ring.head = 0; sport->rx_ring.tail = 0; - sport->rx_periods = RX_DMA_PERIODS; - sg_init_one(sgl, sport->rx_buf, RX_BUF_SIZE); + sg_init_one(sgl, sport->rx_buf, sport->rx_buf_size); ret = dma_map_sg(dev, sgl, 1, DMA_FROM_DEVICE); if (ret == 0) { dev_err(dev, "DMA mapping error for RX.\n"); @@ -1316,7 +1313,8 @@ static int imx_uart_dma_init(struct imx_port *sport) goto err; } - sport->rx_buf = kzalloc(RX_BUF_SIZE, GFP_KERNEL); + sport->rx_buf_size = sport->rx_period_length * sport->rx_periods; + sport->rx_buf = kzalloc(sport->rx_buf_size, GFP_KERNEL); if (!sport->rx_buf) { ret = -ENOMEM; goto err; @@ -1975,8 +1973,8 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count) { struct imx_port *sport = imx_uart_ports[co->index]; struct imx_port_ucrs old_ucr; + unsigned long flags; unsigned int ucr1; - unsigned long flags = 0; int locked = 1; if (sport->port.sysrq) @@ -2179,11 +2177,16 @@ static enum hrtimer_restart imx_trigger_stop_tx(struct hrtimer *t) return HRTIMER_NORESTART; } +/* Default RX DMA buffer configuration */ +#define RX_DMA_PERIODS 16 +#define RX_DMA_PERIOD_LEN (PAGE_SIZE / 4) + static int imx_uart_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct imx_port *sport; void __iomem *base; + u32 dma_buf_conf[2]; int ret = 0; u32 ucr1; struct resource *res; @@ -2218,6 +2221,14 @@ static int imx_uart_probe(struct platform_device *pdev) if (of_get_property(np, "fsl,inverted-rx", NULL)) sport->inverted_rx = 1; + if (!of_property_read_u32_array(np, "fsl,dma-info", dma_buf_conf, 2)) { + sport->rx_period_length = dma_buf_conf[0]; + sport->rx_periods = dma_buf_conf[1]; + } else { + sport->rx_period_length = RX_DMA_PERIOD_LEN; + sport->rx_periods = RX_DMA_PERIODS; + } + if (sport->port.line >= ARRAY_SIZE(imx_uart_ports)) { dev_err(&pdev->dev, "serial%d out of range\n", sport->port.line); diff --git a/drivers/tty/serial/ip22zilog.c b/drivers/tty/serial/ip22zilog.c index 86fff69d7e7c..f4dc5fe4ba92 100644 --- a/drivers/tty/serial/ip22zilog.c +++ b/drivers/tty/serial/ip22zilog.c @@ -31,7 +31,7 @@ #include <linux/spinlock.h> #include <linux/init.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/irq.h> #include <asm/sgialib.h> #include <asm/sgi/ioc.h> diff --git a/drivers/tty/serial/kgdb_nmi.c b/drivers/tty/serial/kgdb_nmi.c index db059b66438e..3e7c6ee8e4b3 100644 --- a/drivers/tty/serial/kgdb_nmi.c +++ b/drivers/tty/serial/kgdb_nmi.c @@ -115,7 +115,7 @@ static void kgdb_tty_recv(int ch) static int kgdb_nmi_poll_one_knock(void) { static int n; - int c = -1; + int c; const char *magic = kgdb_nmi_magic; size_t m = strlen(magic); bool printch = false; @@ -298,7 +298,7 @@ static void kgdb_nmi_tty_hangup(struct tty_struct *tty) tty_port_hangup(&priv->port); } -static int kgdb_nmi_tty_write_room(struct tty_struct *tty) +static unsigned int kgdb_nmi_tty_write_room(struct tty_struct *tty) { /* Actually, we can handle any amount as we use polled writes. */ return 2048; diff --git a/drivers/tty/serial/liteuart.c b/drivers/tty/serial/liteuart.c index 0b06770642cb..dbc0559a9157 100644 --- a/drivers/tty/serial/liteuart.c +++ b/drivers/tty/serial/liteuart.c @@ -370,6 +370,27 @@ static int __init liteuart_console_init(void) return 0; } console_initcall(liteuart_console_init); + +static void early_liteuart_write(struct console *console, const char *s, + unsigned int count) +{ + struct earlycon_device *device = console->data; + struct uart_port *port = &device->port; + + uart_console_write(port, s, count, liteuart_putchar); +} + +static int __init early_liteuart_setup(struct earlycon_device *device, + const char *options) +{ + if (!device->port.membase) + return -ENODEV; + + device->con->write = early_liteuart_write; + return 0; +} + +OF_EARLYCON_DECLARE(liteuart, "litex,liteuart", early_liteuart_setup); #endif /* CONFIG_SERIAL_LITEUART_CONSOLE */ static int __init liteuart_init(void) diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 3cbc757d7be7..0c1e4df52215 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -552,7 +552,7 @@ static int max310x_update_best_err(unsigned long f, long *besterr) return 1; } -static int max310x_set_ref_clk(struct device *dev, struct max310x_port *s, +static u32 max310x_set_ref_clk(struct device *dev, struct max310x_port *s, unsigned long freq, bool xtal) { unsigned int div, clksrc, pllcfg = 0; @@ -618,7 +618,7 @@ static int max310x_set_ref_clk(struct device *dev, struct max310x_port *s, } } - return (int)bestfreq; + return bestfreq; } static void max310x_batch_write(struct uart_port *port, u8 *txbuf, unsigned int len) @@ -1253,9 +1253,10 @@ static int max310x_gpio_set_config(struct gpio_chip *chip, unsigned int offset, static int max310x_probe(struct device *dev, const struct max310x_devtype *devtype, struct regmap *regmap, int irq) { - int i, ret, fmin, fmax, freq, uartclk; + int i, ret, fmin, fmax, freq; struct max310x_port *s; - bool xtal = false; + u32 uartclk = 0; + bool xtal; if (IS_ERR(regmap)) return PTR_ERR(regmap); @@ -1267,24 +1268,20 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty return -ENOMEM; } + /* Always ask for fixed clock rate from a property. */ + device_property_read_u32(dev, "clock-frequency", &uartclk); + s->clk = devm_clk_get_optional(dev, "osc"); if (IS_ERR(s->clk)) return PTR_ERR(s->clk); if (s->clk) { - fmin = 500000; - fmax = 35000000; + xtal = false; } else { s->clk = devm_clk_get_optional(dev, "xtal"); if (IS_ERR(s->clk)) return PTR_ERR(s->clk); - if (s->clk) { - fmin = 1000000; - fmax = 4000000; - xtal = true; - } else { - dev_err(dev, "Cannot get clock\n"); - return -EINVAL; - } + + xtal = true; } ret = clk_prepare_enable(s->clk); @@ -1292,6 +1289,21 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty return ret; freq = clk_get_rate(s->clk); + if (freq == 0) + freq = uartclk; + if (freq == 0) { + dev_err(dev, "Cannot get clock rate\n"); + return -EINVAL; + } + + if (xtal) { + fmin = 1000000; + fmax = 4000000; + } else { + fmin = 500000; + fmax = 35000000; + } + /* Check frequency limits */ if (freq < fmin || freq > fmax) { ret = -ERANGE; diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index 529cd0289056..efee3935917f 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -715,13 +715,15 @@ static int meson_uart_probe(struct platform_device *pdev) { struct resource *res_mem, *res_irq; struct uart_port *port; + u32 fifosize = 64; /* Default is 64, 128 for EE UART_0 */ int ret = 0; - int id = -1; if (pdev->dev.of_node) pdev->id = of_alias_get_id(pdev->dev.of_node, "serial"); if (pdev->id < 0) { + int id; + for (id = AML_UART_PORT_OFFSET; id < AML_UART_PORT_NUM; id++) { if (!meson_ports[id]) { pdev->id = id; @@ -741,6 +743,8 @@ static int meson_uart_probe(struct platform_device *pdev) if (!res_irq) return -ENODEV; + of_property_read_u32(pdev->dev.of_node, "fifo-size", &fifosize); + if (meson_ports[pdev->id]) { dev_err(&pdev->dev, "port %d already allocated\n", pdev->id); return -EBUSY; @@ -770,7 +774,7 @@ static int meson_uart_probe(struct platform_device *pdev) port->type = PORT_MESON; port->x_char = 0; port->ops = &meson_uart_ops; - port->fifosize = 64; + port->fifosize = fifosize; meson_ports[pdev->id] = port; platform_set_drvdata(pdev, port); diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c index 47ab280f553b..be640d9863cd 100644 --- a/drivers/tty/serial/mux.c +++ b/drivers/tty/serial/mux.c @@ -21,7 +21,7 @@ #include <linux/console.h> #include <linux/delay.h> /* for udelay */ #include <linux/device.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/irq.h> #include <asm/parisc-device.h> diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c index 51b0ecabf2ec..231de29a6452 100644 --- a/drivers/tty/serial/mvebu-uart.c +++ b/drivers/tty/serial/mvebu-uart.c @@ -128,7 +128,6 @@ struct mvebu_uart { struct uart_port *port; struct clk *clk; int irq[UART_IRQ_COUNT]; - unsigned char __iomem *nb; struct mvebu_uart_driver_data *data; #if defined(CONFIG_PM) struct mvebu_uart_pm_regs pm_regs; @@ -445,12 +444,11 @@ static void mvebu_uart_shutdown(struct uart_port *port) static int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned int baud) { - struct mvebu_uart *mvuart = to_mvuart(port); unsigned int d_divisor, m_divisor; u32 brdv, osamp; - if (IS_ERR(mvuart->clk)) - return -PTR_ERR(mvuart->clk); + if (!port->uartclk) + return -EOPNOTSUPP; /* * The baudrate is derived from the UART clock thanks to two divisors: @@ -463,7 +461,7 @@ static int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned int baud) * makes use of D to configure the desired baudrate. */ m_divisor = OSAMP_DEFAULT_DIVISOR; - d_divisor = DIV_ROUND_UP(port->uartclk, baud * m_divisor); + d_divisor = DIV_ROUND_CLOSEST(port->uartclk, baud * m_divisor); brdv = readl(port->membase + UART_BRDV); brdv &= ~BRDV_BAUD_MASK; @@ -482,7 +480,7 @@ static void mvebu_uart_set_termios(struct uart_port *port, struct ktermios *old) { unsigned long flags; - unsigned int baud; + unsigned int baud, min_baud, max_baud; spin_lock_irqsave(&port->lock, flags); @@ -501,16 +499,21 @@ static void mvebu_uart_set_termios(struct uart_port *port, port->ignore_status_mask |= STAT_RX_RDY(port) | STAT_BRK_ERR; /* + * Maximal divisor is 1023 * 16 when using default (x16) scheme. * Maximum achievable frequency with simple baudrate divisor is 230400. * Since the error per bit frame would be of more than 15%, achieving * higher frequencies would require to implement the fractional divisor * feature. */ - baud = uart_get_baud_rate(port, termios, old, 0, 230400); + min_baud = DIV_ROUND_UP(port->uartclk, 1023 * 16); + max_baud = 230400; + + baud = uart_get_baud_rate(port, termios, old, min_baud, max_baud); if (mvebu_uart_baud_rate_set(port, baud)) { /* No clock available, baudrate cannot be changed */ if (old) - baud = uart_get_baud_rate(port, old, NULL, 0, 230400); + baud = uart_get_baud_rate(port, old, NULL, + min_baud, max_baud); } else { tty_termios_encode_baud_rate(termios, baud, baud); uart_update_timeout(port, termios->c_cflag, baud); @@ -617,7 +620,7 @@ static void mvebu_uart_putc(struct uart_port *port, int c) static void mvebu_uart_putc_early_write(struct console *con, const char *s, - unsigned n) + unsigned int n) { struct earlycon_device *dev = con->data; diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index f414d6acad69..ac45f3386e97 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -87,7 +87,7 @@ #define AUART_LINECTRL_BAUD_DIVFRAC(v) (((v) & 0x3f) << 8) #define AUART_LINECTRL_SPS (1 << 7) #define AUART_LINECTRL_WLEN_MASK 0x00000060 -#define AUART_LINECTRL_WLEN(v) (((v) & 0x3) << 5) +#define AUART_LINECTRL_WLEN(v) ((((v) - 5) & 0x3) << 5) #define AUART_LINECTRL_FEN (1 << 4) #define AUART_LINECTRL_STP2 (1 << 3) #define AUART_LINECTRL_EPS (1 << 2) @@ -962,7 +962,7 @@ static void mxs_auart_settermios(struct uart_port *u, struct ktermios *old) { struct mxs_auart_port *s = to_auart_port(u); - u32 bm, ctrl, ctrl2, div; + u32 ctrl, ctrl2, div; unsigned int cflag, baud, baud_min, baud_max; cflag = termios->c_cflag; @@ -970,25 +970,7 @@ static void mxs_auart_settermios(struct uart_port *u, ctrl = AUART_LINECTRL_FEN; ctrl2 = mxs_read(s, REG_CTRL2); - /* byte size */ - switch (cflag & CSIZE) { - case CS5: - bm = 0; - break; - case CS6: - bm = 1; - break; - case CS7: - bm = 2; - break; - case CS8: - bm = 3; - break; - default: - return; - } - - ctrl |= AUART_LINECTRL_WLEN(bm); + ctrl |= AUART_LINECTRL_WLEN(tty_get_char_size(cflag)); /* parity */ if (cflag & PARENB) { @@ -1403,7 +1385,7 @@ auart_console_get_options(struct mxs_auart_port *s, int *baud, *parity = 'o'; } - if ((lcr_h & AUART_LINECTRL_WLEN_MASK) == AUART_LINECTRL_WLEN(2)) + if ((lcr_h & AUART_LINECTRL_WLEN_MASK) == AUART_LINECTRL_WLEN(7)) *bits = 7; else *bits = 8; diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 84e8158088cd..9e81b09ba08e 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -626,7 +626,7 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id) static unsigned int serial_omap_tx_empty(struct uart_port *port) { struct uart_omap_port *up = to_uart_omap_port(port); - unsigned long flags = 0; + unsigned long flags; unsigned int ret = 0; pm_runtime_get_sync(up->dev); @@ -704,7 +704,7 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) static void serial_omap_break_ctl(struct uart_port *port, int break_state) { struct uart_omap_port *up = to_uart_omap_port(port); - unsigned long flags = 0; + unsigned long flags; dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->port.line); pm_runtime_get_sync(up->dev); @@ -722,7 +722,7 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state) static int serial_omap_startup(struct uart_port *port) { struct uart_omap_port *up = to_uart_omap_port(port); - unsigned long flags = 0; + unsigned long flags; int retval; /* @@ -797,7 +797,7 @@ static int serial_omap_startup(struct uart_port *port) static void serial_omap_shutdown(struct uart_port *port) { struct uart_omap_port *up = to_uart_omap_port(port); - unsigned long flags = 0; + unsigned long flags; dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->port.line); @@ -845,7 +845,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, { struct uart_omap_port *up = to_uart_omap_port(port); unsigned char cval = 0; - unsigned long flags = 0; + unsigned long flags; unsigned int baud, quot; switch (termios->c_cflag & CSIZE) { diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index d6aef8a1f0a4..12ce150b0ad4 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -47,7 +47,7 @@ #include <linux/of_address.h> #include <linux/of_irq.h> #include <asm/sections.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/irq.h> #ifdef CONFIG_PPC_PMAC diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 23d729ed3bf6..aedc38893e6c 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -1050,21 +1050,7 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport, } /* bits per char */ - switch (termios->c_cflag & CSIZE) { - case CS5: - bits_per_char = 5; - break; - case CS6: - bits_per_char = 6; - break; - case CS7: - bits_per_char = 7; - break; - case CS8: - default: - bits_per_char = 8; - break; - } + bits_per_char = tty_get_char_size(termios->c_cflag); /* stop bits */ if (termios->c_cflag & CSTOPB) @@ -1338,7 +1324,7 @@ static const struct uart_ops qcom_geni_uart_pops = { static int qcom_geni_serial_probe(struct platform_device *pdev) { int ret = 0; - int line = -1; + int line; struct qcom_geni_serial_port *port; struct uart_port *uport; struct resource *res; @@ -1354,7 +1340,9 @@ static int qcom_geni_serial_probe(struct platform_device *pdev) line = of_alias_get_id(pdev->dev.of_node, "serial"); } else { drv = &qcom_geni_uart_driver; - line = of_alias_get_id(pdev->dev.of_node, "hsuart"); + line = of_alias_get_id(pdev->dev.of_node, "serial"); + if (line == -ENODEV) /* compat with non-standard aliases */ + line = of_alias_get_id(pdev->dev.of_node, "hsuart"); } port = get_port_from_line(line, console); diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c index d9e4b67a12a0..9fbc61151c2e 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -2220,8 +2220,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) default: dev_warn(&pdev->dev, "unsupported reg-io-width (%d)\n", prop); - ret = -EINVAL; - break; + return -EINVAL; } } } diff --git a/drivers/tty/serial/sb1250-duart.c b/drivers/tty/serial/sb1250-duart.c index 22c7bc90b104..738df6d9c0d9 100644 --- a/drivers/tty/serial/sb1250-duart.c +++ b/drivers/tty/serial/sb1250-duart.c @@ -34,7 +34,7 @@ #include <linux/types.h> #include <linux/refcount.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/sibyte/sb1250.h> #include <asm/sibyte/sb1250_uart.h> diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 9adb8362578c..acbb615dd28f 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -1208,8 +1208,16 @@ static int sc16is7xx_probe(struct device *dev, /* Always ask for fixed clock rate from a property. */ device_property_read_u32(dev, "clock-frequency", &uartclk); - s->clk = devm_clk_get(dev, NULL); - if (IS_ERR(s->clk)) { + s->clk = devm_clk_get_optional(dev, NULL); + if (IS_ERR(s->clk)) + return PTR_ERR(s->clk); + + ret = clk_prepare_enable(s->clk); + if (ret) + return ret; + + freq = clk_get_rate(s->clk); + if (freq == 0) { if (uartclk) freq = uartclk; if (pfreq) @@ -1217,13 +1225,7 @@ static int sc16is7xx_probe(struct device *dev, if (freq) dev_dbg(dev, "Clock frequency: %luHz\n", freq); else - return PTR_ERR(s->clk); - } else { - ret = clk_prepare_enable(s->clk); - if (ret) - return ret; - - freq = clk_get_rate(s->clk); + return -EINVAL; } s->regmap = regmap; @@ -1358,8 +1360,7 @@ out_thread: kthread_stop(s->kworker_task); out_clk: - if (!IS_ERR(s->clk)) - clk_disable_unprepare(s->clk); + clk_disable_unprepare(s->clk); return ret; } @@ -1383,8 +1384,7 @@ static int sc16is7xx_remove(struct device *dev) kthread_flush_worker(&s->kworker); kthread_stop(s->kworker_task); - if (!IS_ERR(s->clk)) - clk_disable_unprepare(s->clk); + clk_disable_unprepare(s->clk); return 0; } diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 18ff85a83f80..69092deba11f 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -184,8 +184,8 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state, int init_hw) { struct uart_port *uport = uart_port_check(state); + unsigned long flags; unsigned long page; - unsigned long flags = 0; int retval = 0; if (uport->type == PORT_UNKNOWN) @@ -275,7 +275,7 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) { struct uart_port *uport = uart_port_check(state); struct tty_port *port = &state->port; - unsigned long flags = 0; + unsigned long flags; char *xmit_buf = NULL; /* @@ -334,39 +334,15 @@ void uart_update_timeout(struct uart_port *port, unsigned int cflag, unsigned int baud) { - unsigned int bits; + unsigned int size; - /* byte size and parity */ - switch (cflag & CSIZE) { - case CS5: - bits = 7; - break; - case CS6: - bits = 8; - break; - case CS7: - bits = 9; - break; - default: - bits = 10; - break; /* CS8 */ - } - - if (cflag & CSTOPB) - bits++; - if (cflag & PARENB) - bits++; - - /* - * The total number of bits to be transmitted in the fifo. - */ - bits = bits * port->fifosize; + size = tty_get_frame_size(cflag) * port->fifosize; /* * Figure the timeout to send the above number of bits. * Add .02 seconds of slop */ - port->timeout = (HZ * bits) / baud + HZ/50; + port->timeout = (HZ * size) / baud + HZ/50; } EXPORT_SYMBOL(uart_update_timeout); @@ -616,12 +592,12 @@ static int uart_write(struct tty_struct *tty, return ret; } -static int uart_write_room(struct tty_struct *tty) +static unsigned int uart_write_room(struct tty_struct *tty) { struct uart_state *state = tty->driver_data; struct uart_port *port; unsigned long flags; - int ret; + unsigned int ret; port = uart_port_lock(state, flags); ret = uart_circ_chars_free(&state->xmit); @@ -629,12 +605,12 @@ static int uart_write_room(struct tty_struct *tty) return ret; } -static int uart_chars_in_buffer(struct tty_struct *tty) +static unsigned int uart_chars_in_buffer(struct tty_struct *tty) { struct uart_state *state = tty->driver_data; struct uart_port *port; unsigned long flags; - int ret; + unsigned int ret; port = uart_port_lock(state, flags); ret = uart_circ_chars_pending(&state->xmit); @@ -3029,26 +3005,28 @@ out: /* * Are the two ports equivalent? */ -int uart_match_port(struct uart_port *port1, struct uart_port *port2) +bool uart_match_port(const struct uart_port *port1, + const struct uart_port *port2) { if (port1->iotype != port2->iotype) - return 0; + return false; switch (port1->iotype) { case UPIO_PORT: - return (port1->iobase == port2->iobase); + return port1->iobase == port2->iobase; case UPIO_HUB6: - return (port1->iobase == port2->iobase) && - (port1->hub6 == port2->hub6); + return port1->iobase == port2->iobase && + port1->hub6 == port2->hub6; case UPIO_MEM: case UPIO_MEM16: case UPIO_MEM32: case UPIO_MEM32BE: case UPIO_AU: case UPIO_TSI: - return (port1->mapbase == port2->mapbase); + return port1->mapbase == port2->mapbase; } - return 0; + + return false; } EXPORT_SYMBOL(uart_match_port); diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c index 0a7e5b74bc1d..aaca4fe38486 100644 --- a/drivers/tty/serial/serial_txx9.c +++ b/drivers/tty/serial/serial_txx9.c @@ -24,7 +24,7 @@ #include <linux/tty.h> #include <linux/tty_flip.h> -#include <asm/io.h> +#include <linux/io.h> static char *serial_version = "1.11"; static char *serial_name = "TX39/49 Serial driver"; diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 4baf1316ea72..07eb56294371 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -289,7 +289,7 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = { }, /* - * The "SCIFA" that is in RZ/T and RZ/A2. + * The "SCIFA" that is in RZ/A2, RZ/G2L and RZ/T. * It looks like a normal SCIF with FIFO data, but with a * compressed address space. Also, the break out of interrupts * are different: ERI/BRI, RXI, TXI, TEI, DRI. @@ -306,6 +306,7 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = { [SCFDR] = { 0x0E, 16 }, [SCSPTR] = { 0x10, 16 }, [SCLSR] = { 0x12, 16 }, + [SEMR] = { 0x14, 8 }, }, .fifosize = 16, .overrun_reg = SCLSR, @@ -610,6 +611,14 @@ static void sci_stop_tx(struct uart_port *port) ctrl &= ~SCSCR_TIE; serial_port_out(port, SCSCR, ctrl); + +#ifdef CONFIG_SERIAL_SH_SCI_DMA + if (to_sci_port(port)->chan_tx && + !dma_submit_error(to_sci_port(port)->cookie_tx)) { + dmaengine_terminate_async(to_sci_port(port)->chan_tx); + to_sci_port(port)->cookie_tx = -EINVAL; + } +#endif } static void sci_start_rx(struct uart_port *port) @@ -840,9 +849,6 @@ static void sci_transmit_chars(struct uart_port *port) } -/* On SH3, SCIF may read end-of-break as a space->mark char */ -#define STEPFN(c) ({int __c = (c); (((__c-1)|(__c)) == -1); }) - static void sci_receive_chars(struct uart_port *port) { struct tty_port *tport = &port->state->port; @@ -2494,25 +2500,10 @@ done: uart_update_timeout(port, termios->c_cflag, baud); /* byte size and parity */ - switch (termios->c_cflag & CSIZE) { - case CS5: - bits = 7; - break; - case CS6: - bits = 8; - break; - case CS7: - bits = 9; - break; - default: - bits = 10; - break; - } + bits = tty_get_frame_size(termios->c_cflag); - if (termios->c_cflag & CSTOPB) - bits++; - if (termios->c_cflag & PARENB) - bits++; + if (sci_getreg(port, SEMR)->size) + serial_port_out(port, SEMR, 0); if (best_clk >= 0) { if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) @@ -3170,6 +3161,10 @@ static const struct of_device_id of_sci_match[] = { .compatible = "renesas,scif-r7s9210", .data = SCI_OF_DATA(PORT_SCIF, SCIx_RZ_SCIFA_REGTYPE), }, + { + .compatible = "renesas,scif-r9a07g044", + .data = SCI_OF_DATA(PORT_SCIF, SCIx_RZ_SCIFA_REGTYPE), + }, /* Family-specific types */ { .compatible = "renesas,rcar-gen1-scif", @@ -3452,6 +3447,7 @@ static int __init rzscifa_early_console_setup(struct earlycon_device *device, port_cfg.regtype = SCIx_RZ_SCIFA_REGTYPE; return early_console_setup(device, PORT_SCIF); } + static int __init scifa_early_console_setup(struct earlycon_device *device, const char *opt) { @@ -3471,6 +3467,7 @@ static int __init hscif_early_console_setup(struct earlycon_device *device, OF_EARLYCON_DECLARE(sci, "renesas,sci", sci_early_console_setup); OF_EARLYCON_DECLARE(scif, "renesas,scif", scif_early_console_setup); OF_EARLYCON_DECLARE(scif, "renesas,scif-r7s9210", rzscifa_early_console_setup); +OF_EARLYCON_DECLARE(scif, "renesas,scif-r9a07g044", rzscifa_early_console_setup); OF_EARLYCON_DECLARE(scifa, "renesas,scifa", scifa_early_console_setup); OF_EARLYCON_DECLARE(scifb, "renesas,scifb", scifb_early_console_setup); OF_EARLYCON_DECLARE(hscif, "renesas,hscif", hscif_early_console_setup); diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h index c0dfe4382898..c0ae78632dda 100644 --- a/drivers/tty/serial/sh-sci.h +++ b/drivers/tty/serial/sh-sci.h @@ -31,6 +31,7 @@ enum { SCCKS, /* BRG Clock Select Register */ HSRTRGR, /* Rx FIFO Data Count Trigger Register */ HSTTRGR, /* Tx FIFO Data Count Trigger Register */ + SEMR, /* Serial extended mode register */ SCIx_NR_REGS, }; diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c index e7048515a79c..87e480cc8206 100644 --- a/drivers/tty/serial/st-asc.c +++ b/drivers/tty/serial/st-asc.c @@ -65,7 +65,7 @@ static struct uart_driver asc_uart_driver; /* ASC_RXBUF */ #define ASC_RXBUF_PE 0x100 #define ASC_RXBUF_FE 0x200 -/** +/* * Some of status comes from higher bits of the character and some come from * the status register. Combining both of them in to single status using dummy * bits. @@ -478,7 +478,7 @@ static void asc_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { struct asc_port *ascport = to_asc_port(port); - unsigned long flags = 0; + unsigned long flags; u32 ctl; switch (state) { diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index c2ae7b392b86..ef793b3b4591 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -718,36 +718,6 @@ static void stm32_usart_shutdown(struct uart_port *port) free_irq(port->irq, port); } -static unsigned int stm32_usart_get_databits(struct ktermios *termios) -{ - unsigned int bits; - - tcflag_t cflag = termios->c_cflag; - - switch (cflag & CSIZE) { - /* - * CSIZE settings are not necessarily supported in hardware. - * CSIZE unsupported configurations are handled here to set word length - * to 8 bits word as default configuration and to print debug message. - */ - case CS5: - bits = 5; - break; - case CS6: - bits = 6; - break; - case CS7: - bits = 7; - break; - /* default including CS8 */ - default: - bits = 8; - break; - } - - return bits; -} - static void stm32_usart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) @@ -805,7 +775,7 @@ static void stm32_usart_set_termios(struct uart_port *port, if (cflag & CSTOPB) cr2 |= USART_CR2_STOP_2B; - bits = stm32_usart_get_databits(termios); + bits = tty_get_char_size(cflag); stm32_port->rdr_mask = (BIT(bits) - 1); if (cflag & PARENB) { @@ -980,7 +950,7 @@ static void stm32_usart_pm(struct uart_port *port, unsigned int state, struct stm32_port, port); const struct stm32_usart_offsets *ofs = &stm32port->info->ofs; const struct stm32_usart_config *cfg = &stm32port->info->cfg; - unsigned long flags = 0; + unsigned long flags; switch (state) { case UART_PM_STATE_ON: @@ -1182,6 +1152,14 @@ static const struct of_device_id stm32_match[] = { MODULE_DEVICE_TABLE(of, stm32_match); #endif +static void stm32_usart_of_dma_rx_remove(struct stm32_port *stm32port, + struct platform_device *pdev) +{ + if (stm32port->rx_buf) + dma_free_coherent(&pdev->dev, RX_BUF_L, stm32port->rx_buf, + stm32port->rx_dma_buf); +} + static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port, struct platform_device *pdev) { @@ -1199,19 +1177,11 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port, if (uart_console(port)) return -ENODEV; - /* Request DMA RX channel */ - stm32port->rx_ch = dma_request_slave_channel(dev, "rx"); - if (!stm32port->rx_ch) { - dev_info(dev, "rx dma alloc failed\n"); - return -ENODEV; - } stm32port->rx_buf = dma_alloc_coherent(&pdev->dev, RX_BUF_L, &stm32port->rx_dma_buf, GFP_KERNEL); - if (!stm32port->rx_buf) { - ret = -ENOMEM; - goto alloc_err; - } + if (!stm32port->rx_buf) + return -ENOMEM; /* Configure DMA channel */ memset(&config, 0, sizeof(config)); @@ -1221,8 +1191,8 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port, ret = dmaengine_slave_config(stm32port->rx_ch, &config); if (ret < 0) { dev_err(dev, "rx dma channel config failed\n"); - ret = -ENODEV; - goto config_err; + stm32_usart_of_dma_rx_remove(stm32port, pdev); + return ret; } /* Prepare a DMA cyclic transaction */ @@ -1232,8 +1202,8 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port, DMA_PREP_INTERRUPT); if (!desc) { dev_err(dev, "rx dma prep cyclic failed\n"); - ret = -ENODEV; - goto config_err; + stm32_usart_of_dma_rx_remove(stm32port, pdev); + return -ENODEV; } /* No callback as dma buffer is drained on usart interrupt */ @@ -1244,24 +1214,22 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port, ret = dma_submit_error(dmaengine_submit(desc)); if (ret) { dmaengine_terminate_sync(stm32port->rx_ch); - goto config_err; + stm32_usart_of_dma_rx_remove(stm32port, pdev); + return ret; } /* Issue pending DMA requests */ dma_async_issue_pending(stm32port->rx_ch); return 0; +} -config_err: - dma_free_coherent(&pdev->dev, - RX_BUF_L, stm32port->rx_buf, - stm32port->rx_dma_buf); - -alloc_err: - dma_release_channel(stm32port->rx_ch); - stm32port->rx_ch = NULL; - - return ret; +static void stm32_usart_of_dma_tx_remove(struct stm32_port *stm32port, + struct platform_device *pdev) +{ + if (stm32port->tx_buf) + dma_free_coherent(&pdev->dev, TX_BUF_L, stm32port->tx_buf, + stm32port->tx_dma_buf); } static int stm32_usart_of_dma_tx_probe(struct stm32_port *stm32port, @@ -1275,19 +1243,11 @@ static int stm32_usart_of_dma_tx_probe(struct stm32_port *stm32port, stm32port->tx_dma_busy = false; - /* Request DMA TX channel */ - stm32port->tx_ch = dma_request_slave_channel(dev, "tx"); - if (!stm32port->tx_ch) { - dev_info(dev, "tx dma alloc failed\n"); - return -ENODEV; - } stm32port->tx_buf = dma_alloc_coherent(&pdev->dev, TX_BUF_L, &stm32port->tx_dma_buf, GFP_KERNEL); - if (!stm32port->tx_buf) { - ret = -ENOMEM; - goto alloc_err; - } + if (!stm32port->tx_buf) + return -ENOMEM; /* Configure DMA channel */ memset(&config, 0, sizeof(config)); @@ -1297,22 +1257,11 @@ static int stm32_usart_of_dma_tx_probe(struct stm32_port *stm32port, ret = dmaengine_slave_config(stm32port->tx_ch, &config); if (ret < 0) { dev_err(dev, "tx dma channel config failed\n"); - ret = -ENODEV; - goto config_err; + stm32_usart_of_dma_tx_remove(stm32port, pdev); + return ret; } return 0; - -config_err: - dma_free_coherent(&pdev->dev, - TX_BUF_L, stm32port->tx_buf, - stm32port->tx_dma_buf); - -alloc_err: - dma_release_channel(stm32port->tx_ch); - stm32port->tx_ch = NULL; - - return ret; } static int stm32_usart_serial_probe(struct platform_device *pdev) @@ -1336,16 +1285,43 @@ static int stm32_usart_serial_probe(struct platform_device *pdev) device_set_wakeup_capable(&pdev->dev, true); ret = dev_pm_set_wake_irq(&pdev->dev, stm32port->port.irq); if (ret) - goto err_nowup; + goto err_deinit_port; } - ret = stm32_usart_of_dma_rx_probe(stm32port, pdev); - if (ret) - dev_info(&pdev->dev, "interrupt mode used for rx (no dma)\n"); + stm32port->rx_ch = dma_request_chan(&pdev->dev, "rx"); + if (PTR_ERR(stm32port->rx_ch) == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; + goto err_wakeirq; + } + /* Fall back in interrupt mode for any non-deferral error */ + if (IS_ERR(stm32port->rx_ch)) + stm32port->rx_ch = NULL; + + stm32port->tx_ch = dma_request_chan(&pdev->dev, "tx"); + if (PTR_ERR(stm32port->tx_ch) == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; + goto err_dma_rx; + } + /* Fall back in interrupt mode for any non-deferral error */ + if (IS_ERR(stm32port->tx_ch)) + stm32port->tx_ch = NULL; - ret = stm32_usart_of_dma_tx_probe(stm32port, pdev); - if (ret) - dev_info(&pdev->dev, "interrupt mode used for tx (no dma)\n"); + if (stm32port->rx_ch && stm32_usart_of_dma_rx_probe(stm32port, pdev)) { + /* Fall back in interrupt mode */ + dma_release_channel(stm32port->rx_ch); + stm32port->rx_ch = NULL; + } + + if (stm32port->tx_ch && stm32_usart_of_dma_tx_probe(stm32port, pdev)) { + /* Fall back in interrupt mode */ + dma_release_channel(stm32port->tx_ch); + stm32port->tx_ch = NULL; + } + + if (!stm32port->rx_ch) + dev_info(&pdev->dev, "interrupt mode for rx (no dma)\n"); + if (!stm32port->tx_ch) + dev_info(&pdev->dev, "interrupt mode for tx (no dma)\n"); platform_set_drvdata(pdev, &stm32port->port); @@ -1366,30 +1342,23 @@ err_port: pm_runtime_set_suspended(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); - if (stm32port->rx_ch) { - dmaengine_terminate_async(stm32port->rx_ch); - dma_release_channel(stm32port->rx_ch); - } - - if (stm32port->rx_dma_buf) - dma_free_coherent(&pdev->dev, - RX_BUF_L, stm32port->rx_buf, - stm32port->rx_dma_buf); - if (stm32port->tx_ch) { - dmaengine_terminate_async(stm32port->tx_ch); + stm32_usart_of_dma_tx_remove(stm32port, pdev); dma_release_channel(stm32port->tx_ch); } - if (stm32port->tx_dma_buf) - dma_free_coherent(&pdev->dev, - TX_BUF_L, stm32port->tx_buf, - stm32port->tx_dma_buf); + if (stm32port->rx_ch) + stm32_usart_of_dma_rx_remove(stm32port, pdev); + +err_dma_rx: + if (stm32port->rx_ch) + dma_release_channel(stm32port->rx_ch); +err_wakeirq: if (stm32port->wakeup_src) dev_pm_clear_wake_irq(&pdev->dev); -err_nowup: +err_deinit_port: if (stm32port->wakeup_src) device_set_wakeup_capable(&pdev->dev, false); @@ -1416,28 +1385,20 @@ static int stm32_usart_serial_remove(struct platform_device *pdev) stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR); + if (stm32_port->tx_ch) { + dmaengine_terminate_async(stm32_port->tx_ch); + stm32_usart_of_dma_tx_remove(stm32_port, pdev); + dma_release_channel(stm32_port->tx_ch); + } + if (stm32_port->rx_ch) { dmaengine_terminate_async(stm32_port->rx_ch); + stm32_usart_of_dma_rx_remove(stm32_port, pdev); dma_release_channel(stm32_port->rx_ch); } - if (stm32_port->rx_dma_buf) - dma_free_coherent(&pdev->dev, - RX_BUF_L, stm32_port->rx_buf, - stm32_port->rx_dma_buf); - stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); - if (stm32_port->tx_ch) { - dmaengine_terminate_async(stm32_port->tx_ch); - dma_release_channel(stm32_port->tx_ch); - } - - if (stm32_port->tx_dma_buf) - dma_free_coherent(&pdev->dev, - TX_BUF_L, stm32_port->tx_buf, - stm32_port->tx_dma_buf); - if (stm32_port->wakeup_src) { dev_pm_clear_wake_irq(&pdev->dev); device_init_wakeup(&pdev->dev, false); diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c index bab551f46963..92e572634009 100644 --- a/drivers/tty/serial/sunsab.c +++ b/drivers/tty/serial/sunsab.c @@ -35,7 +35,7 @@ #include <linux/init.h> #include <linux/of_device.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/irq.h> #include <asm/prom.h> #include <asm/setup.h> diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c index 12c2468f2b0e..425a016f9db7 100644 --- a/drivers/tty/serial/sunsu.c +++ b/drivers/tty/serial/sunsu.c @@ -39,7 +39,7 @@ #include <linux/delay.h> #include <linux/of_device.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/irq.h> #include <asm/prom.h> #include <asm/setup.h> diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c index 001e19d7c17d..1a54e3e52ed6 100644 --- a/drivers/tty/serial/sunzilog.c +++ b/drivers/tty/serial/sunzilog.c @@ -35,7 +35,7 @@ #include <linux/init.h> #include <linux/of_device.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/irq.h> #include <asm/prom.h> #include <asm/setup.h> diff --git a/drivers/tty/serial/tegra-tcu.c b/drivers/tty/serial/tegra-tcu.c index 52687c65ad74..4877c54c613d 100644 --- a/drivers/tty/serial/tegra-tcu.c +++ b/drivers/tty/serial/tegra-tcu.c @@ -195,13 +195,6 @@ static int tegra_tcu_probe(struct platform_device *pdev) return err; } - tcu->rx = mbox_request_channel_byname(&tcu->rx_client, "rx"); - if (IS_ERR(tcu->rx)) { - err = PTR_ERR(tcu->rx); - dev_err(&pdev->dev, "failed to get rx mailbox: %d\n", err); - goto free_tx; - } - #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE) /* setup the console */ strcpy(tcu->console.name, "ttyTCU"); @@ -226,7 +219,7 @@ static int tegra_tcu_probe(struct platform_device *pdev) if (err) { dev_err(&pdev->dev, "failed to register UART driver: %d\n", err); - goto free_rx; + goto free_tx; } /* setup the port */ @@ -246,6 +239,17 @@ static int tegra_tcu_probe(struct platform_device *pdev) goto unregister_uart; } + /* + * Request RX channel after creating port to ensure tcu->port + * is ready for any immediate incoming bytes. + */ + tcu->rx = mbox_request_channel_byname(&tcu->rx_client, "rx"); + if (IS_ERR(tcu->rx)) { + err = PTR_ERR(tcu->rx); + dev_err(&pdev->dev, "failed to get rx mailbox: %d\n", err); + goto remove_uart_port; + } + platform_set_drvdata(pdev, tcu); #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE) register_console(&tcu->console); @@ -253,10 +257,10 @@ static int tegra_tcu_probe(struct platform_device *pdev) return 0; +remove_uart_port: + uart_remove_one_port(&tcu->driver, &tcu->port); unregister_uart: uart_unregister_driver(&tcu->driver); -free_rx: - mbox_free_channel(tcu->rx); free_tx: mbox_free_channel(tcu->tx); @@ -270,9 +274,9 @@ static int tegra_tcu_remove(struct platform_device *pdev) #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE) unregister_console(&tcu->console); #endif + mbox_free_channel(tcu->rx); uart_remove_one_port(&tcu->driver, &tcu->port); uart_unregister_driver(&tcu->driver); - mbox_free_channel(tcu->rx); mbox_free_channel(tcu->tx); return 0; diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index f42ccc40ffa6..a5f15f22d9ef 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -505,21 +505,23 @@ static void ulite_console_write(struct console *co, const char *s, static int ulite_console_setup(struct console *co, char *options) { - struct uart_port *port; + struct uart_port *port = NULL; int baud = 9600; int bits = 8; int parity = 'n'; int flow = 'n'; - - port = console_port; + if (co->index >= 0 && co->index < ULITE_NR_UARTS) + port = ulite_ports + co->index; /* Has the device been initialized yet? */ - if (!port->mapbase) { + if (!port || !port->mapbase) { pr_debug("console on ttyUL%i not present\n", co->index); return -ENODEV; } + console_port = port; + /* not initialized yet? */ if (!port->membase) { if (ulite_request_port(port)) @@ -655,17 +657,6 @@ static int ulite_assign(struct device *dev, int id, u32 base, int irq, dev_set_drvdata(dev, port); -#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE - /* - * If console hasn't been found yet try to assign this port - * because it is required to be assigned for console setup function. - * If register_console() don't assign value, then console_port pointer - * is cleanup. - */ - if (ulite_uart_driver.cons->index == -1) - console_port = port; -#endif - /* Register the port */ rc = uart_add_one_port(&ulite_uart_driver, port); if (rc) { @@ -675,12 +666,6 @@ static int ulite_assign(struct device *dev, int id, u32 base, int irq, return rc; } -#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE - /* This is not port which is used for console that's why clean it up */ - if (ulite_uart_driver.cons->index == -1) - console_port = NULL; -#endif - return 0; } diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c index f81261cb52b8..6000853973c1 100644 --- a/drivers/tty/serial/ucc_uart.c +++ b/drivers/tty/serial/ucc_uart.c @@ -1227,7 +1227,7 @@ static int soft_uart_init(struct platform_device *ofdev) * kernel, then we use it. */ ret = request_firmware_nowait(THIS_MODULE, - FW_ACTION_HOTPLUG, filename, &ofdev->dev, + FW_ACTION_UEVENT, filename, &ofdev->dev, GFP_KERNEL, &ofdev->dev, uart_firmware_cont); if (ret) { dev_err(&ofdev->dev, diff --git a/drivers/tty/serial/vr41xx_siu.c b/drivers/tty/serial/vr41xx_siu.c index eeb4b6568776..647198b1e2b9 100644 --- a/drivers/tty/serial/vr41xx_siu.c +++ b/drivers/tty/serial/vr41xx_siu.c @@ -20,7 +20,7 @@ #include <linux/tty.h> #include <linux/tty_flip.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/vr41xx/siu.h> #include <asm/vr41xx/vr41xx.h> diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 67a2db621e2b..962e522ccc45 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -484,7 +484,7 @@ static unsigned int cdns_uart_set_baud_rate(struct uart_port *port, #ifdef CONFIG_COMMON_CLK /** - * cdns_uart_clk_notitifer_cb - Clock notifier callback + * cdns_uart_clk_notifier_cb - Clock notifier callback * @nb: Notifier block * @event: Notify event * @data: Notifier data @@ -497,8 +497,8 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb, struct uart_port *port; int locked = 0; struct clk_notifier_data *ndata = data; - unsigned long flags = 0; struct cdns_uart *cdns_uart = to_cdns_uart(nb); + unsigned long flags; port = cdns_uart->port; if (port->suspended) @@ -1149,7 +1149,7 @@ static void cdns_uart_console_putchar(struct uart_port *port, int ch) } static void cdns_early_write(struct console *con, const char *s, - unsigned n) + unsigned int n) { struct earlycon_device *dev = con->data; @@ -1210,7 +1210,7 @@ static void cdns_uart_console_write(struct console *co, const char *s, unsigned int count) { struct uart_port *port = console_port; - unsigned long flags = 0; + unsigned long flags; unsigned int imr, ctrl; int locked = 1; @@ -1308,7 +1308,7 @@ static int cdns_uart_suspend(struct device *device) may_wake = device_may_wakeup(device); if (console_suspend_enabled && uart_console(port) && may_wake) { - unsigned long flags = 0; + unsigned long flags; spin_lock_irqsave(&port->lock, flags); /* Empty the receive FIFO 1st before making changes */ @@ -1339,7 +1339,7 @@ static int cdns_uart_resume(struct device *device) { struct uart_port *port = dev_get_drvdata(device); struct cdns_uart *cdns_uart = port->private_data; - unsigned long flags = 0; + unsigned long flags; u32 ctrl_reg; int may_wake; diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index 5523cf7bd1c2..5bb928b7873e 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c @@ -768,7 +768,7 @@ static int write(struct tty_struct *tty, if (!info->tx_buf || (count > info->max_frame_size)) return -EIO; - if (!count || tty->stopped || tty->hw_stopped) + if (!count || tty->flow.stopped || tty->hw_stopped) return 0; spin_lock_irqsave(&info->lock, flags); @@ -868,15 +868,15 @@ exit: DBGINFO(("%s wait_until_sent exit\n", info->device_name)); } -static int write_room(struct tty_struct *tty) +static unsigned int write_room(struct tty_struct *tty) { struct slgt_info *info = tty->driver_data; - int ret; + unsigned int ret; if (sanity_check(info, tty->name, "write_room")) return 0; ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE; - DBGINFO(("%s write_room=%d\n", info->device_name, ret)); + DBGINFO(("%s write_room=%u\n", info->device_name, ret)); return ret; } @@ -889,7 +889,7 @@ static void flush_chars(struct tty_struct *tty) return; DBGINFO(("%s flush_chars entry tx_count=%d\n", info->device_name, info->tx_count)); - if (info->tx_count <= 0 || tty->stopped || + if (info->tx_count <= 0 || tty->flow.stopped || tty->hw_stopped || !info->tx_buf) return; @@ -1254,14 +1254,14 @@ static int synclink_gt_proc_show(struct seq_file *m, void *v) /* * return count of bytes in transmit buffer */ -static int chars_in_buffer(struct tty_struct *tty) +static unsigned int chars_in_buffer(struct tty_struct *tty) { struct slgt_info *info = tty->driver_data; - int count; + unsigned int count; if (sanity_check(info, tty->name, "chars_in_buffer")) return 0; count = tbuf_bytes(info); - DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, count)); + DBGINFO(("%s chars_in_buffer()=%u\n", info->device_name, count)); return count; } @@ -2241,7 +2241,7 @@ static void isr_txeom(struct slgt_info *info, unsigned short status) else #endif { - if (info->port.tty && (info->port.tty->stopped || info->port.tty->hw_stopped)) { + if (info->port.tty && (info->port.tty->flow.stopped || info->port.tty->hw_stopped)) { tx_stop(info); return; } @@ -2465,14 +2465,7 @@ static void change_params(struct slgt_info *info) /* byte size and parity */ - switch (cflag & CSIZE) { - case CS5: info->params.data_bits = 5; break; - case CS6: info->params.data_bits = 6; break; - case CS7: info->params.data_bits = 7; break; - case CS8: info->params.data_bits = 8; break; - default: info->params.data_bits = 7; break; - } - + info->params.data_bits = tty_get_char_size(cflag); info->params.stop_bits = (cflag & CSTOPB) ? 2 : 1; if (cflag & PARENB) diff --git a/drivers/tty/tty_baudrate.c b/drivers/tty/tty_baudrate.c index 48b5de659c77..426b1252781a 100644 --- a/drivers/tty/tty_baudrate.c +++ b/drivers/tty/tty_baudrate.c @@ -147,7 +147,7 @@ void tty_termios_encode_baud_rate(struct ktermios *termios, int iclose = ibaud/50, oclose = obaud/50; int ibinput = 0; - if (obaud == 0) /* CD dropped */ + if (obaud == 0) /* CD dropped */ ibaud = 0; /* Clear ibaud to be sure */ termios->c_ispeed = ibaud; @@ -159,8 +159,9 @@ void tty_termios_encode_baud_rate(struct ktermios *termios, #endif #ifdef BOTHER /* If the user asked for a precise weird speed give a precise weird - answer. If they asked for a Bfoo speed they may have problems - digesting non-exact replies so fuzz a bit */ + * answer. If they asked for a Bfoo speed they may have problems + * digesting non-exact replies so fuzz a bit. + */ if ((termios->c_cflag & CBAUD) == BOTHER) { oclose = 0; @@ -191,7 +192,8 @@ void tty_termios_encode_baud_rate(struct ktermios *termios, if (ibaud - iclose <= baud_table[i] && ibaud + iclose >= baud_table[i]) { /* For the case input == output don't set IBAUD bits - if the user didn't do so */ + * if the user didn't do so. + */ if (ofound == i && !ibinput) ifound = i; #ifdef IBSHIFT @@ -211,7 +213,8 @@ void tty_termios_encode_baud_rate(struct ktermios *termios, if (ofound == -1) termios->c_cflag |= BOTHER; /* Set exact input bits only if the input and output differ or the - user already did */ + * user already did. + */ if (ifound == -1 && (ibaud != obaud || ibinput)) termios->c_cflag |= (BOTHER << IBSHIFT); #else diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 9733469a14b2..635d0af229b7 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -32,8 +32,8 @@ * We default to dicing tty buffer allocations to this many characters * in order to avoid multiple page allocations. We know the size of * tty_buffer itself but it must also be taken into account that the - * the buffer is 256 byte aligned. See tty_buffer_find for the allocation - * logic this must match + * buffer is 256 byte aligned. See tty_buffer_find for the allocation + * logic this must match. */ #define TTY_BUFFER_PAGE (((PAGE_SIZE - sizeof(struct tty_buffer)) / 2) & ~0xFF) @@ -88,9 +88,10 @@ EXPORT_SYMBOL_GPL(tty_buffer_unlock_exclusive); * pre-allocate if memory guarantee is required). */ -int tty_buffer_space_avail(struct tty_port *port) +unsigned int tty_buffer_space_avail(struct tty_port *port) { int space = port->buf.mem_limit - atomic_read(&port->buf.mem_used); + return max(space, 0); } EXPORT_SYMBOL_GPL(tty_buffer_space_avail); @@ -169,7 +170,8 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size) } /* Should possibly check if this fails for the largest buffer we - have queued and recycle that ? */ + * have queued and recycle that ? + */ if (atomic_read(&port->buf.mem_used) > port->buf.mem_limit) return NULL; p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); @@ -242,7 +244,7 @@ void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld) } /** - * tty_buffer_request_room - grow tty buffer if needed + * __tty_buffer_request_room - grow tty buffer if needed * @port: tty port * @size: size desired * @flags: buffer flags if new buffer allocated (default = 0) @@ -312,11 +314,13 @@ int tty_insert_flip_string_fixed_flag(struct tty_port *port, const unsigned char *chars, char flag, size_t size) { int copied = 0; + do { int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); int flags = (flag == TTY_NORMAL) ? TTYB_NORMAL : 0; int space = __tty_buffer_request_room(port, goal, flags); struct tty_buffer *tb = port->buf.tail; + if (unlikely(space == 0)) break; memcpy(char_buf_ptr(tb, tb->used), chars, space); @@ -326,7 +330,8 @@ int tty_insert_flip_string_fixed_flag(struct tty_port *port, copied += space; chars += space; /* There is a small chance that we need to split the data over - several buffers. If this is the case we must loop */ + * several buffers. If this is the case we must loop. + */ } while (unlikely(size > copied)); return copied; } @@ -348,10 +353,12 @@ int tty_insert_flip_string_flags(struct tty_port *port, const unsigned char *chars, const char *flags, size_t size) { int copied = 0; + do { int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); int space = tty_buffer_request_room(port, goal); struct tty_buffer *tb = port->buf.tail; + if (unlikely(space == 0)) break; memcpy(char_buf_ptr(tb, tb->used), chars, space); @@ -361,7 +368,8 @@ int tty_insert_flip_string_flags(struct tty_port *port, chars += space; flags += space; /* There is a small chance that we need to split the data over - several buffers. If this is the case we must loop */ + * several buffers. If this is the case we must loop. + */ } while (unlikely(size > copied)); return copied; } @@ -431,8 +439,10 @@ int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars, size_t size) { int space = __tty_buffer_request_room(port, size, TTYB_NORMAL); + if (likely(space)) { struct tty_buffer *tb = port->buf.tail; + *chars = char_buf_ptr(tb, tb->used); if (~tb->flags & TTYB_NORMAL) memset(flag_buf_ptr(tb, tb->used), TTY_NORMAL, space); @@ -455,7 +465,7 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string); * Returns the number of bytes processed */ int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p, - char *f, int count) + const char *f, int count) { if (ld->ops->receive_buf2) count = ld->ops->receive_buf2(ld->tty, p, f, count); @@ -472,7 +482,7 @@ static int receive_buf(struct tty_port *port, struct tty_buffer *head, int count) { unsigned char *p = char_buf_ptr(head, head->read); - char *f = NULL; + const char *f = NULL; int n; if (~head->flags & TTYB_NORMAL) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 5b5e99604989..26debec26b4e 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -33,7 +33,7 @@ * -- Nick Holloway <alfie@dcs.warwick.ac.uk>, 27th May 1993. * * Rewrote canonical mode and added more termios flags. - * -- julian@uhunix.uhcc.hawaii.edu (J. Cowley), 13Jan94 + * -- julian@uhunix.uhcc.hawaii.edu (J. Cowley), 13Jan94 * * Reorganized FASYNC support so mouse code can share it. * -- ctm@ardi.com, 9Sep95 @@ -131,12 +131,12 @@ struct ktermios tty_std_termios = { /* for the benefit of tty drivers */ .c_ospeed = 38400, /* .c_line = N_TTY, */ }; - EXPORT_SYMBOL(tty_std_termios); /* This list gets poked at by procfs and various bits of boot up code. This - could do with some rationalisation such as pulling the tty proc function - into this file */ + * could do with some rationalisation such as pulling the tty proc function + * into this file. + */ LIST_HEAD(tty_drivers); /* linked list of tty drivers */ @@ -248,7 +248,6 @@ const char *tty_name(const struct tty_struct *tty) return "NULL tty"; return tty->name; } - EXPORT_SYMBOL(tty_name); const char *tty_driver_name(const struct tty_struct *tty) @@ -320,6 +319,7 @@ static struct tty_driver *get_tty_driver(dev_t device, int *index) list_for_each_entry(p, &tty_drivers, tty_drivers) { dev_t base = MKDEV(p->major, p->minor_start); + if (device < base || device >= base + p->num) continue; *index = device - base; @@ -537,7 +537,6 @@ void tty_wakeup(struct tty_struct *tty) } wake_up_interruptible_poll(&tty->write_wait, EPOLLOUT); } - EXPORT_SYMBOL_GPL(tty_wakeup); /** @@ -613,8 +612,9 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) set_bit(TTY_HUPPING, &tty->flags); /* inuse_filps is protected by the single tty lock, - this really needs to change if we want to flush the - workqueue with the lock held */ + * this really needs to change if we want to flush the + * workqueue with the lock held. + */ check_tty_count(tty, "tty_hangup"); spin_lock(&tty->files_lock); @@ -638,15 +638,15 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) tty_ldisc_hangup(tty, cons_filp != NULL); - spin_lock_irq(&tty->ctrl_lock); + spin_lock_irq(&tty->ctrl.lock); clear_bit(TTY_THROTTLED, &tty->flags); clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - put_pid(tty->session); - put_pid(tty->pgrp); - tty->session = NULL; - tty->pgrp = NULL; - tty->ctrl_status = 0; - spin_unlock_irq(&tty->ctrl_lock); + put_pid(tty->ctrl.session); + put_pid(tty->ctrl.pgrp); + tty->ctrl.session = NULL; + tty->ctrl.pgrp = NULL; + tty->ctrl.pktstatus = 0; + spin_unlock_irq(&tty->ctrl.lock); /* * If one of the devices matches a console pointer, we @@ -694,7 +694,6 @@ void tty_hangup(struct tty_struct *tty) tty_debug_hangup(tty, "hangup\n"); schedule_work(&tty->hangup_work); } - EXPORT_SYMBOL(tty_hangup); /** @@ -711,7 +710,6 @@ void tty_vhangup(struct tty_struct *tty) tty_debug_hangup(tty, "vhangup\n"); __tty_hangup(tty, 0); } - EXPORT_SYMBOL(tty_vhangup); @@ -761,9 +759,17 @@ int tty_hung_up_p(struct file *filp) { return (filp && filp->f_op == &hung_up_tty_fops); } - EXPORT_SYMBOL(tty_hung_up_p); +void __stop_tty(struct tty_struct *tty) +{ + if (tty->flow.stopped) + return; + tty->flow.stopped = true; + if (tty->ops->stop) + tty->ops->stop(tty); +} + /** * stop_tty - propagate flow control * @tty: tty to stop @@ -778,28 +784,28 @@ EXPORT_SYMBOL(tty_hung_up_p); * but not always. * * Locking: - * flow_lock + * flow.lock */ - -void __stop_tty(struct tty_struct *tty) -{ - if (tty->stopped) - return; - tty->stopped = 1; - if (tty->ops->stop) - tty->ops->stop(tty); -} - void stop_tty(struct tty_struct *tty) { unsigned long flags; - spin_lock_irqsave(&tty->flow_lock, flags); + spin_lock_irqsave(&tty->flow.lock, flags); __stop_tty(tty); - spin_unlock_irqrestore(&tty->flow_lock, flags); + spin_unlock_irqrestore(&tty->flow.lock, flags); } EXPORT_SYMBOL(stop_tty); +void __start_tty(struct tty_struct *tty) +{ + if (!tty->flow.stopped || tty->flow.tco_stopped) + return; + tty->flow.stopped = false; + if (tty->ops->start) + tty->ops->start(tty); + tty_wakeup(tty); +} + /** * start_tty - propagate flow control * @tty: tty to start @@ -809,26 +815,15 @@ EXPORT_SYMBOL(stop_tty); * start method is invoked and the line discipline woken. * * Locking: - * flow_lock + * flow.lock */ - -void __start_tty(struct tty_struct *tty) -{ - if (!tty->stopped || tty->flow_stopped) - return; - tty->stopped = 0; - if (tty->ops->start) - tty->ops->start(tty); - tty_wakeup(tty); -} - void start_tty(struct tty_struct *tty) { unsigned long flags; - spin_lock_irqsave(&tty->flow_lock, flags); + spin_lock_irqsave(&tty->flow.lock, flags); __start_tty(tty); - spin_unlock_irqrestore(&tty->flow_lock, flags); + spin_unlock_irqrestore(&tty->flow.lock, flags); } EXPORT_SYMBOL(start_tty); @@ -914,10 +909,8 @@ static int iterate_tty_read(struct tty_ldisc *ld, struct tty_struct *tty, /** * tty_read - read method for tty device files - * @file: pointer to tty file - * @buf: user buffer - * @count: size of user buffer - * @ppos: unused + * @iocb: kernel I/O control block + * @to: destination for the data read * * Perform the read system call function on this terminal device. Checks * for hung up devices before calling the line discipline method. @@ -941,7 +934,8 @@ static ssize_t tty_read(struct kiocb *iocb, struct iov_iter *to) return -EIO; /* We want to wait for the line discipline to sort out in this - situation */ + * situation. + */ ld = tty_ldisc_ref_wait(tty); if (!ld) return hung_up_tty_read(iocb, to); @@ -1033,6 +1027,7 @@ static inline ssize_t do_tty_write( /* Do the write .. */ for (;;) { size_t size = count; + if (size > chunk) size = chunk; @@ -1091,36 +1086,18 @@ void tty_write_message(struct tty_struct *tty, char *msg) tty_unlock(tty); tty_write_unlock(tty); } - return; } - -/** - * tty_write - write method for tty device file - * @file: tty file pointer - * @buf: user data to write - * @count: bytes to write - * @ppos: unused - * - * Write data to a tty device via the line discipline. - * - * Locking: - * Locks the line discipline as required - * Writes to the tty driver are serialized by the atomic_write_lock - * and are then processed in chunks to the device. The line discipline - * write method will not be invoked in parallel for each device. - */ - static ssize_t file_tty_write(struct file *file, struct kiocb *iocb, struct iov_iter *from) { struct tty_struct *tty = file_tty(file); - struct tty_ldisc *ld; + struct tty_ldisc *ld; ssize_t ret; if (tty_paranoia_check(tty, file_inode(file), "tty_write")) return -EIO; if (!tty || !tty->ops->write || tty_io_error(tty)) - return -EIO; + return -EIO; /* Short term debug to catch buggy drivers */ if (tty->ops->write_room == NULL) tty_err(tty, "missing write_room method\n"); @@ -1135,6 +1112,20 @@ static ssize_t file_tty_write(struct file *file, struct kiocb *iocb, struct iov_ return ret; } +/** + * tty_write - write method for tty device file + * @iocb: kernel I/O control block + * @from: iov_iter with data to write + * + * Write data to a tty device via the line discipline. + * + * Locking: + * Locks the line discipline as required + * Writes to the tty driver are serialized by the atomic_write_lock + * and are then processed in chunks to the device. The line + * discipline write method will not be invoked in parallel for + * each device. + */ static ssize_t tty_write(struct kiocb *iocb, struct iov_iter *from) { return file_tty_write(iocb->ki_filp, iocb, from); @@ -1150,11 +1141,12 @@ ssize_t redirected_tty_write(struct kiocb *iocb, struct iov_iter *iter) spin_unlock(&redirect_lock); /* - * We know the redirected tty is just another tty, we can can + * We know the redirected tty is just another tty, we can * call file_tty_write() directly with that file pointer. */ if (p) { ssize_t res; + res = file_tty_write(p, iocb, iter); fput(p); return res; @@ -1172,7 +1164,7 @@ ssize_t redirected_tty_write(struct kiocb *iocb, struct iov_iter *iter) int tty_send_xchar(struct tty_struct *tty, char ch) { - int was_stopped = tty->stopped; + bool was_stopped = tty->flow.stopped; if (tty->ops->send_xchar) { down_read(&tty->termios_rwsem); @@ -1559,8 +1551,8 @@ static void release_one_tty(struct work_struct *work) list_del_init(&tty->tty_files); spin_unlock(&tty->files_lock); - put_pid(tty->pgrp); - put_pid(tty->session); + put_pid(tty->ctrl.pgrp); + put_pid(tty->ctrl.session); free_tty_struct(tty); } @@ -1569,7 +1561,8 @@ static void queue_release_one_tty(struct kref *kref) struct tty_struct *tty = container_of(kref, struct tty_struct, kref); /* The hangup queue is now free so we can reuse it rather than - waste a chunk of memory for each port */ + * waste a chunk of memory for each port. + */ INIT_WORK(&tty->hangup_work, release_one_tty); schedule_work(&tty->hangup_work); } @@ -1861,9 +1854,9 @@ int tty_release(struct inode *inode, struct file *filp) */ if (!tty->count) { read_lock(&tasklist_lock); - session_clear_tty(tty->session); + session_clear_tty(tty->ctrl.session); if (o_tty) - session_clear_tty(o_tty->session); + session_clear_tty(o_tty->ctrl.session); read_unlock(&tasklist_lock); } @@ -1874,7 +1867,8 @@ int tty_release(struct inode *inode, struct file *filp) tty_unlock(tty); /* At this point, the tty->count == 0 should ensure a dead tty - cannot be re-opened by a racing opener */ + * cannot be re-opened by a racing opener. + */ if (!final) return 0; @@ -1928,8 +1922,8 @@ static struct tty_struct *tty_open_current_tty(dev_t device, struct file *filp) * @index: index for the device in the @return driver * @return: driver for this inode (with increased refcount) * - * If @return is not erroneous, the caller is responsible to decrement the - * refcount by tty_driver_kref_put. + * If @return is not erroneous, the caller is responsible to decrement the + * refcount by tty_driver_kref_put. * * Locking: tty_mutex protects get_tty_driver */ @@ -1942,6 +1936,7 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, #ifdef CONFIG_VT case MKDEV(TTY_MAJOR, 0): { extern struct tty_driver *console_driver; + driver = tty_driver_kref_get(console_driver); *index = fg_console; break; @@ -1949,6 +1944,7 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, #endif case MKDEV(TTYAUX_MAJOR, 1): { struct tty_driver *console_driver = console_device(index); + if (console_driver) { driver = tty_driver_kref_get(console_driver); if (driver && filp) { @@ -2250,16 +2246,16 @@ static int __tty_fasync(int fd, struct file *filp, int on) enum pid_type type; struct pid *pid; - spin_lock_irqsave(&tty->ctrl_lock, flags); - if (tty->pgrp) { - pid = tty->pgrp; + spin_lock_irqsave(&tty->ctrl.lock, flags); + if (tty->ctrl.pgrp) { + pid = tty->ctrl.pgrp; type = PIDTYPE_PGID; } else { pid = task_pid(current); type = PIDTYPE_TGID; } get_pid(pid); - spin_unlock_irqrestore(&tty->ctrl_lock, flags); + spin_unlock_irqrestore(&tty->ctrl.lock, flags); __f_setown(filp, pid, type, 0); put_pid(pid); retval = 0; @@ -2336,7 +2332,7 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg) err = copy_to_user(arg, &tty->winsize, sizeof(*arg)); mutex_unlock(&tty->winsize_mutex); - return err ? -EFAULT: 0; + return err ? -EFAULT : 0; } /** @@ -2381,13 +2377,14 @@ EXPORT_SYMBOL(tty_do_resize); * * Locking: * Driver dependent. The default do_resize method takes the - * tty termios mutex and ctrl_lock. The console takes its own lock + * tty termios mutex and ctrl.lock. The console takes its own lock * then calls into the default method. */ static int tiocswinsz(struct tty_struct *tty, struct winsize __user *arg) { struct winsize tmp_ws; + if (copy_from_user(&tmp_ws, arg, sizeof(*arg))) return -EFAULT; @@ -2412,6 +2409,7 @@ static int tioccons(struct file *file) return -EPERM; if (file->f_op->write_iter == redirected_tty_write) { struct file *f; + spin_lock(&redirect_lock); f = redirect; redirect = NULL; @@ -2734,6 +2732,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case TIOCGEXCL: { int excl = test_bit(TTY_EXCLUSIVE, &tty->flags); + return put_user(excl, (int __user *)p); } case TIOCGETD: @@ -2748,6 +2747,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case TIOCGDEV: { unsigned int ret = new_encode_dev(tty_devnum(real_tty)); + return put_user(ret, (unsigned int __user *)p); } /* @@ -3006,7 +3006,7 @@ static int this_tty(const void *t, struct file *file, unsigned fd) return 0; return file_tty(file) != t ? 0 : fd + 1; } - + /* * This implements the "Secure Attention Key" --- the idea is to * prevent trojan horses by killing all processes associated with this @@ -3039,9 +3039,9 @@ void __do_SAK(struct tty_struct *tty) if (!tty) return; - spin_lock_irqsave(&tty->ctrl_lock, flags); - session = get_pid(tty->session); - spin_unlock_irqrestore(&tty->ctrl_lock, flags); + spin_lock_irqsave(&tty->ctrl.lock, flags); + session = get_pid(tty->ctrl.session); + spin_unlock_irqrestore(&tty->ctrl.lock, flags); tty_ldisc_flush(tty); @@ -3096,13 +3096,13 @@ void do_SAK(struct tty_struct *tty) return; schedule_work(&tty->SAK_work); } - EXPORT_SYMBOL(do_SAK); /* Must put_device() after it's unused! */ static struct device *tty_get_device(struct tty_struct *tty) { dev_t devt = tty_devnum(tty); + return class_find_device_by_devt(tty_class, devt); } @@ -3129,8 +3129,8 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx) kfree(tty); return NULL; } - tty->session = NULL; - tty->pgrp = NULL; + tty->ctrl.session = NULL; + tty->ctrl.pgrp = NULL; mutex_init(&tty->legacy_mutex); mutex_init(&tty->throttle_mutex); init_rwsem(&tty->termios_rwsem); @@ -3140,8 +3140,8 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx) init_waitqueue_head(&tty->read_wait); INIT_WORK(&tty->hangup_work, do_tty_hangup); mutex_init(&tty->atomic_write_lock); - spin_lock_init(&tty->ctrl_lock); - spin_lock_init(&tty->flow_lock); + spin_lock_init(&tty->ctrl.lock); + spin_lock_init(&tty->flow.lock); spin_lock_init(&tty->files_lock); INIT_LIST_HEAD(&tty->tty_files); INIT_WORK(&tty->SAK_work, do_SAK_work); @@ -3317,11 +3317,11 @@ err_put: EXPORT_SYMBOL_GPL(tty_register_device_attr); /** - * tty_unregister_device - unregister a tty device - * @driver: the tty driver that describes the tty device - * @index: the index in the tty driver for this tty device + * tty_unregister_device - unregister a tty device + * @driver: the tty driver that describes the tty device + * @index: the index in the tty driver for this tty device * - * If a tty device is registered with a call to tty_register_device() then + * If a tty device is registered with a call to tty_register_device() then * this function must be called when the tty device is gone. * * Locking: ?? diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index 41f7449d0464..507a25d692bb 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -54,7 +54,7 @@ * to be no queue on the device. */ -int tty_chars_in_buffer(struct tty_struct *tty) +unsigned int tty_chars_in_buffer(struct tty_struct *tty) { if (tty->ops->chars_in_buffer) return tty->ops->chars_in_buffer(tty); @@ -73,7 +73,7 @@ EXPORT_SYMBOL(tty_chars_in_buffer); * returned and data may be lost as there will be no flow control. */ -int tty_write_room(struct tty_struct *tty) +unsigned int tty_write_room(struct tty_struct *tty) { if (tty->ops->write_room) return tty->ops->write_room(tty); @@ -97,28 +97,6 @@ void tty_driver_flush_buffer(struct tty_struct *tty) EXPORT_SYMBOL(tty_driver_flush_buffer); /** - * tty_throttle - flow control - * @tty: terminal - * - * Indicate that a tty should stop transmitting data down the stack. - * Takes the termios rwsem to protect against parallel throttle/unthrottle - * and also to ensure the driver can consistently reference its own - * termios data at this point when implementing software flow control. - */ - -void tty_throttle(struct tty_struct *tty) -{ - down_write(&tty->termios_rwsem); - /* check TTY_THROTTLED first so it indicates our state */ - if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) && - tty->ops->throttle) - tty->ops->throttle(tty); - tty->flow_change = 0; - up_write(&tty->termios_rwsem); -} -EXPORT_SYMBOL(tty_throttle); - -/** * tty_unthrottle - flow control * @tty: terminal * @@ -146,10 +124,11 @@ EXPORT_SYMBOL(tty_unthrottle); * tty_throttle_safe - flow control * @tty: terminal * - * Similar to tty_throttle() but will only attempt throttle - * if tty->flow_change is TTY_THROTTLE_SAFE. Prevents an accidental - * throttle due to race conditions when throttling is conditional - * on factors evaluated prior to throttling. + * Indicate that a tty should stop transmitting data down the stack. + * tty_throttle_safe will only attempt throttle if tty->flow_change is + * TTY_THROTTLE_SAFE. Prevents an accidental throttle due to race + * conditions when throttling is conditional on factors evaluated prior to + * throttling. * * Returns 0 if tty is throttled (or was already throttled) */ @@ -301,6 +280,51 @@ int tty_termios_hw_change(const struct ktermios *a, const struct ktermios *b) EXPORT_SYMBOL(tty_termios_hw_change); /** + * tty_get_char_size - get size of a character + * @cflag: termios cflag value + * + * Get the size (in bits) of a character depending on @cflag's %CSIZE + * setting. + */ +unsigned char tty_get_char_size(unsigned int cflag) +{ + switch (cflag & CSIZE) { + case CS5: + return 5; + case CS6: + return 6; + case CS7: + return 7; + case CS8: + default: + return 8; + } +} +EXPORT_SYMBOL_GPL(tty_get_char_size); + +/** + * tty_get_frame_size - get size of a frame + * @cflag: termios cflag value + * + * Get the size (in bits) of a frame depending on @cflag's %CSIZE, %CSTOPB, + * and %PARENB setting. The result is a sum of character size, start and + * stop bits -- one bit each -- second stop bit (if set), and parity bit + * (if set). + */ +unsigned char tty_get_frame_size(unsigned int cflag) +{ + unsigned char bits = 2 + tty_get_char_size(cflag); + + if (cflag & CSTOPB) + bits++; + if (cflag & PARENB) + bits++; + + return bits; +} +EXPORT_SYMBOL_GPL(tty_get_frame_size); + +/** * tty_set_termios - update termios values * @tty: tty to update * @new_termios: desired new value @@ -846,20 +870,20 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file, return retval; switch (arg) { case TCOOFF: - spin_lock_irq(&tty->flow_lock); - if (!tty->flow_stopped) { - tty->flow_stopped = 1; + spin_lock_irq(&tty->flow.lock); + if (!tty->flow.tco_stopped) { + tty->flow.tco_stopped = true; __stop_tty(tty); } - spin_unlock_irq(&tty->flow_lock); + spin_unlock_irq(&tty->flow.lock); break; case TCOON: - spin_lock_irq(&tty->flow_lock); - if (tty->flow_stopped) { - tty->flow_stopped = 0; + spin_lock_irq(&tty->flow.lock); + if (tty->flow.tco_stopped) { + tty->flow.tco_stopped = false; __start_tty(tty); } - spin_unlock_irq(&tty->flow_lock); + spin_unlock_irq(&tty->flow.lock); break; case TCIOFF: if (STOP_CHAR(tty) != __DISABLED_CHAR) diff --git a/drivers/tty/tty_jobctrl.c b/drivers/tty/tty_jobctrl.c index 7813dc910a19..80b86a7992b5 100644 --- a/drivers/tty/tty_jobctrl.c +++ b/drivers/tty/tty_jobctrl.c @@ -20,7 +20,7 @@ static int is_ignored(int sig) } /** - * tty_check_change - check for POSIX terminal changes + * __tty_check_change - check for POSIX terminal changes * @tty: tty to check * @sig: signal to send * @@ -28,7 +28,7 @@ static int is_ignored(int sig) * not in the foreground, send a SIGTTOU. If the signal is blocked or * ignored, go ahead and perform the operation. (POSIX 7.2) * - * Locking: ctrl_lock + * Locking: ctrl.lock */ int __tty_check_change(struct tty_struct *tty, int sig) { @@ -42,9 +42,9 @@ int __tty_check_change(struct tty_struct *tty, int sig) rcu_read_lock(); pgrp = task_pgrp(current); - spin_lock_irqsave(&tty->ctrl_lock, flags); - tty_pgrp = tty->pgrp; - spin_unlock_irqrestore(&tty->ctrl_lock, flags); + spin_lock_irqsave(&tty->ctrl.lock, flags); + tty_pgrp = tty->ctrl.pgrp; + spin_unlock_irqrestore(&tty->ctrl.lock, flags); if (tty_pgrp && pgrp != tty_pgrp) { if (is_ignored(sig)) { @@ -85,7 +85,7 @@ void proc_clear_tty(struct task_struct *p) } /** - * proc_set_tty - set the controlling terminal + * __proc_set_tty - set the controlling terminal * @tty: tty structure * * Only callable by the session leader and only if it does not already have @@ -99,16 +99,16 @@ static void __proc_set_tty(struct tty_struct *tty) { unsigned long flags; - spin_lock_irqsave(&tty->ctrl_lock, flags); + spin_lock_irqsave(&tty->ctrl.lock, flags); /* * The session and fg pgrp references will be non-NULL if * tiocsctty() is stealing the controlling tty */ - put_pid(tty->session); - put_pid(tty->pgrp); - tty->pgrp = get_pid(task_pgrp(current)); - tty->session = get_pid(task_session(current)); - spin_unlock_irqrestore(&tty->ctrl_lock, flags); + put_pid(tty->ctrl.session); + put_pid(tty->ctrl.pgrp); + tty->ctrl.pgrp = get_pid(task_pgrp(current)); + tty->ctrl.session = get_pid(task_session(current)); + spin_unlock_irqrestore(&tty->ctrl.lock, flags); if (current->signal->tty) { tty_debug(tty, "current tty %s not NULL!!\n", current->signal->tty->name); @@ -135,7 +135,7 @@ void tty_open_proc_set_tty(struct file *filp, struct tty_struct *tty) spin_lock_irq(¤t->sighand->siglock); if (current->signal->leader && !current->signal->tty && - tty->session == NULL) { + tty->ctrl.session == NULL) { /* * Don't let a process that only has write access to the tty * obtain the privileges associated with having a tty as @@ -200,8 +200,8 @@ int tty_signal_session_leader(struct tty_struct *tty, int exit_session) struct pid *tty_pgrp = NULL; read_lock(&tasklist_lock); - if (tty->session) { - do_each_pid_task(tty->session, PIDTYPE_SID, p) { + if (tty->ctrl.session) { + do_each_pid_task(tty->ctrl.session, PIDTYPE_SID, p) { spin_lock_irq(&p->sighand->siglock); if (p->signal->tty == tty) { p->signal->tty = NULL; @@ -218,13 +218,14 @@ int tty_signal_session_leader(struct tty_struct *tty, int exit_session) __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p); __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p); put_pid(p->signal->tty_old_pgrp); /* A noop */ - spin_lock(&tty->ctrl_lock); - tty_pgrp = get_pid(tty->pgrp); - if (tty->pgrp) - p->signal->tty_old_pgrp = get_pid(tty->pgrp); - spin_unlock(&tty->ctrl_lock); + spin_lock(&tty->ctrl.lock); + tty_pgrp = get_pid(tty->ctrl.pgrp); + if (tty->ctrl.pgrp) + p->signal->tty_old_pgrp = + get_pid(tty->ctrl.pgrp); + spin_unlock(&tty->ctrl.lock); spin_unlock_irq(&p->sighand->siglock); - } while_each_pid_task(tty->session, PIDTYPE_SID, p); + } while_each_pid_task(tty->ctrl.session, PIDTYPE_SID, p); } read_unlock(&tasklist_lock); @@ -309,12 +310,12 @@ void disassociate_ctty(int on_exit) unsigned long flags; tty_lock(tty); - spin_lock_irqsave(&tty->ctrl_lock, flags); - put_pid(tty->session); - put_pid(tty->pgrp); - tty->session = NULL; - tty->pgrp = NULL; - spin_unlock_irqrestore(&tty->ctrl_lock, flags); + spin_lock_irqsave(&tty->ctrl.lock, flags); + put_pid(tty->ctrl.session); + put_pid(tty->ctrl.pgrp); + tty->ctrl.session = NULL; + tty->ctrl.pgrp = NULL; + spin_unlock_irqrestore(&tty->ctrl.lock, flags); tty_unlock(tty); tty_kref_put(tty); } @@ -363,7 +364,8 @@ static int tiocsctty(struct tty_struct *tty, struct file *file, int arg) tty_lock(tty); read_lock(&tasklist_lock); - if (current->signal->leader && (task_session(current) == tty->session)) + if (current->signal->leader && + task_session(current) == tty->ctrl.session) goto unlock; /* @@ -375,7 +377,7 @@ static int tiocsctty(struct tty_struct *tty, struct file *file, int arg) goto unlock; } - if (tty->session) { + if (tty->ctrl.session) { /* * This tty is already the controlling * tty for another session group! @@ -384,7 +386,7 @@ static int tiocsctty(struct tty_struct *tty, struct file *file, int arg) /* * Steal it away */ - session_clear_tty(tty->session); + session_clear_tty(tty->ctrl.session); } else { ret = -EPERM; goto unlock; @@ -416,9 +418,9 @@ struct pid *tty_get_pgrp(struct tty_struct *tty) unsigned long flags; struct pid *pgrp; - spin_lock_irqsave(&tty->ctrl_lock, flags); - pgrp = get_pid(tty->pgrp); - spin_unlock_irqrestore(&tty->ctrl_lock, flags); + spin_lock_irqsave(&tty->ctrl.lock, flags); + pgrp = get_pid(tty->ctrl.pgrp); + spin_unlock_irqrestore(&tty->ctrl.lock, flags); return pgrp; } @@ -499,10 +501,10 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t if (pgrp_nr < 0) return -EINVAL; - spin_lock_irq(&real_tty->ctrl_lock); + spin_lock_irq(&real_tty->ctrl.lock); if (!current->signal->tty || (current->signal->tty != real_tty) || - (real_tty->session != task_session(current))) { + (real_tty->ctrl.session != task_session(current))) { retval = -ENOTTY; goto out_unlock_ctrl; } @@ -515,12 +517,12 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t if (session_of_pgrp(pgrp) != task_session(current)) goto out_unlock; retval = 0; - put_pid(real_tty->pgrp); - real_tty->pgrp = get_pid(pgrp); + put_pid(real_tty->ctrl.pgrp); + real_tty->ctrl.pgrp = get_pid(pgrp); out_unlock: rcu_read_unlock(); out_unlock_ctrl: - spin_unlock_irq(&real_tty->ctrl_lock); + spin_unlock_irq(&real_tty->ctrl.lock); return retval; } @@ -545,16 +547,16 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t _ if (tty == real_tty && current->signal->tty != real_tty) return -ENOTTY; - spin_lock_irqsave(&real_tty->ctrl_lock, flags); - if (!real_tty->session) + spin_lock_irqsave(&real_tty->ctrl.lock, flags); + if (!real_tty->ctrl.session) goto err; - sid = pid_vnr(real_tty->session); - spin_unlock_irqrestore(&real_tty->ctrl_lock, flags); + sid = pid_vnr(real_tty->ctrl.session); + spin_unlock_irqrestore(&real_tty->ctrl.lock, flags); return put_user(sid, p); err: - spin_unlock_irqrestore(&real_tty->ctrl_lock, flags); + spin_unlock_irqrestore(&real_tty->ctrl.lock, flags); return -ENOTTY; } diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 03f414172f34..756a4bfa6a69 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -48,7 +48,6 @@ static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; /** * tty_register_ldisc - install a line discipline - * @disc: ldisc number * @new_ldisc: pointer to the ldisc object * * Installs a new line discipline into the kernel. The discipline @@ -59,18 +58,16 @@ static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; * takes tty_ldiscs_lock to guard against ldisc races */ -int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc) +int tty_register_ldisc(struct tty_ldisc_ops *new_ldisc) { unsigned long flags; int ret = 0; - if (disc < N_TTY || disc >= NR_LDISCS) + if (new_ldisc->num < N_TTY || new_ldisc->num >= NR_LDISCS) return -EINVAL; raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); - tty_ldiscs[disc] = new_ldisc; - new_ldisc->num = disc; - new_ldisc->refcount = 0; + tty_ldiscs[new_ldisc->num] = new_ldisc; raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); return ret; @@ -79,7 +76,7 @@ EXPORT_SYMBOL(tty_register_ldisc); /** * tty_unregister_ldisc - unload a line discipline - * @disc: ldisc number + * @ldisc: ldisc number * * Remove a line discipline from the kernel providing it is not * currently in use. @@ -88,22 +85,13 @@ EXPORT_SYMBOL(tty_register_ldisc); * takes tty_ldiscs_lock to guard against ldisc races */ -int tty_unregister_ldisc(int disc) +void tty_unregister_ldisc(struct tty_ldisc_ops *ldisc) { unsigned long flags; - int ret = 0; - - if (disc < N_TTY || disc >= NR_LDISCS) - return -EINVAL; raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); - if (tty_ldiscs[disc]->refcount) - ret = -EBUSY; - else - tty_ldiscs[disc] = NULL; + tty_ldiscs[ldisc->num] = NULL; raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); - - return ret; } EXPORT_SYMBOL(tty_unregister_ldisc); @@ -117,10 +105,8 @@ static struct tty_ldisc_ops *get_ldops(int disc) ldops = tty_ldiscs[disc]; if (ldops) { ret = ERR_PTR(-EAGAIN); - if (try_module_get(ldops->owner)) { - ldops->refcount++; + if (try_module_get(ldops->owner)) ret = ldops; - } } raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); return ret; @@ -131,7 +117,6 @@ static void put_ldops(struct tty_ldisc_ops *ldops) unsigned long flags; raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); - ldops->refcount--; module_put(ldops->owner); raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); } diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 303c198fbf5c..2f1061a9d926 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -468,7 +468,8 @@ int tty_port_block_til_ready(struct tty_port *port, DEFINE_WAIT(wait); /* if non-blocking mode is set we can pass directly to open unless - the port has just hung up or is in another error state */ + * the port has just hung up or is in another error state. + */ if (tty_io_error(tty)) { tty_port_set_active(port, 1); return 0; @@ -485,8 +486,9 @@ int tty_port_block_til_ready(struct tty_port *port, do_clocal = 1; /* Block waiting until we can proceed. We may need to wait for the - carrier, but we must also wait for any close that is in progress - before the next open may complete */ + * carrier, but we must also wait for any close that is in progress + * before the next open may complete. + */ retval = 0; @@ -503,7 +505,8 @@ int tty_port_block_til_ready(struct tty_port *port, prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE); /* Check for a hangup or uninitialised port. - Return accordingly */ + * Return accordingly. + */ if (tty_hung_up_p(filp) || !tty_port_initialized(port)) { if (port->flags & ASYNC_HUP_NOTIFY) retval = -EAGAIN; @@ -530,7 +533,8 @@ int tty_port_block_til_ready(struct tty_port *port, finish_wait(&port->open_wait, &wait); /* Update counts. A parallel hangup will have set count to zero and - we must not mess that up further */ + * we must not mess that up further. + */ spin_lock_irqsave(&port->lock, flags); if (!tty_hung_up_p(filp)) port->count++; @@ -587,7 +591,7 @@ int tty_port_close_start(struct tty_port *port, if (tty_port_initialized(port)) { /* Don't block on a stalled port, just pull the chain */ - if (tty->flow_stopped) + if (tty->flow.tco_stopped) tty_driver_flush_buffer(tty); if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) tty_wait_until_sent(tty, port->closing_wait); @@ -688,6 +692,7 @@ int tty_port_open(struct tty_port *port, struct tty_struct *tty, clear_bit(TTY_IO_ERROR, &tty->flags); if (port->ops->activate) { int retval = port->ops->activate(port, tty); + if (retval) { mutex_unlock(&port->mutex); return retval; @@ -698,5 +703,4 @@ int tty_port_open(struct tty_port *port, struct tty_struct *tty, mutex_unlock(&port->mutex); return tty_port_block_til_ready(port, tty, filp); } - EXPORT_SYMBOL(tty_port_open); diff --git a/drivers/tty/ttynull.c b/drivers/tty/ttynull.c index 17f05b7eb6d3..af3311a24917 100644 --- a/drivers/tty/ttynull.c +++ b/drivers/tty/ttynull.c @@ -35,7 +35,7 @@ static int ttynull_write(struct tty_struct *tty, const unsigned char *buf, return count; } -static int ttynull_write_room(struct tty_struct *tty) +static unsigned int ttynull_write_room(struct tty_struct *tty) { return 65536; } diff --git a/drivers/tty/vcc.c b/drivers/tty/vcc.c index 0a3a71e14df4..d06bcc3b4c07 100644 --- a/drivers/tty/vcc.c +++ b/drivers/tty/vcc.c @@ -473,9 +473,9 @@ static struct vio_version vcc_versions[] = { static struct tty_port_operations vcc_port_ops = { 0 }; -static ssize_t vcc_sysfs_domain_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t domain_show(struct device *dev, + struct device_attribute *attr, + char *buf) { struct vcc_port *port; int rv; @@ -505,9 +505,9 @@ static int vcc_send_ctl(struct vcc_port *port, int ctl) return rv; } -static ssize_t vcc_sysfs_break_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t break_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct vcc_port *port; unsigned long flags; @@ -530,8 +530,8 @@ static ssize_t vcc_sysfs_break_store(struct device *dev, return rv; } -static DEVICE_ATTR(domain, 0400, vcc_sysfs_domain_show, NULL); -static DEVICE_ATTR(break, 0200, NULL, vcc_sysfs_break_store); +static DEVICE_ATTR_ADMIN_RO(domain); +static DEVICE_ATTR_WO(break); static struct attribute *vcc_sysfs_entries[] = { &dev_attr_domain.attr, @@ -668,7 +668,7 @@ free_port: * * Return: status of removal */ -static int vcc_remove(struct vio_dev *vdev) +static void vcc_remove(struct vio_dev *vdev) { struct vcc_port *port = dev_get_drvdata(&vdev->dev); @@ -703,8 +703,6 @@ static int vcc_remove(struct vio_dev *vdev) kfree(port->domain); kfree(port); } - - return 0; } static const struct vio_device_id vcc_match[] = { @@ -870,10 +868,10 @@ static int vcc_write(struct tty_struct *tty, const unsigned char *buf, return total_sent ? total_sent : rv; } -static int vcc_write_room(struct tty_struct *tty) +static unsigned int vcc_write_room(struct tty_struct *tty) { struct vcc_port *port; - u64 num; + unsigned int num; port = vcc_get_ne(tty->index); if (unlikely(!port)) { @@ -888,10 +886,10 @@ static int vcc_write_room(struct tty_struct *tty) return num; } -static int vcc_chars_in_buffer(struct tty_struct *tty) +static unsigned int vcc_chars_in_buffer(struct tty_struct *tty) { struct vcc_port *port; - u64 num; + unsigned int num; port = vcc_get_ne(tty->index); if (unlikely(!port)) { diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 5d2309742718..4b0d69042ceb 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -515,7 +515,7 @@ static void fn_hold(struct vc_data *vc) * these routines are also activated by ^S/^Q. * (And SCROLLOCK can also be set by the ioctl KDSKBLED.) */ - if (tty->stopped) + if (tty->flow.stopped) start_tty(tty); else stop_tty(tty); diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index f245a5acf7e9..f7755e73696e 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -33,7 +33,7 @@ #include <linux/sched/signal.h> /* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */ -#define isspace(c) ((c) == ' ') +#define is_space_on_vt(c) ((c) == ' ') /* FIXME: all this needs locking */ static struct vc_selection { @@ -109,7 +109,7 @@ static inline int inword(const u32 c) } /** - * set loadlut - load the LUT table + * sel_loadlut() - load the LUT table * @p: user table * * Load the LUT table from user space. The caller must hold the console @@ -209,7 +209,7 @@ static int vc_selection_store_chars(struct vc_data *vc, bool unicode) bp += store_utf8(c, bp); else *bp++ = c; - if (!isspace(c)) + if (!is_space_on_vt(c)) obp = bp; if (!((i + 2) % vc->vc_size_row)) { /* strip trailing blanks from line and add newline, @@ -238,9 +238,9 @@ static int vc_do_selection(struct vc_data *vc, unsigned short mode, int ps, new_sel_end = pe; break; case TIOCL_SELWORD: /* word-by-word selection */ - spc = isspace(sel_pos(ps, unicode)); + spc = is_space_on_vt(sel_pos(ps, unicode)); for (new_sel_start = ps; ; ps -= 2) { - if ((spc && !isspace(sel_pos(ps, unicode))) || + if ((spc && !is_space_on_vt(sel_pos(ps, unicode))) || (!spc && !inword(sel_pos(ps, unicode)))) break; new_sel_start = ps; @@ -248,9 +248,9 @@ static int vc_do_selection(struct vc_data *vc, unsigned short mode, int ps, break; } - spc = isspace(sel_pos(pe, unicode)); + spc = is_space_on_vt(sel_pos(pe, unicode)); for (new_sel_end = pe; ; pe += 2) { - if ((spc && !isspace(sel_pos(pe, unicode))) || + if ((spc && !is_space_on_vt(sel_pos(pe, unicode))) || (!spc && !inword(sel_pos(pe, unicode)))) break; new_sel_end = pe; @@ -276,12 +276,12 @@ static int vc_do_selection(struct vc_data *vc, unsigned short mode, int ps, /* select to end of line if on trailing space */ if (new_sel_end > new_sel_start && !atedge(new_sel_end, vc->vc_size_row) && - isspace(sel_pos(new_sel_end, unicode))) { + is_space_on_vt(sel_pos(new_sel_end, unicode))) { for (pe = new_sel_end + 2; ; pe += 2) - if (!isspace(sel_pos(pe, unicode)) || + if (!is_space_on_vt(sel_pos(pe, unicode)) || atedge(pe, vc->vc_size_row)) break; - if (isspace(sel_pos(pe, unicode))) + if (is_space_on_vt(sel_pos(pe, unicode))) new_sel_end = pe; } if (vc_sel.start == -1) /* no current selection */ diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index fa1548d4f94b..ef981d3b7bb4 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1189,7 +1189,7 @@ static inline int resize_screen(struct vc_data *vc, int width, int height, * information and perform any necessary signal handling. * * Caller must hold the console semaphore. Takes the termios rwsem and - * ctrl_lock of the tty IFF a tty is passed. + * ctrl.lock of the tty IFF a tty is passed. */ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, @@ -1355,7 +1355,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) * the actual work. * * Takes the console sem and the called methods then take the tty - * termios_rwsem and the tty ctrl_lock in that order. + * termios_rwsem and the tty ctrl.lock in that order. */ static int vt_resize(struct tty_struct *tty, struct winsize *ws) { @@ -2888,7 +2888,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co param.vc = vc; - while (!tty->stopped && count) { + while (!tty->flow.stopped && count) { int orig = *buf; buf++; n++; @@ -3260,23 +3260,16 @@ static int con_write(struct tty_struct *tty, const unsigned char *buf, int count static int con_put_char(struct tty_struct *tty, unsigned char ch) { - if (in_interrupt()) - return 0; /* n_r3964 calls put_char() from interrupt context */ return do_con_write(tty, &ch, 1); } -static int con_write_room(struct tty_struct *tty) +static unsigned int con_write_room(struct tty_struct *tty) { - if (tty->stopped) + if (tty->flow.stopped) return 0; return 32768; /* No limit, really; we're not buffering */ } -static int con_chars_in_buffer(struct tty_struct *tty) -{ - return 0; /* we're not buffering */ -} - /* * con_throttle and con_unthrottle are only used for * paste_selection(), which has to stuff in a large number of @@ -3523,7 +3516,6 @@ static const struct tty_operations con_ops = { .write_room = con_write_room, .put_char = con_put_char, .flush_chars = con_flush_chars, - .chars_in_buffer = con_chars_in_buffer, .ioctl = vt_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = vt_compat_ioctl, diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig index 5531f3afeb21..2e16c5338e5b 100644 --- a/drivers/uio/Kconfig +++ b/drivers/uio/Kconfig @@ -18,7 +18,7 @@ config UIO_CIF depends on PCI help Driver for Hilscher CIF DeviceNet and Profibus cards. This - driver requires a userspace component called cif that handles + driver requires a userspace component called cif that handles all of the heavy lifting and can be found at: <http://www.osadl.org/projects/downloads/UIO/user/> diff --git a/drivers/uio/uio_aec.c b/drivers/uio/uio_aec.c index 32357f8a92b5..64eafd59e6e7 100644 --- a/drivers/uio/uio_aec.c +++ b/drivers/uio/uio_aec.c @@ -133,7 +133,7 @@ static void remove(struct pci_dev *pdev) uio_unregister_device(info); pci_release_regions(pdev); pci_disable_device(pdev); - iounmap(info->priv); + pci_iounmap(pdev, info->priv); } static struct pci_driver pci_driver = { diff --git a/drivers/uio/uio_pci_generic.c b/drivers/uio/uio_pci_generic.c index 3bb0b0075467..e03f9b532a96 100644 --- a/drivers/uio/uio_pci_generic.c +++ b/drivers/uio/uio_pci_generic.c @@ -72,7 +72,9 @@ static int probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct uio_pci_generic_dev *gdev; + struct uio_mem *uiomem; int err; + int i; err = pcim_enable_device(pdev); if (err) { @@ -101,6 +103,36 @@ static int probe(struct pci_dev *pdev, "no support for interrupts?\n"); } + uiomem = &gdev->info.mem[0]; + for (i = 0; i < MAX_UIO_MAPS; ++i) { + struct resource *r = &pdev->resource[i]; + + if (r->flags != (IORESOURCE_SIZEALIGN | IORESOURCE_MEM)) + continue; + + if (uiomem >= &gdev->info.mem[MAX_UIO_MAPS]) { + dev_warn( + &pdev->dev, + "device has more than " __stringify( + MAX_UIO_MAPS) " I/O memory resources.\n"); + break; + } + + uiomem->memtype = UIO_MEM_PHYS; + uiomem->addr = r->start & PAGE_MASK; + uiomem->offs = r->start & ~PAGE_MASK; + uiomem->size = + (uiomem->offs + resource_size(r) + PAGE_SIZE - 1) & + PAGE_MASK; + uiomem->name = r->name; + ++uiomem; + } + + while (uiomem < &gdev->info.mem[MAX_UIO_MAPS]) { + uiomem->size = 0; + ++uiomem; + } + return devm_uio_register_device(&pdev->dev, &gdev->info); } diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 4d3947476f0e..4ce7cba2b48a 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -180,7 +180,7 @@ struct cxacru_data { struct mutex poll_state_serialize; enum cxacru_poll_state poll_state; - /* contol handles */ + /* control handles */ struct mutex cm_serialize; u8 *rcv_buf; u8 *snd_buf; diff --git a/drivers/usb/cdns3/cdns3-ep0.c b/drivers/usb/cdns3/cdns3-ep0.c index 9a17802275d5..02ec7ab4bb48 100644 --- a/drivers/usb/cdns3/cdns3-ep0.c +++ b/drivers/usb/cdns3/cdns3-ep0.c @@ -677,7 +677,7 @@ static int cdns3_gadget_ep0_set_halt(struct usb_ep *ep, int value) } /** - * cdns3_gadget_ep0_queue Transfer data on endpoint zero + * cdns3_gadget_ep0_queue - Transfer data on endpoint zero * @ep: pointer to endpoint zero object * @request: pointer to request object * @gfp_flags: gfp flags @@ -772,7 +772,7 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep, } /** - * cdns3_gadget_ep_set_wedge Set wedge on selected endpoint + * cdns3_gadget_ep_set_wedge - Set wedge on selected endpoint * @ep: endpoint object * * Returns 0 @@ -865,7 +865,7 @@ void cdns3_ep0_config(struct cdns3_device *priv_dev) } /** - * cdns3_init_ep0 Initializes software endpoint 0 of gadget + * cdns3_init_ep0 - Initializes software endpoint 0 of gadget * @priv_dev: extended gadget object * @priv_ep: extended endpoint object * diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c index 5281f8d3fb3d..5d8c982019af 100644 --- a/drivers/usb/cdns3/cdns3-gadget.c +++ b/drivers/usb/cdns3/cdns3-gadget.c @@ -155,7 +155,7 @@ static struct cdns3_request *cdns3_next_priv_request(struct list_head *list) } /** - * select_ep - selects endpoint + * cdns3_select_ep - selects endpoint * @priv_dev: extended gadget object * @ep: endpoint address */ @@ -430,9 +430,7 @@ static int cdns3_start_all_request(struct cdns3_device *priv_dev, if (ret) return ret; - list_del(&request->list); - list_add_tail(&request->list, - &priv_ep->pending_req_list); + list_move_tail(&request->list, &priv_ep->pending_req_list); if (request->stream_id != 0 || (priv_ep->flags & EP_TDLCHK_EN)) break; } @@ -484,7 +482,7 @@ static void __cdns3_descmiss_copy_data(struct usb_request *request, } /** - * cdns3_wa2_descmiss_copy_data copy data from internal requests to + * cdns3_wa2_descmiss_copy_data - copy data from internal requests to * request queued by class driver. * @priv_ep: extended endpoint object * @request: request object @@ -1835,7 +1833,7 @@ __must_hold(&priv_dev->lock) } /** - * cdns3_device_irq_handler- interrupt handler for device part of controller + * cdns3_device_irq_handler - interrupt handler for device part of controller * * @irq: irq number for cdns3 core device * @data: structure of cdns3 @@ -1879,7 +1877,7 @@ static irqreturn_t cdns3_device_irq_handler(int irq, void *data) } /** - * cdns3_device_thread_irq_handler- interrupt handler for device part + * cdns3_device_thread_irq_handler - interrupt handler for device part * of controller * * @irq: irq number for cdns3 core device @@ -2022,7 +2020,7 @@ static void cdns3_configure_dmult(struct cdns3_device *priv_dev, } /** - * cdns3_ep_config Configure hardware endpoint + * cdns3_ep_config - Configure hardware endpoint * @priv_ep: extended endpoint object * @enable: set EP_CFG_ENABLE bit in ep_cfg register. */ @@ -2221,7 +2219,7 @@ usb_ep *cdns3_gadget_match_ep(struct usb_gadget *gadget, } /** - * cdns3_gadget_ep_alloc_request Allocates request + * cdns3_gadget_ep_alloc_request - Allocates request * @ep: endpoint object associated with request * @gfp_flags: gfp flags * @@ -2244,7 +2242,7 @@ struct usb_request *cdns3_gadget_ep_alloc_request(struct usb_ep *ep, } /** - * cdns3_gadget_ep_free_request Free memory occupied by request + * cdns3_gadget_ep_free_request - Free memory occupied by request * @ep: endpoint object associated with request * @request: request to free memory */ @@ -2261,7 +2259,7 @@ void cdns3_gadget_ep_free_request(struct usb_ep *ep, } /** - * cdns3_gadget_ep_enable Enable endpoint + * cdns3_gadget_ep_enable - Enable endpoint * @ep: endpoint object * @desc: endpoint descriptor * @@ -2396,7 +2394,7 @@ exit: } /** - * cdns3_gadget_ep_disable Disable endpoint + * cdns3_gadget_ep_disable - Disable endpoint * @ep: endpoint object * * Returns 0 on success, error code elsewhere @@ -2486,7 +2484,7 @@ static int cdns3_gadget_ep_disable(struct usb_ep *ep) } /** - * cdns3_gadget_ep_queue Transfer data on endpoint + * __cdns3_gadget_ep_queue - Transfer data on endpoint * @ep: endpoint object * @request: request object * @gfp_flags: gfp flags @@ -2586,7 +2584,7 @@ static int cdns3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, } /** - * cdns3_gadget_ep_dequeue Remove request from transfer queue + * cdns3_gadget_ep_dequeue - Remove request from transfer queue * @ep: endpoint object associated with request * @request: request object * @@ -2653,7 +2651,7 @@ not_found: } /** - * __cdns3_gadget_ep_set_halt Sets stall on selected endpoint + * __cdns3_gadget_ep_set_halt - Sets stall on selected endpoint * Should be called after acquiring spin_lock and selecting ep * @priv_ep: endpoint object to set stall on. */ @@ -2674,7 +2672,7 @@ void __cdns3_gadget_ep_set_halt(struct cdns3_endpoint *priv_ep) } /** - * __cdns3_gadget_ep_clear_halt Clears stall on selected endpoint + * __cdns3_gadget_ep_clear_halt - Clears stall on selected endpoint * Should be called after acquiring spin_lock and selecting ep * @priv_ep: endpoint object to clear stall on */ @@ -2719,7 +2717,7 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep) } /** - * cdns3_gadget_ep_set_halt Sets/clears stall on selected endpoint + * cdns3_gadget_ep_set_halt - Sets/clears stall on selected endpoint * @ep: endpoint object to set/clear stall on * @value: 1 for set stall, 0 for clear stall * @@ -2765,7 +2763,7 @@ static const struct usb_ep_ops cdns3_gadget_ep_ops = { }; /** - * cdns3_gadget_get_frame Returns number of actual ITP frame + * cdns3_gadget_get_frame - Returns number of actual ITP frame * @gadget: gadget object * * Returns number of actual ITP frame @@ -2874,7 +2872,7 @@ static void cdns3_gadget_config(struct cdns3_device *priv_dev) } /** - * cdns3_gadget_udc_start Gadget start + * cdns3_gadget_udc_start - Gadget start * @gadget: gadget object * @driver: driver which operates on this gadget * @@ -2920,7 +2918,7 @@ static int cdns3_gadget_udc_start(struct usb_gadget *gadget, } /** - * cdns3_gadget_udc_stop Stops gadget + * cdns3_gadget_udc_stop - Stops gadget * @gadget: gadget object * * Returns 0 @@ -2983,7 +2981,7 @@ static void cdns3_free_all_eps(struct cdns3_device *priv_dev) } /** - * cdns3_init_eps Initializes software endpoints of gadget + * cdns3_init_eps - Initializes software endpoints of gadget * @priv_dev: extended gadget object * * Returns 0 on success, error code elsewhere diff --git a/drivers/usb/cdns3/cdns3-imx.c b/drivers/usb/cdns3/cdns3-imx.c index 74e758dc0895..59860d1753fd 100644 --- a/drivers/usb/cdns3/cdns3-imx.c +++ b/drivers/usb/cdns3/cdns3-imx.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/** +/* * cdns3-imx.c - NXP i.MX specific Glue layer for Cadence USB Controller * * Copyright (C) 2019 NXP diff --git a/drivers/usb/cdns3/cdns3-plat.c b/drivers/usb/cdns3/cdns3-plat.c index e1deeada425c..4d0f027e5bd3 100644 --- a/drivers/usb/cdns3/cdns3-plat.c +++ b/drivers/usb/cdns3/cdns3-plat.c @@ -170,7 +170,7 @@ err_phy3_init: } /** - * cdns3_remove - unbind drd driver and clean up + * cdns3_plat_remove() - unbind drd driver and clean up * @pdev: Pointer to Linux platform device * * Returns 0 on success otherwise negative errno diff --git a/drivers/usb/cdns3/cdns3-ti.c b/drivers/usb/cdns3/cdns3-ti.c index eccb1c766bba..07c318770362 100644 --- a/drivers/usb/cdns3/cdns3-ti.c +++ b/drivers/usb/cdns3/cdns3-ti.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/** +/* * cdns3-ti.c - TI specific Glue layer for Cadence USB Controller * * Copyright (C) 2019 Texas Instruments Incorporated - https://www.ti.com diff --git a/drivers/usb/cdns3/cdnsp-gadget.c b/drivers/usb/cdns3/cdnsp-gadget.c index c083985e387b..c23f53e9b1ef 100644 --- a/drivers/usb/cdns3/cdnsp-gadget.c +++ b/drivers/usb/cdns3/cdnsp-gadget.c @@ -56,7 +56,8 @@ u32 cdnsp_port_state_to_neutral(u32 state) } /** - * Find the offset of the extended capabilities with capability ID id. + * cdnsp_find_next_ext_cap - Find the offset of the extended capabilities + * with capability ID id. * @base: PCI MMIO registers base address. * @start: Address at which to start looking, (0 or HCC_PARAMS to start at * beginning of list) @@ -1151,7 +1152,7 @@ static int cdnsp_gadget_ep_set_halt(struct usb_ep *ep, int value) struct cdnsp_ep *pep = to_cdnsp_ep(ep); struct cdnsp_device *pdev = pep->pdev; struct cdnsp_request *preq; - unsigned long flags = 0; + unsigned long flags; int ret; spin_lock_irqsave(&pdev->lock, flags); @@ -1176,7 +1177,7 @@ static int cdnsp_gadget_ep_set_wedge(struct usb_ep *ep) { struct cdnsp_ep *pep = to_cdnsp_ep(ep); struct cdnsp_device *pdev = pep->pdev; - unsigned long flags = 0; + unsigned long flags; int ret; spin_lock_irqsave(&pdev->lock, flags); diff --git a/drivers/usb/cdns3/cdnsp-mem.c b/drivers/usb/cdns3/cdnsp-mem.c index 5d4c4bfe15b7..a47948a1623f 100644 --- a/drivers/usb/cdns3/cdnsp-mem.c +++ b/drivers/usb/cdns3/cdnsp-mem.c @@ -1082,9 +1082,8 @@ void cdnsp_mem_cleanup(struct cdnsp_device *pdev) dma_pool_destroy(pdev->device_pool); pdev->device_pool = NULL; - if (pdev->dcbaa) - dma_free_coherent(dev, sizeof(*pdev->dcbaa), - pdev->dcbaa, pdev->dcbaa->dma); + dma_free_coherent(dev, sizeof(*pdev->dcbaa), + pdev->dcbaa, pdev->dcbaa->dma); pdev->dcbaa = NULL; diff --git a/drivers/usb/cdns3/cdnsp-trace.h b/drivers/usb/cdns3/cdnsp-trace.h index 5aa88ca012de..6a2571c6aa9e 100644 --- a/drivers/usb/cdns3/cdnsp-trace.h +++ b/drivers/usb/cdns3/cdnsp-trace.h @@ -138,7 +138,7 @@ DECLARE_EVENT_CLASS(cdnsp_log_simple, __string(text, msg) ), TP_fast_assign( - __assign_str(text, msg) + __assign_str(text, msg); ), TP_printk("%s", __get_str(text)) ); diff --git a/drivers/usb/cdns3/core.c b/drivers/usb/cdns3/core.c index bb739d88179f..dbcdf3b24b47 100644 --- a/drivers/usb/cdns3/core.c +++ b/drivers/usb/cdns3/core.c @@ -332,7 +332,7 @@ exit: } /** - * cdsn3_role_get - get current role of controller. + * cdns_role_get - get current role of controller. * * @sw: pointer to USB role switch structure * @@ -419,7 +419,7 @@ static irqreturn_t cdns_wakeup_irq(int irq, void *data) } /** - * cdns_probe - probe for cdns3/cdnsp core device + * cdns_init - probe for cdns3/cdnsp core device * @cdns: Pointer to cdns structure. * * Returns 0 on success otherwise negative errno diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index 0697eb980e5f..99440baa6458 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h @@ -195,7 +195,6 @@ struct hw_bank { * @phy: pointer to PHY, if any * @usb_phy: pointer to USB PHY, if any and if using the USB PHY framework * @hcd: pointer to usb_hcd for ehci host driver - * @debugfs: root dentry for this controller in debugfs * @id_event: indicates there is an id event, and handled at ci_otg_work * @b_sess_valid_event: indicates there is a vbus event, and handled * at ci_otg_work @@ -249,7 +248,6 @@ struct ci_hdrc { /* old usb_phy interface */ struct usb_phy *usb_phy; struct usb_hcd *hcd; - struct dentry *debugfs; bool id_event; bool b_sess_valid_event; bool imx28_write_fix; diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 3f6c21406dbd..2b18f5088ae4 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -335,7 +335,7 @@ static int _ci_usb_phy_init(struct ci_hdrc *ci) } /** - * _ci_usb_phy_exit: deinitialize phy taking in account both phy and usb_phy + * ci_usb_phy_exit: deinitialize phy taking in account both phy and usb_phy * interfaces * @ci: the controller */ diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index da5d18cf6840..faf6b078b6c4 100644 --- a/drivers/usb/chipidea/debug.c +++ b/drivers/usb/chipidea/debug.c @@ -342,26 +342,20 @@ DEFINE_SHOW_ATTRIBUTE(ci_registers); */ void dbg_create_files(struct ci_hdrc *ci) { - ci->debugfs = debugfs_create_dir(dev_name(ci->dev), usb_debug_root); - - debugfs_create_file("device", S_IRUGO, ci->debugfs, ci, - &ci_device_fops); - debugfs_create_file("port_test", S_IRUGO | S_IWUSR, ci->debugfs, ci, - &ci_port_test_fops); - debugfs_create_file("qheads", S_IRUGO, ci->debugfs, ci, - &ci_qheads_fops); - debugfs_create_file("requests", S_IRUGO, ci->debugfs, ci, - &ci_requests_fops); - - if (ci_otg_is_fsm_mode(ci)) { - debugfs_create_file("otg", S_IRUGO, ci->debugfs, ci, - &ci_otg_fops); - } + struct dentry *dir; + + dir = debugfs_create_dir(dev_name(ci->dev), usb_debug_root); + + debugfs_create_file("device", S_IRUGO, dir, ci, &ci_device_fops); + debugfs_create_file("port_test", S_IRUGO | S_IWUSR, dir, ci, &ci_port_test_fops); + debugfs_create_file("qheads", S_IRUGO, dir, ci, &ci_qheads_fops); + debugfs_create_file("requests", S_IRUGO, dir, ci, &ci_requests_fops); + + if (ci_otg_is_fsm_mode(ci)) + debugfs_create_file("otg", S_IRUGO, dir, ci, &ci_otg_fops); - debugfs_create_file("role", S_IRUGO | S_IWUSR, ci->debugfs, ci, - &ci_role_fops); - debugfs_create_file("registers", S_IRUGO, ci->debugfs, ci, - &ci_registers_fops); + debugfs_create_file("role", S_IRUGO | S_IWUSR, dir, ci, &ci_role_fops); + debugfs_create_file("registers", S_IRUGO, dir, ci, &ci_registers_fops); } /** @@ -370,5 +364,5 @@ void dbg_create_files(struct ci_hdrc *ci) */ void dbg_remove_files(struct ci_hdrc *ci) { - debugfs_remove_recursive(ci->debugfs); + debugfs_remove(debugfs_lookup(dev_name(ci->dev), usb_debug_root)); } diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c index d3aada3ce7ec..8dd59282827b 100644 --- a/drivers/usb/chipidea/otg.c +++ b/drivers/usb/chipidea/otg.c @@ -22,7 +22,7 @@ #include "otg_fsm.h" /** - * hw_read_otgsc returns otgsc register bits value. + * hw_read_otgsc - returns otgsc register bits value. * @ci: the controller * @mask: bitfield mask */ @@ -75,7 +75,7 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask) } /** - * hw_write_otgsc updates target bits of OTGSC register. + * hw_write_otgsc - updates target bits of OTGSC register. * @ci: the controller * @mask: bitfield mask * @data: to be written @@ -140,8 +140,9 @@ void ci_handle_vbus_change(struct ci_hdrc *ci) } /** - * When we switch to device mode, the vbus value should be lower - * than OTGSC_BSV before connecting to host. + * hw_wait_vbus_lower_bsv - When we switch to device mode, the vbus value + * should be lower than OTGSC_BSV before connecting + * to host. * * @ci: the controller * diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 393f216b9161..8834ca613721 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -238,7 +238,7 @@ static int hw_ep_set_halt(struct ci_hdrc *ci, int num, int dir, int value) } /** - * hw_is_port_high_speed: test if port is high speed + * hw_port_is_high_speed: test if port is high speed * @ci: the controller * * This function returns true if high speed port diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index ca7a61190dd9..4895325b16a4 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -838,7 +838,7 @@ static int acm_tty_write(struct tty_struct *tty, return count; } -static int acm_tty_write_room(struct tty_struct *tty) +static unsigned int acm_tty_write_room(struct tty_struct *tty) { struct acm *acm = tty->driver_data; /* @@ -848,7 +848,7 @@ static int acm_tty_write_room(struct tty_struct *tty) return acm_wb_is_avail(acm) ? acm->writesize : 0; } -static int acm_tty_chars_in_buffer(struct tty_struct *tty) +static unsigned int acm_tty_chars_in_buffer(struct tty_struct *tty) { struct acm *acm = tty->driver_data; /* @@ -1056,21 +1056,8 @@ static void acm_tty_set_termios(struct tty_struct *tty, newline.bParityType = termios->c_cflag & PARENB ? (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0; - switch (termios->c_cflag & CSIZE) { - case CS5: - newline.bDataBits = 5; - break; - case CS6: - newline.bDataBits = 6; - break; - case CS7: - newline.bDataBits = 7; - break; - case CS8: - default: - newline.bDataBits = 8; - break; - } + newline.bDataBits = tty_get_char_size(termios->c_cflag); + /* FIXME: Needs to clear unsupported bits in the termios */ acm->clocal = ((termios->c_cflag & CLOCAL) != 0); @@ -1959,6 +1946,11 @@ static const struct usb_device_id acm_ids[] = { .driver_info = IGNORE_DEVICE, }, + /* Exclude Heimann Sensor GmbH USB appset demo */ + { USB_DEVICE(0x32a7, 0x0000), + .driver_info = IGNORE_DEVICE, + }, + /* control interfaces without any protocol set */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_PROTO_NONE) }, diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 8e5490ac13a2..fdf79bcf7eb0 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -1035,9 +1035,10 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor INIT_WORK(&desc->rxwork, wdm_rxwork); INIT_WORK(&desc->service_outs_intr, service_interrupt_work); - rv = -EINVAL; - if (!usb_endpoint_is_int_in(ep)) + if (!usb_endpoint_is_int_in(ep)) { + rv = -EINVAL; goto err; + } desc->wMaxPacketSize = usb_endpoint_maxp(ep); diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index ce5e6f6711f7..7e13b74e60e5 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -141,7 +141,7 @@ static const struct device_type ulpi_dev_type = { /* -------------------------------------------------------------------------- */ /** - * ulpi_register_driver - register a driver with the ULPI bus + * __ulpi_register_driver - register a driver with the ULPI bus * @drv: driver being registered * @module: ends up being THIS_MODULE * diff --git a/drivers/usb/common/usb-conn-gpio.c b/drivers/usb/common/usb-conn-gpio.c index 6c4e3a19f42c..0158148cb054 100644 --- a/drivers/usb/common/usb-conn-gpio.c +++ b/drivers/usb/common/usb-conn-gpio.c @@ -83,11 +83,11 @@ static void usb_conn_detect_cable(struct work_struct *work) else role = USB_ROLE_NONE; - dev_dbg(info->dev, "role %d/%d, gpios: id %d, vbus %d\n", - info->last_role, role, id, vbus); + dev_dbg(info->dev, "role %s -> %s, gpios: id %d, vbus %d\n", + usb_role_string(info->last_role), usb_role_string(role), id, vbus); if (info->last_role == role) { - dev_warn(info->dev, "repeated role: %d\n", role); + dev_warn(info->dev, "repeated role: %s\n", usb_role_string(role)); return; } @@ -149,14 +149,32 @@ static int usb_charger_get_property(struct power_supply *psy, return 0; } -static int usb_conn_probe(struct platform_device *pdev) +static int usb_conn_psy_register(struct usb_conn_info *info) { - struct device *dev = &pdev->dev; - struct power_supply_desc *desc; - struct usb_conn_info *info; + struct device *dev = info->dev; + struct power_supply_desc *desc = &info->desc; struct power_supply_config cfg = { .of_node = dev->of_node, }; + + desc->name = "usb-charger"; + desc->properties = usb_charger_properties; + desc->num_properties = ARRAY_SIZE(usb_charger_properties); + desc->get_property = usb_charger_get_property; + desc->type = POWER_SUPPLY_TYPE_USB; + cfg.drv_data = info; + + info->charger = devm_power_supply_register(dev, desc, &cfg); + if (IS_ERR(info->charger)) + dev_err(dev, "Unable to register charger\n"); + + return PTR_ERR_OR_ZERO(info->charger); +} + +static int usb_conn_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct usb_conn_info *info; bool need_vbus = true; int ret = 0; @@ -205,18 +223,18 @@ static int usb_conn_probe(struct platform_device *pdev) } if (IS_ERR(info->vbus)) { - if (PTR_ERR(info->vbus) != -EPROBE_DEFER) - dev_err(dev, "failed to get vbus: %ld\n", PTR_ERR(info->vbus)); - return PTR_ERR(info->vbus); + ret = PTR_ERR(info->vbus); + return dev_err_probe(dev, ret, "failed to get vbus :%d\n", ret); } info->role_sw = usb_role_switch_get(dev); - if (IS_ERR(info->role_sw)) { - if (PTR_ERR(info->role_sw) != -EPROBE_DEFER) - dev_err(dev, "failed to get role switch\n"); + if (IS_ERR(info->role_sw)) + return dev_err_probe(dev, PTR_ERR(info->role_sw), + "failed to get role switch\n"); - return PTR_ERR(info->role_sw); - } + ret = usb_conn_psy_register(info); + if (ret) + goto put_role_sw; if (info->id_gpiod) { info->id_irq = gpiod_to_irq(info->id_gpiod); @@ -252,20 +270,6 @@ static int usb_conn_probe(struct platform_device *pdev) } } - desc = &info->desc; - desc->name = "usb-charger"; - desc->properties = usb_charger_properties; - desc->num_properties = ARRAY_SIZE(usb_charger_properties); - desc->get_property = usb_charger_get_property; - desc->type = POWER_SUPPLY_TYPE_USB; - cfg.drv_data = info; - - info->charger = devm_power_supply_register(dev, desc, &cfg); - if (IS_ERR(info->charger)) { - dev_err(dev, "Unable to register charger\n"); - return PTR_ERR(info->charger); - } - platform_set_drvdata(pdev, info); /* Perform initial detection */ diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 2218941d35a3..b97464498763 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1162,7 +1162,7 @@ static int do_proc_control(struct usb_dev_state *ps, tbuf, ctrl->wLength); usb_unlock_device(dev); - i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl->bRequest, + i = usb_control_msg(dev, pipe, ctrl->bRequest, ctrl->bRequestType, ctrl->wValue, ctrl->wIndex, tbuf, ctrl->wLength, tmo); usb_lock_device(dev); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 6119fb41d736..0f8b7c93310e 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2111,6 +2111,136 @@ int usb_hcd_get_frame_number (struct usb_device *udev) } /*-------------------------------------------------------------------------*/ +#ifdef CONFIG_USB_HCD_TEST_MODE + +static void usb_ehset_completion(struct urb *urb) +{ + struct completion *done = urb->context; + + complete(done); +} +/* + * Allocate and initialize a control URB. This request will be used by the + * EHSET SINGLE_STEP_SET_FEATURE test in which the DATA and STATUS stages + * of the GetDescriptor request are sent 15 seconds after the SETUP stage. + * Return NULL if failed. + */ +static struct urb *request_single_step_set_feature_urb( + struct usb_device *udev, + void *dr, + void *buf, + struct completion *done) +{ + struct urb *urb; + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + struct usb_host_endpoint *ep; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + return NULL; + + urb->pipe = usb_rcvctrlpipe(udev, 0); + ep = (usb_pipein(urb->pipe) ? udev->ep_in : udev->ep_out) + [usb_pipeendpoint(urb->pipe)]; + if (!ep) { + usb_free_urb(urb); + return NULL; + } + + urb->ep = ep; + urb->dev = udev; + urb->setup_packet = (void *)dr; + urb->transfer_buffer = buf; + urb->transfer_buffer_length = USB_DT_DEVICE_SIZE; + urb->complete = usb_ehset_completion; + urb->status = -EINPROGRESS; + urb->actual_length = 0; + urb->transfer_flags = URB_DIR_IN; + usb_get_urb(urb); + atomic_inc(&urb->use_count); + atomic_inc(&urb->dev->urbnum); + if (map_urb_for_dma(hcd, urb, GFP_KERNEL)) { + usb_put_urb(urb); + usb_free_urb(urb); + return NULL; + } + + urb->context = done; + return urb; +} + +int ehset_single_step_set_feature(struct usb_hcd *hcd, int port) +{ + int retval = -ENOMEM; + struct usb_ctrlrequest *dr; + struct urb *urb; + struct usb_device *udev; + struct usb_device_descriptor *buf; + DECLARE_COMPLETION_ONSTACK(done); + + /* Obtain udev of the rhub's child port */ + udev = usb_hub_find_child(hcd->self.root_hub, port); + if (!udev) { + dev_err(hcd->self.controller, "No device attached to the RootHub\n"); + return -ENODEV; + } + buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); + if (!dr) { + kfree(buf); + return -ENOMEM; + } + + /* Fill Setup packet for GetDescriptor */ + dr->bRequestType = USB_DIR_IN; + dr->bRequest = USB_REQ_GET_DESCRIPTOR; + dr->wValue = cpu_to_le16(USB_DT_DEVICE << 8); + dr->wIndex = 0; + dr->wLength = cpu_to_le16(USB_DT_DEVICE_SIZE); + urb = request_single_step_set_feature_urb(udev, dr, buf, &done); + if (!urb) + goto cleanup; + + /* Submit just the SETUP stage */ + retval = hcd->driver->submit_single_step_set_feature(hcd, urb, 1); + if (retval) + goto out1; + if (!wait_for_completion_timeout(&done, msecs_to_jiffies(2000))) { + usb_kill_urb(urb); + retval = -ETIMEDOUT; + dev_err(hcd->self.controller, + "%s SETUP stage timed out on ep0\n", __func__); + goto out1; + } + msleep(15 * 1000); + + /* Complete remaining DATA and STATUS stages using the same URB */ + urb->status = -EINPROGRESS; + usb_get_urb(urb); + atomic_inc(&urb->use_count); + atomic_inc(&urb->dev->urbnum); + retval = hcd->driver->submit_single_step_set_feature(hcd, urb, 0); + if (!retval && !wait_for_completion_timeout(&done, + msecs_to_jiffies(2000))) { + usb_kill_urb(urb); + retval = -ETIMEDOUT; + dev_err(hcd->self.controller, + "%s IN stage timed out on ep0\n", __func__); + } +out1: + usb_free_urb(urb); +cleanup: + kfree(dr); + kfree(buf); + return retval; +} +EXPORT_SYMBOL_GPL(ehset_single_step_set_feature); +#endif /* CONFIG_USB_HCD_TEST_MODE */ + +/*-------------------------------------------------------------------------*/ #ifdef CONFIG_PM diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index df8e69e60aaf..d1efc7141333 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2434,6 +2434,8 @@ static void set_usb_port_removable(struct usb_device *udev) u16 wHubCharacteristics; bool removable = true; + dev_set_removable(&udev->dev, DEVICE_REMOVABLE_UNKNOWN); + if (!hdev) return; @@ -2445,11 +2447,11 @@ static void set_usb_port_removable(struct usb_device *udev) */ switch (hub->ports[udev->portnum - 1]->connect_type) { case USB_PORT_CONNECT_TYPE_HOT_PLUG: - udev->removable = USB_DEVICE_REMOVABLE; + dev_set_removable(&udev->dev, DEVICE_REMOVABLE); return; case USB_PORT_CONNECT_TYPE_HARD_WIRED: case USB_PORT_NOT_USED: - udev->removable = USB_DEVICE_FIXED; + dev_set_removable(&udev->dev, DEVICE_FIXED); return; default: break; @@ -2474,9 +2476,9 @@ static void set_usb_port_removable(struct usb_device *udev) } if (removable) - udev->removable = USB_DEVICE_REMOVABLE; + dev_set_removable(&udev->dev, DEVICE_REMOVABLE); else - udev->removable = USB_DEVICE_FIXED; + dev_set_removable(&udev->dev, DEVICE_FIXED); } @@ -2548,8 +2550,7 @@ int usb_new_device(struct usb_device *udev) device_enable_async_suspend(&udev->dev); /* check whether the hub or firmware marks this port as non-removable */ - if (udev->parent) - set_usb_port_removable(udev); + set_usb_port_removable(udev); /* Register the device. The device driver is responsible * for configuring the device and invoking the add-device @@ -3387,6 +3388,26 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) status = 0; } if (status) { + /* Check if the port has been suspended for the timeout case + * to prevent the suspended port from incorrect handling. + */ + if (status == -ETIMEDOUT) { + int ret; + u16 portstatus, portchange; + + portstatus = portchange = 0; + ret = hub_port_status(hub, port1, &portstatus, + &portchange); + + dev_dbg(&port_dev->dev, + "suspend timeout, status %04x\n", portstatus); + + if (ret == 0 && port_is_suspended(hub, portstatus)) { + status = 0; + goto suspend_done; + } + } + dev_dbg(&port_dev->dev, "can't suspend, status %d\n", status); /* Try to enable USB3 LTM again */ @@ -3403,6 +3424,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) if (!PMSG_IS_AUTO(msg)) status = 0; } else { + suspend_done: dev_dbg(&udev->dev, "usb %ssuspend, wakeup %d\n", (PMSG_IS_AUTO(msg) ? "auto-" : ""), udev->do_remote_wakeup); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 30e9e680c74c..4d59d927ae3e 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -783,6 +783,9 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, int i; int result; + if (size <= 0) /* No point in asking for no data */ + return -EINVAL; + memset(buf, 0, size); /* Make sure we parse really received data */ for (i = 0; i < 3; ++i) { @@ -832,6 +835,9 @@ static int usb_get_string(struct usb_device *dev, unsigned short langid, int i; int result; + if (size <= 0) /* No point in asking for no data */ + return -EINVAL; + for (i = 0; i < 3; ++i) { /* retry on length 0 or stall; some devices are flakey */ result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 21e7522655ac..6114cf83bb44 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -406,7 +406,6 @@ static const struct usb_device_id usb_quirk_list[] = { /* Realtek hub in Dell WD19 (Type-C) */ { USB_DEVICE(0x0bda, 0x0487), .driver_info = USB_QUIRK_NO_LPM }, - { USB_DEVICE(0x0bda, 0x5487), .driver_info = USB_QUIRK_RESET_RESUME }, /* Generic RTL8153 based ethernet adapters */ { USB_DEVICE(0x0bda, 0x8153), .driver_info = USB_QUIRK_NO_LPM }, diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 5a168ba9fc51..fa2e49d432ff 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -301,29 +301,6 @@ static ssize_t urbnum_show(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RO(urbnum); -static ssize_t removable_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct usb_device *udev; - char *state; - - udev = to_usb_device(dev); - - switch (udev->removable) { - case USB_DEVICE_REMOVABLE: - state = "removable"; - break; - case USB_DEVICE_FIXED: - state = "fixed"; - break; - default: - state = "unknown"; - } - - return sprintf(buf, "%s\n", state); -} -static DEVICE_ATTR_RO(removable); - static ssize_t ltm_capable_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -828,7 +805,6 @@ static struct attribute *dev_attrs[] = { &dev_attr_avoid_reset_quirk.attr, &dev_attr_authorized.attr, &dev_attr_remove.attr, - &dev_attr_removable.attr, &dev_attr_ltm_capable.attr, #ifdef CONFIG_OF &dev_attr_devspec.attr, diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 357b149b20d3..30727729a44c 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -407,6 +407,15 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) return -ENOEXEC; is_out = !(setup->bRequestType & USB_DIR_IN) || !setup->wLength; + dev_WARN_ONCE(&dev->dev, (usb_pipeout(urb->pipe) != is_out), + "BOGUS control dir, pipe %x doesn't match bRequestType %x\n", + urb->pipe, setup->bRequestType); + if (le16_to_cpu(setup->wLength) != urb->transfer_buffer_length) { + dev_dbg(&dev->dev, "BOGUS control len %d doesn't match transfer length %d\n", + le16_to_cpu(setup->wLength), + urb->transfer_buffer_length); + return -EBADR; + } } else { is_out = usb_endpoint_dir_out(&ep->desc); } diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 6f70ab9577b4..272ae5722c86 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -1111,15 +1111,6 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) usbcfg &= ~(GUSBCFG_ULPI_UTMI_SEL | GUSBCFG_PHYIF16); if (hsotg->params.phy_utmi_width == 16) usbcfg |= GUSBCFG_PHYIF16; - - /* Set turnaround time */ - if (dwc2_is_device_mode(hsotg)) { - usbcfg &= ~GUSBCFG_USBTRDTIM_MASK; - if (hsotg->params.phy_utmi_width == 16) - usbcfg |= 5 << GUSBCFG_USBTRDTIM_SHIFT; - else - usbcfg |= 9 << GUSBCFG_USBTRDTIM_SHIFT; - } break; default: dev_err(hsotg->dev, "FS PHY selected at HS!\n"); @@ -1141,6 +1132,24 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) return retval; } +static void dwc2_set_turnaround_time(struct dwc2_hsotg *hsotg) +{ + u32 usbcfg; + + if (hsotg->params.phy_type != DWC2_PHY_TYPE_PARAM_UTMI) + return; + + usbcfg = dwc2_readl(hsotg, GUSBCFG); + + usbcfg &= ~GUSBCFG_USBTRDTIM_MASK; + if (hsotg->params.phy_utmi_width == 16) + usbcfg |= 5 << GUSBCFG_USBTRDTIM_SHIFT; + else + usbcfg |= 9 << GUSBCFG_USBTRDTIM_SHIFT; + + dwc2_writel(hsotg, usbcfg, GUSBCFG); +} + int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) { u32 usbcfg; @@ -1158,6 +1167,9 @@ int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) retval = dwc2_hs_phy_init(hsotg, select_phy); if (retval) return retval; + + if (dwc2_is_device_mode(hsotg)) + dwc2_set_turnaround_time(hsotg); } if (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI && diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 184964174dc0..c581ee41ac81 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -1496,8 +1496,8 @@ static int dwc2_hsotg_ep_queue_lock(struct usb_ep *ep, struct usb_request *req, { struct dwc2_hsotg_ep *hs_ep = our_ep(ep); struct dwc2_hsotg *hs = hs_ep->parent; - unsigned long flags = 0; - int ret = 0; + unsigned long flags; + int ret; spin_lock_irqsave(&hs->lock, flags); ret = dwc2_hsotg_ep_queue(ep, req, gfp_flags); @@ -3338,7 +3338,7 @@ static void dwc2_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic) static int dwc2_hsotg_ep_disable(struct usb_ep *ep); /** - * dwc2_hsotg_core_init - issue softreset to the core + * dwc2_hsotg_core_init_disconnected - issue softreset to the core * @hsotg: The device state * @is_usb_reset: Usb resetting flag * @@ -4374,8 +4374,8 @@ static int dwc2_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value) { struct dwc2_hsotg_ep *hs_ep = our_ep(ep); struct dwc2_hsotg *hs = hs_ep->parent; - unsigned long flags = 0; - int ret = 0; + unsigned long flags; + int ret; spin_lock_irqsave(&hs->lock, flags); ret = dwc2_hsotg_ep_sethalt(ep, value, false); @@ -4505,7 +4505,7 @@ err: static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget) { struct dwc2_hsotg *hsotg = to_hsotg(gadget); - unsigned long flags = 0; + unsigned long flags; int ep; if (!hsotg) @@ -4577,7 +4577,7 @@ static int dwc2_hsotg_set_selfpowered(struct usb_gadget *gadget, static int dwc2_hsotg_pullup(struct usb_gadget *gadget, int is_on) { struct dwc2_hsotg *hsotg = to_hsotg(gadget); - unsigned long flags = 0; + unsigned long flags; dev_dbg(hsotg->dev, "%s: is_on: %d op_state: %d\n", __func__, is_on, hsotg->op_state); diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c index 621a4846bd05..89a788326c56 100644 --- a/drivers/usb/dwc2/hcd_queue.c +++ b/drivers/usb/dwc2/hcd_queue.c @@ -675,7 +675,7 @@ static int dwc2_hs_pmap_schedule(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, } /** - * dwc2_ls_pmap_unschedule() - Undo work done by dwc2_hs_pmap_schedule() + * dwc2_hs_pmap_unschedule() - Undo work done by dwc2_hs_pmap_schedule() * * @hsotg: The HCD state structure for the DWC OTG controller. * @qh: QH for the periodic transfer. diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index 7a6089fa81e1..67c5eb140232 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -784,8 +784,8 @@ static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg) } /** - * During device initialization, read various hardware configuration - * registers and interpret the contents. + * dwc2_get_hwparams() - During device initialization, read various hardware + * configuration registers and interpret the contents. * * @hsotg: Programming view of the DWC_otg controller * diff --git a/drivers/usb/dwc2/pci.c b/drivers/usb/dwc2/pci.c index 0000151e3ca9..a93559b4ecdb 100644 --- a/drivers/usb/dwc2/pci.c +++ b/drivers/usb/dwc2/pci.c @@ -64,7 +64,7 @@ struct dwc2_pci_glue { }; /** - * dwc2_pci_probe() - Provides the cleanup entry points for the DWC_otg PCI + * dwc2_pci_remove() - Provides the cleanup entry points for the DWC_otg PCI * driver * * @pci: The programming view of DWC_otg PCI diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 520a0beef77c..c8f18f3ba9e3 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -408,7 +408,7 @@ static bool dwc2_check_core_endianness(struct dwc2_hsotg *hsotg) } /** - * Check core version + * dwc2_check_core_version() - Check core version * * @hsotg: Programming view of the DWC_otg controller * diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 4ac397e43e19..ba74ad7f6995 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1545,6 +1545,10 @@ static int dwc3_probe(struct platform_device *pdev) dwc3_get_properties(dwc); + ret = dma_set_mask_and_coherent(dwc->sysdev, DMA_BIT_MASK(64)); + if (ret) + return ret; + dwc->reset = devm_reset_control_array_get_optional_shared(dev); if (IS_ERR(dwc->reset)) return PTR_ERR(dwc->reset); @@ -1616,17 +1620,18 @@ static int dwc3_probe(struct platform_device *pdev) } dwc3_check_params(dwc); + dwc3_debugfs_init(dwc); ret = dwc3_core_init_mode(dwc); if (ret) goto err5; - dwc3_debugfs_init(dwc); pm_runtime_put(dev); return 0; err5: + dwc3_debugfs_exit(dwc); dwc3_event_buffers_cleanup(dwc); usb_phy_shutdown(dwc->usb2_phy); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index c5d5760cdf53..dccdf13b5f9e 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1013,7 +1013,6 @@ struct dwc3_scratchpad_array { * @link_state: link state * @speed: device speed (super, high, full, low) * @hwparams: copy of hwparams registers - * @root: debugfs root folder pointer * @regset: debugfs pointer to regdump file * @dbg_lsp_select: current debug lsp mux register selection * @test_mode: true when we're entering a USB test mode @@ -1222,7 +1221,6 @@ struct dwc3 { u8 num_eps; struct dwc3_hwparams hwparams; - struct dentry *root; struct debugfs_regset32 *regset; u32 dbg_lsp_select; diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 5dbbe53269d3..f2b7675c7f62 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -889,8 +889,10 @@ static void dwc3_debugfs_create_endpoint_files(struct dwc3_ep *dep, void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep) { struct dentry *dir; + struct dentry *root; - dir = debugfs_create_dir(dep->name, dep->dwc->root); + root = debugfs_lookup(dev_name(dep->dwc->dev), usb_debug_root); + dir = debugfs_create_dir(dep->name, root); dwc3_debugfs_create_endpoint_files(dep, dir); } @@ -909,8 +911,6 @@ void dwc3_debugfs_init(struct dwc3 *dwc) dwc->regset->base = dwc->regs - DWC3_GLOBALS_REGS_START; root = debugfs_create_dir(dev_name(dwc->dev), usb_debug_root); - dwc->root = root; - debugfs_create_regset32("regdump", 0444, root, dwc->regset); debugfs_create_file("lsp_dump", 0644, root, dwc, &dwc3_lsp_fops); @@ -929,6 +929,6 @@ void dwc3_debugfs_init(struct dwc3 *dwc) void dwc3_debugfs_exit(struct dwc3 *dwc) { - debugfs_remove_recursive(dwc->root); + debugfs_remove(debugfs_lookup(dev_name(dwc->dev), usb_debug_root)); kfree(dwc->regset); } diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c index e2b68bb770d1..8fcbac10510c 100644 --- a/drivers/usb/dwc3/drd.c +++ b/drivers/usb/dwc3/drd.c @@ -596,7 +596,6 @@ int dwc3_drd_init(struct dwc3 *dwc) dwc3_drd_update(dwc); } else { dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_OTG); - dwc->current_dr_role = DWC3_GCTL_PRTCAP_OTG; /* use OTG block to get ID event */ irq = dwc3_otg_get_irq(dwc); diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 1e51460938b8..2b37bdd39a74 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -36,7 +36,7 @@ #define PCI_DEVICE_ID_INTEL_CNPH 0xa36e #define PCI_DEVICE_ID_INTEL_CNPV 0xa3b0 #define PCI_DEVICE_ID_INTEL_ICLLP 0x34ee -#define PCI_DEVICE_ID_INTEL_EHLLP 0x4b7e +#define PCI_DEVICE_ID_INTEL_EHL 0x4b7e #define PCI_DEVICE_ID_INTEL_TGPLP 0xa0ee #define PCI_DEVICE_ID_INTEL_TGPH 0x43ee #define PCI_DEVICE_ID_INTEL_JSP 0x4dee @@ -167,7 +167,7 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc) if (pdev->vendor == PCI_VENDOR_ID_INTEL) { if (pdev->device == PCI_DEVICE_ID_INTEL_BXT || pdev->device == PCI_DEVICE_ID_INTEL_BXT_M || - pdev->device == PCI_DEVICE_ID_INTEL_EHLLP) { + pdev->device == PCI_DEVICE_ID_INTEL_EHL) { guid_parse(PCI_INTEL_BXT_DSM_GUID, &dwc->guid); dwc->has_dsm_for_pm = true; } @@ -375,8 +375,8 @@ static const struct pci_device_id dwc3_pci_id_table[] = { { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICLLP), (kernel_ulong_t) &dwc3_pci_intel_swnode, }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_EHLLP), - (kernel_ulong_t) &dwc3_pci_intel_swnode }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_EHL), + (kernel_ulong_t) &dwc3_pci_intel_swnode, }, { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGPLP), (kernel_ulong_t) &dwc3_pci_intel_swnode, }, diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index f14c2aa83759..af6d7f157989 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2798,7 +2798,9 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc) list_del(&dep->endpoint.ep_list); } - debugfs_remove_recursive(debugfs_lookup(dep->name, dwc->root)); + debugfs_remove_recursive(debugfs_lookup(dep->name, + debugfs_lookup(dev_name(dep->dwc->dev), + usb_debug_root))); kfree(dep); } } diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h index 51d18e8d1602..cb998ba50fea 100644 --- a/drivers/usb/dwc3/trace.h +++ b/drivers/usb/dwc3/trace.h @@ -222,8 +222,6 @@ DECLARE_EVENT_CLASS(dwc3_log_trb, TP_STRUCT__entry( __string(name, dep->name) __field(struct dwc3_trb *, trb) - __field(u32, allocated) - __field(u32, queued) __field(u32, bpl) __field(u32, bph) __field(u32, size) diff --git a/drivers/usb/gadget/function/f_eem.c b/drivers/usb/gadget/function/f_eem.c index 2cd9942707b4..5d38f29bda72 100644 --- a/drivers/usb/gadget/function/f_eem.c +++ b/drivers/usb/gadget/function/f_eem.c @@ -30,6 +30,11 @@ struct f_eem { u8 ctrl_id; }; +struct in_context { + struct sk_buff *skb; + struct usb_ep *ep; +}; + static inline struct f_eem *func_to_eem(struct usb_function *f) { return container_of(f, struct f_eem, port.func); @@ -320,9 +325,12 @@ fail: static void eem_cmd_complete(struct usb_ep *ep, struct usb_request *req) { - struct sk_buff *skb = (struct sk_buff *)req->context; + struct in_context *ctx = req->context; - dev_kfree_skb_any(skb); + dev_kfree_skb_any(ctx->skb); + kfree(req->buf); + usb_ep_free_request(ctx->ep, req); + kfree(ctx); } /* @@ -410,7 +418,9 @@ static int eem_unwrap(struct gether *port, * b15: bmType (0 == data, 1 == command) */ if (header & BIT(15)) { - struct usb_request *req = cdev->req; + struct usb_request *req; + struct in_context *ctx; + struct usb_ep *ep; u16 bmEEMCmd; /* EEM command packet format: @@ -439,11 +449,36 @@ static int eem_unwrap(struct gether *port, skb_trim(skb2, len); put_unaligned_le16(BIT(15) | BIT(11) | len, skb_push(skb2, 2)); + + ep = port->in_ep; + req = usb_ep_alloc_request(ep, GFP_ATOMIC); + if (!req) { + dev_kfree_skb_any(skb2); + goto next; + } + + req->buf = kmalloc(skb2->len, GFP_KERNEL); + if (!req->buf) { + usb_ep_free_request(ep, req); + dev_kfree_skb_any(skb2); + goto next; + } + + ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) { + kfree(req->buf); + usb_ep_free_request(ep, req); + dev_kfree_skb_any(skb2); + goto next; + } + ctx->skb = skb2; + ctx->ep = ep; + skb_copy_bits(skb2, 0, req->buf, skb2->len); req->length = skb2->len; req->complete = eem_cmd_complete; req->zero = 1; - req->context = skb2; + req->context = ctx; if (usb_ep_queue(port->in_ep, req, GFP_ATOMIC)) DBG(cdev, "echo response queue fail\n"); break; diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index d4844afeaffc..9c0c393abb39 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -250,8 +250,8 @@ EXPORT_SYMBOL_GPL(ffs_lock); static struct ffs_dev *_ffs_find_dev(const char *name); static struct ffs_dev *_ffs_alloc_dev(void); static void _ffs_free_dev(struct ffs_dev *dev); -static void *ffs_acquire_dev(const char *dev_name); -static void ffs_release_dev(struct ffs_data *ffs_data); +static int ffs_acquire_dev(const char *dev_name, struct ffs_data *ffs_data); +static void ffs_release_dev(struct ffs_dev *ffs_dev); static int ffs_ready(struct ffs_data *ffs); static void ffs_closed(struct ffs_data *ffs); @@ -1554,8 +1554,8 @@ unmapped_value: static int ffs_fs_get_tree(struct fs_context *fc) { struct ffs_sb_fill_data *ctx = fc->fs_private; - void *ffs_dev; struct ffs_data *ffs; + int ret; ENTER(); @@ -1574,13 +1574,12 @@ static int ffs_fs_get_tree(struct fs_context *fc) return -ENOMEM; } - ffs_dev = ffs_acquire_dev(ffs->dev_name); - if (IS_ERR(ffs_dev)) { + ret = ffs_acquire_dev(ffs->dev_name, ffs); + if (ret) { ffs_data_put(ffs); - return PTR_ERR(ffs_dev); + return ret; } - ffs->private_data = ffs_dev; ctx->ffs_data = ffs; return get_tree_nodev(fc, ffs_sb_fill); } @@ -1591,7 +1590,6 @@ static void ffs_fs_free_fc(struct fs_context *fc) if (ctx) { if (ctx->ffs_data) { - ffs_release_dev(ctx->ffs_data); ffs_data_put(ctx->ffs_data); } @@ -1630,10 +1628,8 @@ ffs_fs_kill_sb(struct super_block *sb) ENTER(); kill_litter_super(sb); - if (sb->s_fs_info) { - ffs_release_dev(sb->s_fs_info); + if (sb->s_fs_info) ffs_data_closed(sb->s_fs_info); - } } static struct file_system_type ffs_fs_type = { @@ -1703,6 +1699,7 @@ static void ffs_data_put(struct ffs_data *ffs) if (refcount_dec_and_test(&ffs->ref)) { pr_info("%s(): freeing\n", __func__); ffs_data_clear(ffs); + ffs_release_dev(ffs->private_data); BUG_ON(waitqueue_active(&ffs->ev.waitq) || swait_active(&ffs->ep0req_completion.wait) || waitqueue_active(&ffs->wait)); @@ -3032,6 +3029,7 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f, struct ffs_function *func = ffs_func_from_usb(f); struct f_fs_opts *ffs_opts = container_of(f->fi, struct f_fs_opts, func_inst); + struct ffs_data *ffs_data; int ret; ENTER(); @@ -3046,12 +3044,13 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f, if (!ffs_opts->no_configfs) ffs_dev_lock(); ret = ffs_opts->dev->desc_ready ? 0 : -ENODEV; - func->ffs = ffs_opts->dev->ffs_data; + ffs_data = ffs_opts->dev->ffs_data; if (!ffs_opts->no_configfs) ffs_dev_unlock(); if (ret) return ERR_PTR(ret); + func->ffs = ffs_data; func->conf = c; func->gadget = c->cdev->gadget; @@ -3506,6 +3505,7 @@ static void ffs_free_inst(struct usb_function_instance *f) struct f_fs_opts *opts; opts = to_f_fs_opts(f); + ffs_release_dev(opts->dev); ffs_dev_lock(); _ffs_free_dev(opts->dev); ffs_dev_unlock(); @@ -3693,47 +3693,48 @@ static void _ffs_free_dev(struct ffs_dev *dev) { list_del(&dev->entry); - /* Clear the private_data pointer to stop incorrect dev access */ - if (dev->ffs_data) - dev->ffs_data->private_data = NULL; - kfree(dev); if (list_empty(&ffs_devices)) functionfs_cleanup(); } -static void *ffs_acquire_dev(const char *dev_name) +static int ffs_acquire_dev(const char *dev_name, struct ffs_data *ffs_data) { + int ret = 0; struct ffs_dev *ffs_dev; ENTER(); ffs_dev_lock(); ffs_dev = _ffs_find_dev(dev_name); - if (!ffs_dev) - ffs_dev = ERR_PTR(-ENOENT); - else if (ffs_dev->mounted) - ffs_dev = ERR_PTR(-EBUSY); - else if (ffs_dev->ffs_acquire_dev_callback && - ffs_dev->ffs_acquire_dev_callback(ffs_dev)) - ffs_dev = ERR_PTR(-ENOENT); - else + if (!ffs_dev) { + ret = -ENOENT; + } else if (ffs_dev->mounted) { + ret = -EBUSY; + } else if (ffs_dev->ffs_acquire_dev_callback && + ffs_dev->ffs_acquire_dev_callback(ffs_dev)) { + ret = -ENOENT; + } else { ffs_dev->mounted = true; + ffs_dev->ffs_data = ffs_data; + ffs_data->private_data = ffs_dev; + } ffs_dev_unlock(); - return ffs_dev; + return ret; } -static void ffs_release_dev(struct ffs_data *ffs_data) +static void ffs_release_dev(struct ffs_dev *ffs_dev) { - struct ffs_dev *ffs_dev; - ENTER(); ffs_dev_lock(); - ffs_dev = ffs_data->private_data; - if (ffs_dev) { + if (ffs_dev && ffs_dev->mounted) { ffs_dev->mounted = false; + if (ffs_dev->ffs_data) { + ffs_dev->ffs_data->private_data = NULL; + ffs_dev->ffs_data = NULL; + } if (ffs_dev->ffs_release_dev_callback) ffs_dev->ffs_release_dev_callback(ffs_dev); @@ -3761,7 +3762,6 @@ static int ffs_ready(struct ffs_data *ffs) } ffs_obj->desc_ready = true; - ffs_obj->ffs_data = ffs; if (ffs_obj->ffs_ready_callback) { ret = ffs_obj->ffs_ready_callback(ffs); @@ -3789,7 +3789,6 @@ static void ffs_closed(struct ffs_data *ffs) goto done; ffs_obj->desc_ready = false; - ffs_obj->ffs_data = NULL; if (test_and_clear_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags) && ffs_obj->ffs_closed_callback) diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index e55699308117..02683ac0719d 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c @@ -88,7 +88,7 @@ static struct usb_interface_descriptor hidg_interface_desc = { static struct hid_descriptor hidg_desc = { .bLength = sizeof hidg_desc, .bDescriptorType = HID_DT_HID, - .bcdHID = 0x0101, + .bcdHID = cpu_to_le16(0x0101), .bCountryCode = 0x00, .bNumDescriptors = 0x1, /*.desc[0].bDescriptorType = DYNAMIC */ @@ -1118,7 +1118,7 @@ static struct usb_function *hidg_alloc(struct usb_function_instance *fi) hidg->func.setup = hidg_setup; hidg->func.free_func = hidg_free; - /* this could me made configurable at some point */ + /* this could be made configurable at some point */ hidg->qlen = 4; return &hidg->func; diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index 59d382fe1bbf..abec5c58f525 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c @@ -667,8 +667,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) value = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC); spin_lock(&dev->lock); if (value) { - list_del(&req->list); - list_add(&req->list, &dev->tx_reqs); + list_move(&req->list, &dev->tx_reqs); spin_unlock_irqrestore(&dev->lock, flags); mutex_unlock(&dev->lock_printer_io); return -EAGAIN; diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 7aa4c8bc5a1a..ae29ff2b2b68 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -44,6 +44,7 @@ #define EPIN_EN(_opts) ((_opts)->p_chmask != 0) #define EPOUT_EN(_opts) ((_opts)->c_chmask != 0) +#define EPOUT_FBACK_IN_EN(_opts) ((_opts)->c_sync == USB_ENDPOINT_SYNC_ASYNC) struct f_uac2 { struct g_audio g_audio; @@ -273,7 +274,7 @@ static struct usb_endpoint_descriptor fs_epout_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, + /* .bmAttributes = DYNAMIC */ /* .wMaxPacketSize = DYNAMIC */ .bInterval = 1, }; @@ -282,7 +283,7 @@ static struct usb_endpoint_descriptor hs_epout_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, + /* .bmAttributes = DYNAMIC */ /* .wMaxPacketSize = DYNAMIC */ .bInterval = 4, }; @@ -292,7 +293,7 @@ static struct usb_endpoint_descriptor ss_epout_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, + /* .bmAttributes = DYNAMIC */ /* .wMaxPacketSize = DYNAMIC */ .bInterval = 4, }; @@ -317,6 +318,37 @@ static struct uac2_iso_endpoint_descriptor as_iso_out_desc = { .wLockDelay = 0, }; +/* STD AS ISO IN Feedback Endpoint */ +static struct usb_endpoint_descriptor fs_epin_fback_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_USAGE_FEEDBACK, + .wMaxPacketSize = cpu_to_le16(3), + .bInterval = 1, +}; + +static struct usb_endpoint_descriptor hs_epin_fback_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_USAGE_FEEDBACK, + .wMaxPacketSize = cpu_to_le16(4), + .bInterval = 4, +}; + +static struct usb_endpoint_descriptor ss_epin_fback_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_USAGE_FEEDBACK, + .wMaxPacketSize = cpu_to_le16(4), + .bInterval = 4, +}; + + /* Audio Streaming IN Interface - Alt0 */ static struct usb_interface_descriptor std_as_in_if0_desc = { .bLength = sizeof std_as_in_if0_desc, @@ -431,6 +463,7 @@ static struct usb_descriptor_header *fs_audio_desc[] = { (struct usb_descriptor_header *)&as_out_fmt1_desc, (struct usb_descriptor_header *)&fs_epout_desc, (struct usb_descriptor_header *)&as_iso_out_desc, + (struct usb_descriptor_header *)&fs_epin_fback_desc, (struct usb_descriptor_header *)&std_as_in_if0_desc, (struct usb_descriptor_header *)&std_as_in_if1_desc, @@ -461,6 +494,7 @@ static struct usb_descriptor_header *hs_audio_desc[] = { (struct usb_descriptor_header *)&as_out_fmt1_desc, (struct usb_descriptor_header *)&hs_epout_desc, (struct usb_descriptor_header *)&as_iso_out_desc, + (struct usb_descriptor_header *)&hs_epin_fback_desc, (struct usb_descriptor_header *)&std_as_in_if0_desc, (struct usb_descriptor_header *)&std_as_in_if1_desc, @@ -492,6 +526,7 @@ static struct usb_descriptor_header *ss_audio_desc[] = { (struct usb_descriptor_header *)&ss_epout_desc, (struct usb_descriptor_header *)&ss_epout_desc_comp, (struct usb_descriptor_header *)&as_iso_out_desc, + (struct usb_descriptor_header *)&ss_epin_fback_desc, (struct usb_descriptor_header *)&std_as_in_if0_desc, (struct usb_descriptor_header *)&std_as_in_if1_desc, @@ -549,8 +584,11 @@ static int set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts, ssize = uac2_opts->c_ssize; } + if (!is_playback && (uac2_opts->c_sync == USB_ENDPOINT_SYNC_ASYNC)) + srate = srate * (1000 + uac2_opts->fb_max) / 1000; + max_size_bw = num_channels(chmask) * ssize * - ((srate / (factor / (1 << (ep_desc->bInterval - 1)))) + 1); + DIV_ROUND_UP(srate, factor / (1 << (ep_desc->bInterval - 1))); ep_desc->wMaxPacketSize = cpu_to_le16(min_t(u16, max_size_bw, max_size_ep)); @@ -568,22 +606,26 @@ static void setup_headers(struct f_uac2_opts *opts, struct usb_ss_ep_comp_descriptor *epin_desc_comp = NULL; struct usb_endpoint_descriptor *epout_desc; struct usb_endpoint_descriptor *epin_desc; + struct usb_endpoint_descriptor *epin_fback_desc; int i; switch (speed) { case USB_SPEED_FULL: epout_desc = &fs_epout_desc; epin_desc = &fs_epin_desc; + epin_fback_desc = &fs_epin_fback_desc; break; case USB_SPEED_HIGH: epout_desc = &hs_epout_desc; epin_desc = &hs_epin_desc; + epin_fback_desc = &hs_epin_fback_desc; break; default: epout_desc = &ss_epout_desc; epin_desc = &ss_epin_desc; epout_desc_comp = &ss_epout_desc_comp; epin_desc_comp = &ss_epin_desc_comp; + epin_fback_desc = &ss_epin_fback_desc; } i = 0; @@ -611,6 +653,9 @@ static void setup_headers(struct f_uac2_opts *opts, headers[i++] = USBDHDR(epout_desc_comp); headers[i++] = USBDHDR(&as_iso_out_desc); + + if (EPOUT_FBACK_IN_EN(opts)) + headers[i++] = USBDHDR(epin_fback_desc); } if (EPIN_EN(opts)) { headers[i++] = USBDHDR(&std_as_in_if0_desc); @@ -781,6 +826,23 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) std_as_out_if1_desc.bInterfaceNumber = ret; uac2->as_out_intf = ret; uac2->as_out_alt = 0; + + if (EPOUT_FBACK_IN_EN(uac2_opts)) { + fs_epout_desc.bmAttributes = + USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC; + hs_epout_desc.bmAttributes = + USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC; + ss_epout_desc.bmAttributes = + USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC; + std_as_out_if1_desc.bNumEndpoints++; + } else { + fs_epout_desc.bmAttributes = + USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ADAPTIVE; + hs_epout_desc.bmAttributes = + USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ADAPTIVE; + ss_epout_desc.bmAttributes = + USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ADAPTIVE; + } } if (EPIN_EN(uac2_opts)) { @@ -844,6 +906,15 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); return -ENODEV; } + if (EPOUT_FBACK_IN_EN(uac2_opts)) { + agdev->in_ep_fback = usb_ep_autoconfig(gadget, + &fs_epin_fback_desc); + if (!agdev->in_ep_fback) { + dev_err(dev, "%s:%d Error!\n", + __func__, __LINE__); + return -ENODEV; + } + } } if (EPIN_EN(uac2_opts)) { @@ -867,8 +938,10 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) le16_to_cpu(ss_epout_desc.wMaxPacketSize)); hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; + hs_epin_fback_desc.bEndpointAddress = fs_epin_fback_desc.bEndpointAddress; hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; ss_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; + ss_epin_fback_desc.bEndpointAddress = fs_epin_fback_desc.bEndpointAddress; ss_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; setup_descriptor(uac2_opts); @@ -887,6 +960,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) agdev->params.c_srate = uac2_opts->c_srate; agdev->params.c_ssize = uac2_opts->c_ssize; agdev->params.req_number = uac2_opts->req_number; + agdev->params.fb_max = uac2_opts->fb_max; ret = g_audio_setup(agdev, "UAC2 PCM", "UAC2_Gadget"); if (ret) goto err_free_descs; @@ -1195,13 +1269,71 @@ end: \ \ CONFIGFS_ATTR(f_uac2_opts_, name) +#define UAC2_ATTRIBUTE_SYNC(name) \ +static ssize_t f_uac2_opts_##name##_show(struct config_item *item, \ + char *page) \ +{ \ + struct f_uac2_opts *opts = to_f_uac2_opts(item); \ + int result; \ + char *str; \ + \ + mutex_lock(&opts->lock); \ + switch (opts->name) { \ + case USB_ENDPOINT_SYNC_ASYNC: \ + str = "async"; \ + break; \ + case USB_ENDPOINT_SYNC_ADAPTIVE: \ + str = "adaptive"; \ + break; \ + default: \ + str = "unknown"; \ + break; \ + } \ + result = sprintf(page, "%s\n", str); \ + mutex_unlock(&opts->lock); \ + \ + return result; \ +} \ + \ +static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \ + const char *page, size_t len) \ +{ \ + struct f_uac2_opts *opts = to_f_uac2_opts(item); \ + int ret = 0; \ + \ + mutex_lock(&opts->lock); \ + if (opts->refcnt) { \ + ret = -EBUSY; \ + goto end; \ + } \ + \ + if (!strncmp(page, "async", 5)) \ + opts->name = USB_ENDPOINT_SYNC_ASYNC; \ + else if (!strncmp(page, "adaptive", 8)) \ + opts->name = USB_ENDPOINT_SYNC_ADAPTIVE; \ + else { \ + ret = -EINVAL; \ + goto end; \ + } \ + \ + ret = len; \ + \ +end: \ + mutex_unlock(&opts->lock); \ + return ret; \ +} \ + \ +CONFIGFS_ATTR(f_uac2_opts_, name) + UAC2_ATTRIBUTE(p_chmask); UAC2_ATTRIBUTE(p_srate); UAC2_ATTRIBUTE(p_ssize); UAC2_ATTRIBUTE(c_chmask); UAC2_ATTRIBUTE(c_srate); +UAC2_ATTRIBUTE_SYNC(c_sync); UAC2_ATTRIBUTE(c_ssize); UAC2_ATTRIBUTE(req_number); +UAC2_ATTRIBUTE(fb_max); static struct configfs_attribute *f_uac2_attrs[] = { &f_uac2_opts_attr_p_chmask, @@ -1210,7 +1342,9 @@ static struct configfs_attribute *f_uac2_attrs[] = { &f_uac2_opts_attr_c_chmask, &f_uac2_opts_attr_c_srate, &f_uac2_opts_attr_c_ssize, + &f_uac2_opts_attr_c_sync, &f_uac2_opts_attr_req_number, + &f_uac2_opts_attr_fb_max, NULL, }; @@ -1248,7 +1382,9 @@ static struct usb_function_instance *afunc_alloc_inst(void) opts->c_chmask = UAC2_DEF_CCHMASK; opts->c_srate = UAC2_DEF_CSRATE; opts->c_ssize = UAC2_DEF_CSSIZE; + opts->c_sync = UAC2_DEF_CSYNC; opts->req_number = UAC2_DEF_REQ_NUM; + opts->fb_max = UAC2_DEF_FB_MAX; return &opts->func_inst; } diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c index 5fbceee897a3..018dd0978995 100644 --- a/drivers/usb/gadget/function/u_audio.c +++ b/drivers/usb/gadget/function/u_audio.c @@ -16,6 +16,7 @@ #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> +#include <sound/control.h> #include "u_audio.h" @@ -35,9 +36,13 @@ struct uac_rtd_params { void *rbuf; + unsigned int pitch; /* Stream pitch ratio to 1000000 */ unsigned int max_psize; /* MaxPacketSize of endpoint */ struct usb_request **reqs; + + struct usb_request *req_fback; /* Feedback endpoint request */ + bool fb_ep_enabled; /* if the ep is enabled */ }; struct snd_uac_chip { @@ -70,6 +75,48 @@ static const struct snd_pcm_hardware uac_pcm_hardware = { .periods_min = MIN_PERIODS, }; +static void u_audio_set_fback_frequency(enum usb_device_speed speed, + unsigned long long freq, + unsigned int pitch, + void *buf) +{ + u32 ff = 0; + + /* + * Because the pitch base is 1000000, the final divider here + * will be 1000 * 1000000 = 1953125 << 9 + * + * Instead of dealing with big numbers lets fold this 9 left shift + */ + + if (speed == USB_SPEED_FULL) { + /* + * Full-speed feedback endpoints report frequency + * in samples/frame + * Format is encoded in Q10.10 left-justified in the 24 bits, + * so that it has a Q10.14 format. + * + * ff = (freq << 14) / 1000 + */ + freq <<= 5; + } else { + /* + * High-speed feedback endpoints report frequency + * in samples/microframe. + * Format is encoded in Q12.13 fitted into four bytes so that + * the binary point is located between the second and the third + * byte fromat (that is Q16.16) + * + * ff = (freq << 16) / 8000 + */ + freq <<= 4; + } + + ff = DIV_ROUND_CLOSEST_ULL((freq * pitch), 1953125); + + *(__le32 *)buf = cpu_to_le32(ff); +} + static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req) { unsigned int pending; @@ -173,6 +220,35 @@ exit: dev_err(uac->card->dev, "%d Error!\n", __LINE__); } +static void u_audio_iso_fback_complete(struct usb_ep *ep, + struct usb_request *req) +{ + struct uac_rtd_params *prm = req->context; + struct snd_uac_chip *uac = prm->uac; + struct g_audio *audio_dev = uac->audio_dev; + struct uac_params *params = &audio_dev->params; + int status = req->status; + + /* i/f shutting down */ + if (!prm->fb_ep_enabled || req->status == -ESHUTDOWN) + return; + + /* + * We can't really do much about bad xfers. + * Afterall, the ISOCH xfers could fail legitimately. + */ + if (status) + pr_debug("%s: iso_complete status(%d) %d/%d\n", + __func__, status, req->actual, req->length); + + u_audio_set_fback_frequency(audio_dev->gadget->speed, + params->c_srate, prm->pitch, + req->buf); + + if (usb_ep_queue(ep, req, GFP_ATOMIC)) + dev_err(uac->card->dev, "%d Error!\n", __LINE__); +} + static int uac_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_uac_chip *uac = snd_pcm_substream_chip(substream); @@ -335,14 +411,33 @@ static inline void free_ep(struct uac_rtd_params *prm, struct usb_ep *ep) dev_err(uac->card->dev, "%s:%d Error!\n", __func__, __LINE__); } +static inline void free_ep_fback(struct uac_rtd_params *prm, struct usb_ep *ep) +{ + struct snd_uac_chip *uac = prm->uac; + + if (!prm->fb_ep_enabled) + return; + + prm->fb_ep_enabled = false; + + if (prm->req_fback) { + usb_ep_dequeue(ep, prm->req_fback); + kfree(prm->req_fback->buf); + usb_ep_free_request(ep, prm->req_fback); + prm->req_fback = NULL; + } + + if (usb_ep_disable(ep)) + dev_err(uac->card->dev, "%s:%d Error!\n", __func__, __LINE__); +} int u_audio_start_capture(struct g_audio *audio_dev) { struct snd_uac_chip *uac = audio_dev->uac; struct usb_gadget *gadget = audio_dev->gadget; struct device *dev = &gadget->dev; - struct usb_request *req; - struct usb_ep *ep; + struct usb_request *req, *req_fback; + struct usb_ep *ep, *ep_fback; struct uac_rtd_params *prm; struct uac_params *params = &audio_dev->params; int req_len, i; @@ -374,6 +469,43 @@ int u_audio_start_capture(struct g_audio *audio_dev) dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); } + ep_fback = audio_dev->in_ep_fback; + if (!ep_fback) + return 0; + + /* Setup feedback endpoint */ + config_ep_by_speed(gadget, &audio_dev->func, ep_fback); + prm->fb_ep_enabled = true; + usb_ep_enable(ep_fback); + req_len = ep_fback->maxpacket; + + req_fback = usb_ep_alloc_request(ep_fback, GFP_ATOMIC); + if (req_fback == NULL) + return -ENOMEM; + + prm->req_fback = req_fback; + req_fback->zero = 0; + req_fback->context = prm; + req_fback->length = req_len; + req_fback->complete = u_audio_iso_fback_complete; + + req_fback->buf = kzalloc(req_len, GFP_ATOMIC); + if (!req_fback->buf) + return -ENOMEM; + + /* + * Configure the feedback endpoint's reported frequency. + * Always start with original frequency since its deviation can't + * be meauserd at start of playback + */ + prm->pitch = 1000000; + u_audio_set_fback_frequency(audio_dev->gadget->speed, + params->c_srate, prm->pitch, + req_fback->buf); + + if (usb_ep_queue(ep_fback, req_fback, GFP_ATOMIC)) + dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); + return 0; } EXPORT_SYMBOL_GPL(u_audio_start_capture); @@ -382,6 +514,8 @@ void u_audio_stop_capture(struct g_audio *audio_dev) { struct snd_uac_chip *uac = audio_dev->uac; + if (audio_dev->in_ep_fback) + free_ep_fback(&uac->c_prm, audio_dev->in_ep_fback); free_ep(&uac->c_prm, audio_dev->out_ep); } EXPORT_SYMBOL_GPL(u_audio_stop_capture); @@ -463,12 +597,82 @@ void u_audio_stop_playback(struct g_audio *audio_dev) } EXPORT_SYMBOL_GPL(u_audio_stop_playback); +static int u_audio_pitch_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol); + struct snd_uac_chip *uac = prm->uac; + struct g_audio *audio_dev = uac->audio_dev; + struct uac_params *params = &audio_dev->params; + unsigned int pitch_min, pitch_max; + + pitch_min = (1000 - FBACK_SLOW_MAX) * 1000; + pitch_max = (1000 + params->fb_max) * 1000; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = pitch_min; + uinfo->value.integer.max = pitch_max; + uinfo->value.integer.step = 1; + return 0; +} + +static int u_audio_pitch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = prm->pitch; + + return 0; +} + +static int u_audio_pitch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct uac_rtd_params *prm = snd_kcontrol_chip(kcontrol); + struct snd_uac_chip *uac = prm->uac; + struct g_audio *audio_dev = uac->audio_dev; + struct uac_params *params = &audio_dev->params; + unsigned int val; + unsigned int pitch_min, pitch_max; + int change = 0; + + pitch_min = (1000 - FBACK_SLOW_MAX) * 1000; + pitch_max = (1000 + params->fb_max) * 1000; + + val = ucontrol->value.integer.value[0]; + + if (val < pitch_min) + val = pitch_min; + if (val > pitch_max) + val = pitch_max; + + if (prm->pitch != val) { + prm->pitch = val; + change = 1; + } + + return change; +} + +static const struct snd_kcontrol_new u_audio_controls[] = { +{ + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "Capture Pitch 1000000", + .info = u_audio_pitch_info, + .get = u_audio_pitch_get, + .put = u_audio_pitch_put, +}, +}; + int g_audio_setup(struct g_audio *g_audio, const char *pcm_name, const char *card_name) { struct snd_uac_chip *uac; struct snd_card *card; struct snd_pcm *pcm; + struct snd_kcontrol *kctl; struct uac_params *params; int p_chmask, c_chmask; int err; @@ -556,6 +760,23 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name, snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &uac_pcm_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &uac_pcm_ops); + if (c_chmask && g_audio->in_ep_fback) { + strscpy(card->mixername, card_name, sizeof(card->driver)); + + kctl = snd_ctl_new1(&u_audio_controls[0], &uac->c_prm); + if (!kctl) { + err = -ENOMEM; + goto snd_fail; + } + + kctl->id.device = pcm->device; + kctl->id.subdevice = 0; + + err = snd_ctl_add(card, kctl); + if (err < 0) + goto snd_fail; + } + strscpy(card->driver, card_name, sizeof(card->driver)); strscpy(card->shortname, card_name, sizeof(card->shortname)); sprintf(card->longname, "%s %i", card_name, card->dev->id); diff --git a/drivers/usb/gadget/function/u_audio.h b/drivers/usb/gadget/function/u_audio.h index 5ea6b86f1fda..a218cdf771fe 100644 --- a/drivers/usb/gadget/function/u_audio.h +++ b/drivers/usb/gadget/function/u_audio.h @@ -11,6 +11,14 @@ #include <linux/usb/composite.h> +/* + * Same maximum frequency deviation on the slower side as in + * sound/usb/endpoint.c. Value is expressed in per-mil deviation. + * The maximum deviation on the faster side will be provided as + * parameter, as it impacts the endpoint required bandwidth. + */ +#define FBACK_SLOW_MAX 250 + struct uac_params { /* playback */ int p_chmask; /* channel mask */ @@ -23,6 +31,7 @@ struct uac_params { int c_ssize; /* sample size */ int req_number; /* number of preallocated requests */ + int fb_max; /* upper frequency drift feedback limit per-mil */ }; struct g_audio { @@ -30,7 +39,10 @@ struct g_audio { struct usb_gadget *gadget; struct usb_ep *in_ep; + struct usb_ep *out_ep; + /* feedback IN endpoint corresponding to out_ep */ + struct usb_ep *in_ep_fback; /* Max packet size for all in_ep possible speeds */ unsigned int in_ep_maxpsize; diff --git a/drivers/usb/gadget/function/u_hid.h b/drivers/usb/gadget/function/u_hid.h index 84e6da302499..98d6af558c03 100644 --- a/drivers/usb/gadget/function/u_hid.h +++ b/drivers/usb/gadget/function/u_hid.h @@ -29,8 +29,8 @@ struct f_hid_opts { * Protect the data form concurrent access by read/write * and create symlink/remove symlink. */ - struct mutex lock; - int refcnt; + struct mutex lock; + int refcnt; }; int ghid_setup(struct usb_gadget *g, int count); diff --git a/drivers/usb/gadget/function/u_midi.h b/drivers/usb/gadget/function/u_midi.h index f6e14af7f566..2e400b495cb8 100644 --- a/drivers/usb/gadget/function/u_midi.h +++ b/drivers/usb/gadget/function/u_midi.h @@ -29,8 +29,8 @@ struct f_midi_opts { * Protect the data form concurrent access by read/write * and create symlink/remove symlink. */ - struct mutex lock; - int refcnt; + struct mutex lock; + int refcnt; }; #endif /* U_MIDI_H */ diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index 1e59204ec7aa..bffef8e47dac 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -774,34 +774,34 @@ static void gs_flush_chars(struct tty_struct *tty) spin_unlock_irqrestore(&port->port_lock, flags); } -static int gs_write_room(struct tty_struct *tty) +static unsigned int gs_write_room(struct tty_struct *tty) { struct gs_port *port = tty->driver_data; unsigned long flags; - int room = 0; + unsigned int room = 0; spin_lock_irqsave(&port->port_lock, flags); if (port->port_usb) room = kfifo_avail(&port->port_write_buf); spin_unlock_irqrestore(&port->port_lock, flags); - pr_vdebug("gs_write_room: (%d,%p) room=%d\n", + pr_vdebug("gs_write_room: (%d,%p) room=%u\n", port->port_num, tty, room); return room; } -static int gs_chars_in_buffer(struct tty_struct *tty) +static unsigned int gs_chars_in_buffer(struct tty_struct *tty) { struct gs_port *port = tty->driver_data; unsigned long flags; - int chars = 0; + unsigned int chars; spin_lock_irqsave(&port->port_lock, flags); chars = kfifo_len(&port->port_write_buf); spin_unlock_irqrestore(&port->port_lock, flags); - pr_vdebug("gs_chars_in_buffer: (%d,%p) chars=%d\n", + pr_vdebug("gs_chars_in_buffer: (%d,%p) chars=%u\n", port->port_num, tty, chars); return chars; diff --git a/drivers/usb/gadget/function/u_uac2.h b/drivers/usb/gadget/function/u_uac2.h index b5035711172d..179d3ef6a195 100644 --- a/drivers/usb/gadget/function/u_uac2.h +++ b/drivers/usb/gadget/function/u_uac2.h @@ -21,7 +21,9 @@ #define UAC2_DEF_CCHMASK 0x3 #define UAC2_DEF_CSRATE 64000 #define UAC2_DEF_CSSIZE 2 +#define UAC2_DEF_CSYNC USB_ENDPOINT_SYNC_ASYNC #define UAC2_DEF_REQ_NUM 2 +#define UAC2_DEF_FB_MAX 5 struct f_uac2_opts { struct usb_function_instance func_inst; @@ -31,7 +33,9 @@ struct f_uac2_opts { int c_chmask; int c_srate; int c_ssize; + int c_sync; int req_number; + int fb_max; bool bound; struct mutex lock; diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c index cd28dec837dd..77d64031aa9c 100644 --- a/drivers/usb/gadget/function/uvc_configfs.c +++ b/drivers/usb/gadget/function/uvc_configfs.c @@ -914,8 +914,6 @@ static int uvcg_streaming_header_allow_link(struct config_item *src, target_fmt = container_of(to_config_group(target), struct uvcg_format, group); - if (!target_fmt) - goto out; uvcg_format_set_indices(to_config_group(target)); @@ -955,8 +953,6 @@ static void uvcg_streaming_header_drop_link(struct config_item *src, mutex_lock(&opts->lock); target_fmt = container_of(to_config_group(target), struct uvcg_format, group); - if (!target_fmt) - goto out; list_for_each_entry_safe(format_ptr, tmp, &src_hdr->formats, entry) if (format_ptr->fmt == target_fmt) { @@ -968,7 +964,6 @@ static void uvcg_streaming_header_drop_link(struct config_item *src, --target_fmt->linked; -out: mutex_unlock(&opts->lock); mutex_unlock(su_mutex); } diff --git a/drivers/usb/gadget/legacy/hid.c b/drivers/usb/gadget/legacy/hid.c index c4eda7fe7ab4..5b27d289443f 100644 --- a/drivers/usb/gadget/legacy/hid.c +++ b/drivers/usb/gadget/legacy/hid.c @@ -171,8 +171,10 @@ static int hid_bind(struct usb_composite_dev *cdev) struct usb_descriptor_header *usb_desc; usb_desc = usb_otg_descriptor_alloc(gadget); - if (!usb_desc) + if (!usb_desc) { + status = -ENOMEM; goto put; + } usb_otg_descriptor_init(gadget, usb_desc); otg_desc[0] = usb_desc; otg_desc[1] = NULL; diff --git a/drivers/usb/gadget/udc/bcm63xx_udc.c b/drivers/usb/gadget/udc/bcm63xx_udc.c index 9cd4a70ccdd6..a9f07c59fc37 100644 --- a/drivers/usb/gadget/udc/bcm63xx_udc.c +++ b/drivers/usb/gadget/udc/bcm63xx_udc.c @@ -288,7 +288,6 @@ struct bcm63xx_req { * @ep0_req_completed: ep0 request has completed; worker has not seen it yet. * @ep0_reply: Pending reply from gadget driver. * @ep0_request: Outstanding ep0 request. - * @debugfs_root: debugfs directory: /sys/kernel/debug/<DRV_MODULE_NAME>. */ struct bcm63xx_udc { spinlock_t lock; @@ -327,8 +326,6 @@ struct bcm63xx_udc { unsigned ep0_req_completed:1; struct usb_request *ep0_reply; struct usb_request *ep0_request; - - struct dentry *debugfs_root; }; static const struct usb_ep_ops bcm63xx_udc_ep_ops; @@ -2250,8 +2247,6 @@ static void bcm63xx_udc_init_debugfs(struct bcm63xx_udc *udc) return; root = debugfs_create_dir(udc->gadget.name, usb_debug_root); - udc->debugfs_root = root; - debugfs_create_file("usbd", 0400, root, udc, &bcm63xx_usbd_dbg_fops); debugfs_create_file("iudma", 0400, root, udc, &bcm63xx_iudma_dbg_fops); } @@ -2264,7 +2259,7 @@ static void bcm63xx_udc_init_debugfs(struct bcm63xx_udc *udc) */ static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc) { - debugfs_remove_recursive(udc->debugfs_root); + debugfs_remove(debugfs_lookup(udc->gadget.name, usb_debug_root)); } /*********************************************************************** diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 493ff93f7dda..b7f0b1ebaaa8 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -1148,6 +1148,53 @@ static inline void usb_gadget_udc_set_speed(struct usb_udc *udc, } /** + * usb_gadget_enable_async_callbacks - tell usb device controller to enable asynchronous callbacks + * @udc: The UDC which should enable async callbacks + * + * This routine is used when binding gadget drivers. It undoes the effect + * of usb_gadget_disable_async_callbacks(); the UDC driver should enable IRQs + * (if necessary) and resume issuing callbacks. + * + * This routine will always be called in process context. + */ +static inline void usb_gadget_enable_async_callbacks(struct usb_udc *udc) +{ + struct usb_gadget *gadget = udc->gadget; + + if (gadget->ops->udc_async_callbacks) + gadget->ops->udc_async_callbacks(gadget, true); +} + +/** + * usb_gadget_disable_async_callbacks - tell usb device controller to disable asynchronous callbacks + * @udc: The UDC which should disable async callbacks + * + * This routine is used when unbinding gadget drivers. It prevents a race: + * The UDC driver doesn't know when the gadget driver's ->unbind callback + * runs, so unless it is told to disable asynchronous callbacks, it might + * issue a callback (such as ->disconnect) after the unbind has completed. + * + * After this function runs, the UDC driver must suppress all ->suspend, + * ->resume, ->disconnect, ->reset, and ->setup callbacks to the gadget driver + * until async callbacks are again enabled. A simple-minded but effective + * way to accomplish this is to tell the UDC hardware not to generate any + * more IRQs. + * + * Request completion callbacks must still be issued. However, it's okay + * to defer them until the request is cancelled, since the pull-up will be + * turned off during the time period when async callbacks are disabled. + * + * This routine will always be called in process context. + */ +static inline void usb_gadget_disable_async_callbacks(struct usb_udc *udc) +{ + struct usb_gadget *gadget = udc->gadget; + + if (gadget->ops->udc_async_callbacks) + gadget->ops->udc_async_callbacks(gadget, false); +} + +/** * usb_udc_release - release the usb_udc struct * @dev: the dev member within usb_udc * @@ -1361,6 +1408,7 @@ static void usb_gadget_remove_driver(struct usb_udc *udc) kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); usb_gadget_disconnect(udc->gadget); + usb_gadget_disable_async_callbacks(udc); if (udc->gadget->irq) synchronize_irq(udc->gadget->irq); udc->driver->unbind(udc->gadget); @@ -1442,6 +1490,7 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri driver->unbind(udc->gadget); goto err1; } + usb_gadget_enable_async_callbacks(udc); usb_udc_connect_control(udc); kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c index 7db773c87379..a2d956af42a2 100644 --- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c @@ -934,6 +934,15 @@ static void dummy_udc_set_speed(struct usb_gadget *_gadget, dummy_udc_update_ep0(dum); } +static void dummy_udc_async_callbacks(struct usb_gadget *_gadget, bool enable) +{ + struct dummy *dum = gadget_dev_to_dummy(&_gadget->dev); + + spin_lock_irq(&dum->lock); + dum->ints_enabled = enable; + spin_unlock_irq(&dum->lock); +} + static int dummy_udc_start(struct usb_gadget *g, struct usb_gadget_driver *driver); static int dummy_udc_stop(struct usb_gadget *g); @@ -946,6 +955,7 @@ static const struct usb_gadget_ops dummy_ops = { .udc_start = dummy_udc_start, .udc_stop = dummy_udc_stop, .udc_set_speed = dummy_udc_set_speed, + .udc_async_callbacks = dummy_udc_async_callbacks, }; /*-------------------------------------------------------------------------*/ @@ -1005,7 +1015,6 @@ static int dummy_udc_start(struct usb_gadget *g, spin_lock_irq(&dum->lock); dum->devstatus = 0; dum->driver = driver; - dum->ints_enabled = 1; spin_unlock_irq(&dum->lock); return 0; diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c index fa66449b3907..8e8588933628 100644 --- a/drivers/usb/gadget/udc/fsl_qe_udc.c +++ b/drivers/usb/gadget/udc/fsl_qe_udc.c @@ -541,6 +541,7 @@ static int qe_ep_init(struct qe_udc *udc, case USB_SPEED_HIGH: if ((max == 128) || (max == 256) || (max == 512)) break; + fallthrough; default: switch (max) { case 4: @@ -562,9 +563,11 @@ static int qe_ep_init(struct qe_udc *udc, case USB_SPEED_HIGH: if (max <= 1024) break; + fallthrough; case USB_SPEED_FULL: if (max <= 64) break; + fallthrough; default: if (max <= 8) break; @@ -579,6 +582,7 @@ static int qe_ep_init(struct qe_udc *udc, case USB_SPEED_HIGH: if (max <= 1024) break; + fallthrough; case USB_SPEED_FULL: if (max <= 1023) break; @@ -605,6 +609,7 @@ static int qe_ep_init(struct qe_udc *udc, default: goto en_done; } + fallthrough; case USB_SPEED_LOW: switch (max) { case 1: diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c index ad6ff9c4188e..29fcb9b461d7 100644 --- a/drivers/usb/gadget/udc/fsl_udc_core.c +++ b/drivers/usb/gadget/udc/fsl_udc_core.c @@ -36,7 +36,6 @@ #include <linux/platform_device.h> #include <linux/fsl_devices.h> #include <linux/dmapool.h> -#include <linux/delay.h> #include <linux/of_device.h> #include <asm/byteorder.h> @@ -323,13 +322,11 @@ static int dr_controller_setup(struct fsl_udc *udc) fsl_writel(tmp, &dr_regs->endptctrl[ep_num]); } /* Config control enable i/o output, cpu endian register */ -#ifndef CONFIG_ARCH_MXC if (udc->pdata->have_sysif_regs) { ctrl = __raw_readl(&usb_sys_regs->control); ctrl |= USB_CTRL_IOENB; __raw_writel(ctrl, &usb_sys_regs->control); } -#endif #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) /* Turn on cache snooping hardware, since some PowerPC platforms @@ -547,7 +544,7 @@ static int fsl_ep_enable(struct usb_ep *_ep, unsigned short max = 0; unsigned char mult = 0, zlt; int retval = -EINVAL; - unsigned long flags = 0; + unsigned long flags; ep = container_of(_ep, struct fsl_ep, ep); @@ -631,7 +628,7 @@ static int fsl_ep_disable(struct usb_ep *_ep) { struct fsl_udc *udc = NULL; struct fsl_ep *ep = NULL; - unsigned long flags = 0; + unsigned long flags; u32 epctrl; int ep_num; @@ -1001,7 +998,7 @@ out: epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]); static int fsl_ep_set_halt(struct usb_ep *_ep, int value) { struct fsl_ep *ep = NULL; - unsigned long flags = 0; + unsigned long flags; int status = -EOPNOTSUPP; /* operation not supported */ unsigned char ep_dir = 0, ep_num = 0; struct fsl_udc *udc = NULL; @@ -1938,7 +1935,7 @@ static int fsl_udc_start(struct usb_gadget *g, struct usb_gadget_driver *driver) { int retval = 0; - unsigned long flags = 0; + unsigned long flags; /* lock is needed but whether should use this lock or another */ spin_lock_irqsave(&udc_controller->lock, flags); @@ -2153,7 +2150,6 @@ static int fsl_proc_read(struct seq_file *m, void *v) tmp_reg = fsl_readl(&dr_regs->endpointprime); seq_printf(m, "EP Prime Reg = [0x%x]\n\n", tmp_reg); -#ifndef CONFIG_ARCH_MXC if (udc->pdata->have_sysif_regs) { tmp_reg = usb_sys_regs->snoop1; seq_printf(m, "Snoop1 Reg : = [0x%x]\n\n", tmp_reg); @@ -2161,7 +2157,6 @@ static int fsl_proc_read(struct seq_file *m, void *v) tmp_reg = usb_sys_regs->control; seq_printf(m, "General Control Reg : = [0x%x]\n\n", tmp_reg); } -#endif /* ------fsl_udc, fsl_ep, fsl_request structure information ----- */ ep = &udc->eps[0]; @@ -2412,28 +2407,21 @@ static int fsl_udc_probe(struct platform_device *pdev) */ if (pdata->init && pdata->init(pdev)) { ret = -ENODEV; - goto err_iounmap_noclk; + goto err_iounmap; } /* Set accessors only after pdata->init() ! */ fsl_set_accessors(pdata); -#ifndef CONFIG_ARCH_MXC if (pdata->have_sysif_regs) usb_sys_regs = (void *)dr_regs + USB_DR_SYS_OFFSET; -#endif - - /* Initialize USB clocks */ - ret = fsl_udc_clk_init(pdev); - if (ret < 0) - goto err_iounmap_noclk; /* Read Device Controller Capability Parameters register */ dccparams = fsl_readl(&dr_regs->dccparams); if (!(dccparams & DCCPARAMS_DC)) { ERR("This SOC doesn't support device role\n"); ret = -ENODEV; - goto err_iounmap; + goto err_exit; } /* Get max device endpoints */ /* DEN is bidirectional ep number, max_ep doubles the number */ @@ -2442,7 +2430,7 @@ static int fsl_udc_probe(struct platform_device *pdev) ret = platform_get_irq(pdev, 0); if (ret <= 0) { ret = ret ? : -ENODEV; - goto err_iounmap; + goto err_exit; } udc_controller->irq = ret; @@ -2451,7 +2439,7 @@ static int fsl_udc_probe(struct platform_device *pdev) if (ret != 0) { ERR("cannot request irq %d err %d\n", udc_controller->irq, ret); - goto err_iounmap; + goto err_exit; } /* Initialize the udc structure including QH member and other member */ @@ -2467,10 +2455,6 @@ static int fsl_udc_probe(struct platform_device *pdev) dr_controller_setup(udc_controller); } - ret = fsl_udc_clk_finalize(pdev); - if (ret) - goto err_free_irq; - /* Setup gadget structure */ udc_controller->gadget.ops = &fsl_gadget_ops; udc_controller->gadget.max_speed = USB_SPEED_HIGH; @@ -2530,11 +2514,10 @@ err_del_udc: dma_pool_destroy(udc_controller->td_pool); err_free_irq: free_irq(udc_controller->irq, udc_controller); -err_iounmap: +err_exit: if (pdata->exit) pdata->exit(pdev); - fsl_udc_clk_release(); -err_iounmap_noclk: +err_iounmap: iounmap(dr_regs); err_release_mem_region: if (pdata->operating_mode == FSL_USB2_DR_DEVICE) @@ -2561,8 +2544,6 @@ static int fsl_udc_remove(struct platform_device *pdev) udc_controller->done = &done; usb_del_gadget_udc(&udc_controller->gadget); - fsl_udc_clk_release(); - /* DR has been stopped in usb_gadget_unregister_driver() */ remove_proc_file(); @@ -2677,10 +2658,6 @@ static int fsl_udc_otg_resume(struct device *dev) --------------------------------------------------------------------------*/ static const struct platform_device_id fsl_udc_devtype[] = { { - .name = "imx-udc-mx27", - }, { - .name = "imx-udc-mx51", - }, { .name = "fsl-usb2-udc", }, { /* sentinel */ @@ -2689,7 +2666,6 @@ static const struct platform_device_id fsl_udc_devtype[] = { MODULE_DEVICE_TABLE(platform, fsl_udc_devtype); static struct platform_driver udc_driver = { .remove = fsl_udc_remove, - /* Just for FSL i.mx SoC currently */ .id_table = fsl_udc_devtype, /* these suspend and resume are not usb suspend and resume */ .suspend = fsl_udc_suspend, diff --git a/drivers/usb/gadget/udc/fsl_usb2_udc.h b/drivers/usb/gadget/udc/fsl_usb2_udc.h index 4ba651ae9048..2efc5a930b48 100644 --- a/drivers/usb/gadget/udc/fsl_usb2_udc.h +++ b/drivers/usb/gadget/udc/fsl_usb2_udc.h @@ -588,23 +588,4 @@ static inline struct ep_queue_head *get_qh_by_ep(struct fsl_ep *ep) USB_DIR_IN) ? 1 : 0]; } -struct platform_device; -#ifdef CONFIG_ARCH_MXC -int fsl_udc_clk_init(struct platform_device *pdev); -int fsl_udc_clk_finalize(struct platform_device *pdev); -void fsl_udc_clk_release(void); -#else -static inline int fsl_udc_clk_init(struct platform_device *pdev) -{ - return 0; -} -static inline int fsl_udc_clk_finalize(struct platform_device *pdev) -{ - return 0; -} -static inline void fsl_udc_clk_release(void) -{ -} -#endif - #endif diff --git a/drivers/usb/gadget/udc/gr_udc.c b/drivers/usb/gadget/udc/gr_udc.c index f8f3aa52383b..4b35739d3695 100644 --- a/drivers/usb/gadget/udc/gr_udc.c +++ b/drivers/usb/gadget/udc/gr_udc.c @@ -207,14 +207,15 @@ DEFINE_SHOW_ATTRIBUTE(gr_dfs); static void gr_dfs_create(struct gr_udc *dev) { const char *name = "gr_udc_state"; + struct dentry *root; - dev->dfs_root = debugfs_create_dir(dev_name(dev->dev), usb_debug_root); - debugfs_create_file(name, 0444, dev->dfs_root, dev, &gr_dfs_fops); + root = debugfs_create_dir(dev_name(dev->dev), usb_debug_root); + debugfs_create_file(name, 0444, root, dev, &gr_dfs_fops); } static void gr_dfs_delete(struct gr_udc *dev) { - debugfs_remove_recursive(dev->dfs_root); + debugfs_remove(debugfs_lookup(dev_name(dev->dev), usb_debug_root)); } #else /* !CONFIG_USB_GADGET_DEBUG_FS */ diff --git a/drivers/usb/gadget/udc/gr_udc.h b/drivers/usb/gadget/udc/gr_udc.h index ac5b3f65adb5..70134239179e 100644 --- a/drivers/usb/gadget/udc/gr_udc.h +++ b/drivers/usb/gadget/udc/gr_udc.h @@ -215,8 +215,6 @@ struct gr_udc { struct list_head ep_list; spinlock_t lock; /* General lock, a.k.a. "dev->lock" in comments */ - - struct dentry *dfs_root; }; #define to_gr_udc(gadget) (container_of((gadget), struct gr_udc, gadget)) diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c index 3f1c62adce4b..a25d01c89564 100644 --- a/drivers/usb/gadget/udc/lpc32xx_udc.c +++ b/drivers/usb/gadget/udc/lpc32xx_udc.c @@ -127,7 +127,6 @@ struct lpc32xx_udc { struct usb_gadget_driver *driver; struct platform_device *pdev; struct device *dev; - struct dentry *pde; spinlock_t lock; struct i2c_client *isp1301_i2c_client; @@ -528,12 +527,12 @@ DEFINE_SHOW_ATTRIBUTE(udc); static void create_debug_file(struct lpc32xx_udc *udc) { - udc->pde = debugfs_create_file(debug_filename, 0, NULL, udc, &udc_fops); + debugfs_create_file(debug_filename, 0, NULL, udc, &udc_fops); } static void remove_debug_file(struct lpc32xx_udc *udc) { - debugfs_remove(udc->pde); + debugfs_remove(debugfs_lookup(debug_filename, NULL)); } #else diff --git a/drivers/usb/gadget/udc/mv_u3d_core.c b/drivers/usb/gadget/udc/mv_u3d_core.c index 5486f5a70868..ce3d7a3eb7e3 100644 --- a/drivers/usb/gadget/udc/mv_u3d_core.c +++ b/drivers/usb/gadget/udc/mv_u3d_core.c @@ -941,7 +941,7 @@ mv_u3d_ep_set_stall(struct mv_u3d *u3d, u8 ep_num, u8 direction, int stall) static int mv_u3d_ep_set_halt_wedge(struct usb_ep *_ep, int halt, int wedge) { struct mv_u3d_ep *ep; - unsigned long flags = 0; + unsigned long flags; int status = 0; struct mv_u3d *u3d; diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c index 0fb4ef464321..7f24ce400b59 100644 --- a/drivers/usb/gadget/udc/mv_udc_core.c +++ b/drivers/usb/gadget/udc/mv_udc_core.c @@ -888,7 +888,7 @@ static int ep_is_stall(struct mv_udc *udc, u8 ep_num, u8 direction) static int mv_ep_set_halt_wedge(struct usb_ep *_ep, int halt, int wedge) { struct mv_ep *ep; - unsigned long flags = 0; + unsigned long flags; int status = 0; struct mv_udc *udc; diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c index 89f479b78d80..7c38057dcb4a 100644 --- a/drivers/usb/gadget/udc/net2272.c +++ b/drivers/usb/gadget/udc/net2272.c @@ -1150,6 +1150,7 @@ net2272_pullup(struct usb_gadget *_gadget, int is_on) static int net2272_start(struct usb_gadget *_gadget, struct usb_gadget_driver *driver); static int net2272_stop(struct usb_gadget *_gadget); +static void net2272_async_callbacks(struct usb_gadget *_gadget, bool enable); static const struct usb_gadget_ops net2272_ops = { .get_frame = net2272_get_frame, @@ -1158,6 +1159,7 @@ static const struct usb_gadget_ops net2272_ops = { .pullup = net2272_pullup, .udc_start = net2272_start, .udc_stop = net2272_stop, + .udc_async_callbacks = net2272_async_callbacks, }; /*---------------------------------------------------------------------------*/ @@ -1476,7 +1478,7 @@ stop_activity(struct net2272 *dev, struct usb_gadget_driver *driver) net2272_dequeue_all(&dev->ep[i]); /* report disconnect; the driver is already quiesced */ - if (driver) { + if (dev->async_callbacks && driver) { spin_unlock(&dev->lock); driver->disconnect(&dev->gadget); spin_lock(&dev->lock); @@ -1501,6 +1503,15 @@ static int net2272_stop(struct usb_gadget *_gadget) return 0; } +static void net2272_async_callbacks(struct usb_gadget *_gadget, bool enable) +{ + struct net2272 *dev = container_of(_gadget, struct net2272, gadget); + + spin_lock_irq(&dev->lock); + dev->async_callbacks = enable; + spin_unlock_irq(&dev->lock); +} + /*---------------------------------------------------------------------------*/ /* handle ep-a/ep-b dma completions */ static void @@ -1910,9 +1921,11 @@ net2272_handle_stat0_irqs(struct net2272 *dev, u8 stat) u.r.bRequestType, u.r.bRequest, u.r.wValue, u.r.wIndex, net2272_ep_read(ep, EP_CFG)); - spin_unlock(&dev->lock); - tmp = dev->driver->setup(&dev->gadget, &u.r); - spin_lock(&dev->lock); + if (dev->async_callbacks) { + spin_unlock(&dev->lock); + tmp = dev->driver->setup(&dev->gadget, &u.r); + spin_lock(&dev->lock); + } } /* stall ep0 on error */ @@ -1994,14 +2007,14 @@ net2272_handle_stat1_irqs(struct net2272 *dev, u8 stat) if (disconnect || reset) { stop_activity(dev, dev->driver); net2272_ep0_start(dev); - spin_unlock(&dev->lock); - if (reset) - usb_gadget_udc_reset - (&dev->gadget, dev->driver); - else - (dev->driver->disconnect) - (&dev->gadget); - spin_lock(&dev->lock); + if (dev->async_callbacks) { + spin_unlock(&dev->lock); + if (reset) + usb_gadget_udc_reset(&dev->gadget, dev->driver); + else + (dev->driver->disconnect)(&dev->gadget); + spin_lock(&dev->lock); + } return; } } @@ -2015,14 +2028,14 @@ net2272_handle_stat1_irqs(struct net2272 *dev, u8 stat) if (stat & tmp) { net2272_write(dev, IRQSTAT1, tmp); if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) { - if (dev->driver->suspend) + if (dev->async_callbacks && dev->driver->suspend) dev->driver->suspend(&dev->gadget); if (!enable_suspend) { stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT); dev_dbg(dev->dev, "Suspend disabled, ignoring\n"); } } else { - if (dev->driver->resume) + if (dev->async_callbacks && dev->driver->resume) dev->driver->resume(&dev->gadget); } stat &= ~tmp; diff --git a/drivers/usb/gadget/udc/net2272.h b/drivers/usb/gadget/udc/net2272.h index c669308111c2..a9994f737588 100644 --- a/drivers/usb/gadget/udc/net2272.h +++ b/drivers/usb/gadget/udc/net2272.h @@ -442,6 +442,7 @@ struct net2272 { softconnect:1, wakeup:1, added:1, + async_callbacks:1, dma_eot_polarity:1, dma_dack_polarity:1, dma_dreq_polarity:1, diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c index fc9f99fe7f37..16e7d2db6411 100644 --- a/drivers/usb/gadget/udc/net2280.c +++ b/drivers/usb/gadget/udc/net2280.c @@ -1617,6 +1617,7 @@ static struct usb_ep *net2280_match_ep(struct usb_gadget *_gadget, static int net2280_start(struct usb_gadget *_gadget, struct usb_gadget_driver *driver); static int net2280_stop(struct usb_gadget *_gadget); +static void net2280_async_callbacks(struct usb_gadget *_gadget, bool enable); static const struct usb_gadget_ops net2280_ops = { .get_frame = net2280_get_frame, @@ -1625,6 +1626,7 @@ static const struct usb_gadget_ops net2280_ops = { .pullup = net2280_pullup, .udc_start = net2280_start, .udc_stop = net2280_stop, + .udc_async_callbacks = net2280_async_callbacks, .match_ep = net2280_match_ep, }; @@ -2472,7 +2474,7 @@ static void stop_activity(struct net2280 *dev, struct usb_gadget_driver *driver) nuke(&dev->ep[i]); /* report disconnect; the driver is already quiesced */ - if (driver) { + if (dev->async_callbacks && driver) { spin_unlock(&dev->lock); driver->disconnect(&dev->gadget); spin_lock(&dev->lock); @@ -2502,6 +2504,15 @@ static int net2280_stop(struct usb_gadget *_gadget) return 0; } +static void net2280_async_callbacks(struct usb_gadget *_gadget, bool enable) +{ + struct net2280 *dev = container_of(_gadget, struct net2280, gadget); + + spin_lock_irq(&dev->lock); + dev->async_callbacks = enable; + spin_unlock_irq(&dev->lock); +} + /*-------------------------------------------------------------------------*/ /* handle ep0, ep-e, ep-f with 64 byte packets: packet per irq. @@ -2814,8 +2825,6 @@ static void defect7374_workaround(struct net2280 *dev, struct usb_ctrlrequest r) * - Wait and try again. */ udelay(DEFECT_7374_PROCESSOR_WAIT_TIME); - - continue; } @@ -3042,9 +3051,11 @@ usb3_delegate: readl(&ep->cfg->ep_cfg)); ep->responded = 0; - spin_unlock(&dev->lock); - tmp = dev->driver->setup(&dev->gadget, &r); - spin_lock(&dev->lock); + if (dev->async_callbacks) { + spin_unlock(&dev->lock); + tmp = dev->driver->setup(&dev->gadget, &r); + spin_lock(&dev->lock); + } } do_stall3: if (tmp < 0) { @@ -3284,9 +3295,11 @@ delegate: w_value, w_index, w_length, readl(&ep->cfg->ep_cfg)); ep->responded = 0; - spin_unlock(&dev->lock); - tmp = dev->driver->setup(&dev->gadget, &u.r); - spin_lock(&dev->lock); + if (dev->async_callbacks) { + spin_unlock(&dev->lock); + tmp = dev->driver->setup(&dev->gadget, &u.r); + spin_lock(&dev->lock); + } } /* stall ep0 on error */ @@ -3391,14 +3404,14 @@ __acquires(dev->lock) if (disconnect || reset) { stop_activity(dev, dev->driver); ep0_start(dev); - spin_unlock(&dev->lock); - if (reset) - usb_gadget_udc_reset - (&dev->gadget, dev->driver); - else - (dev->driver->disconnect) - (&dev->gadget); - spin_lock(&dev->lock); + if (dev->async_callbacks) { + spin_unlock(&dev->lock); + if (reset) + usb_gadget_udc_reset(&dev->gadget, dev->driver); + else + (dev->driver->disconnect)(&dev->gadget); + spin_lock(&dev->lock); + } return; } } @@ -3419,12 +3432,12 @@ __acquires(dev->lock) writel(tmp, &dev->regs->irqstat1); spin_unlock(&dev->lock); if (stat & BIT(SUSPEND_REQUEST_INTERRUPT)) { - if (dev->driver->suspend) + if (dev->async_callbacks && dev->driver->suspend) dev->driver->suspend(&dev->gadget); if (!enable_suspend) stat &= ~BIT(SUSPEND_REQUEST_INTERRUPT); } else { - if (dev->driver->resume) + if (dev->async_callbacks && dev->driver->resume) dev->driver->resume(&dev->gadget); /* at high speed, note erratum 0133 */ } diff --git a/drivers/usb/gadget/udc/net2280.h b/drivers/usb/gadget/udc/net2280.h index 7da3dc1e9729..34716a9f4926 100644 --- a/drivers/usb/gadget/udc/net2280.h +++ b/drivers/usb/gadget/udc/net2280.h @@ -162,6 +162,7 @@ struct net2280 { ltm_enable:1, wakeup_enable:1, addressed_state:1, + async_callbacks:1, bug7734_patched:1; u16 chiprev; int enhanced_mode; diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c index 10324a7334fe..69ef1e669d0c 100644 --- a/drivers/usb/gadget/udc/pxa25x_udc.c +++ b/drivers/usb/gadget/udc/pxa25x_udc.c @@ -1338,10 +1338,10 @@ DEFINE_SHOW_ATTRIBUTE(udc_debug); #define create_debug_files(dev) \ do { \ - dev->debugfs_udc = debugfs_create_file(dev->gadget.name, \ + debugfs_create_file(dev->gadget.name, \ S_IRUGO, NULL, dev, &udc_debug_fops); \ } while (0) -#define remove_debug_files(dev) debugfs_remove(dev->debugfs_udc) +#define remove_debug_files(dev) debugfs_remove(debugfs_lookup(dev->gadget.name, NULL)) #else /* !CONFIG_USB_GADGET_DEBUG_FILES */ diff --git a/drivers/usb/gadget/udc/pxa25x_udc.h b/drivers/usb/gadget/udc/pxa25x_udc.h index ccc6b921f067..aa4b68fd9fc0 100644 --- a/drivers/usb/gadget/udc/pxa25x_udc.h +++ b/drivers/usb/gadget/udc/pxa25x_udc.h @@ -116,10 +116,6 @@ struct pxa25x_udc { struct usb_phy *transceiver; u64 dma_mask; struct pxa25x_ep ep [PXA_UDC_NUM_ENDPOINTS]; - -#ifdef CONFIG_USB_GADGET_DEBUG_FS - struct dentry *debugfs_udc; -#endif void __iomem *regs; }; #define to_pxa25x(g) (container_of((g), struct pxa25x_udc, gadget)) diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c index ce57961dfd2d..f4b7a2a3e711 100644 --- a/drivers/usb/gadget/udc/pxa27x_udc.c +++ b/drivers/usb/gadget/udc/pxa27x_udc.c @@ -208,8 +208,6 @@ static void pxa_init_debugfs(struct pxa_udc *udc) struct dentry *root; root = debugfs_create_dir(udc->gadget.name, usb_debug_root); - udc->debugfs_root = root; - debugfs_create_file("udcstate", 0400, root, udc, &state_dbg_fops); debugfs_create_file("queues", 0400, root, udc, &queues_dbg_fops); debugfs_create_file("epstate", 0400, root, udc, &eps_dbg_fops); @@ -217,7 +215,7 @@ static void pxa_init_debugfs(struct pxa_udc *udc) static void pxa_cleanup_debugfs(struct pxa_udc *udc) { - debugfs_remove_recursive(udc->debugfs_root); + debugfs_remove(debugfs_lookup(udc->gadget.name, usb_debug_root)); } #else @@ -1730,7 +1728,7 @@ static void udc_enable(struct pxa_udc *udc) } /** - * pxa27x_start - Register gadget driver + * pxa27x_udc_start - Register gadget driver * @g: gadget * @driver: gadget driver * diff --git a/drivers/usb/gadget/udc/pxa27x_udc.h b/drivers/usb/gadget/udc/pxa27x_udc.h index 13b2977399ab..0a6bc18a1264 100644 --- a/drivers/usb/gadget/udc/pxa27x_udc.h +++ b/drivers/usb/gadget/udc/pxa27x_udc.h @@ -440,7 +440,6 @@ struct udc_stats { * @last_interface: UDC interface of the last SET_INTERFACE host request * @last_alternate: UDC altsetting of the last SET_INTERFACE host request * @udccsr0: save of udccsr0 in case of suspend - * @debugfs_root: root entry of debug filesystem * @debugfs_state: debugfs entry for "udcstate" * @debugfs_queues: debugfs entry for "queues" * @debugfs_eps: debugfs entry for "epstate" @@ -474,9 +473,6 @@ struct pxa_udc { #ifdef CONFIG_PM unsigned udccsr0; #endif -#ifdef CONFIG_USB_GADGET_DEBUG_FS - struct dentry *debugfs_root; -#endif }; #define to_pxa(g) (container_of((g), struct pxa_udc, gadget)) diff --git a/drivers/usb/gadget/udc/s3c-hsudc.c b/drivers/usb/gadget/udc/s3c-hsudc.c index 7bd5182ce3ef..89f1f8c9f02e 100644 --- a/drivers/usb/gadget/udc/s3c-hsudc.c +++ b/drivers/usb/gadget/udc/s3c-hsudc.c @@ -1220,9 +1220,8 @@ static int s3c_hsudc_probe(struct platform_device *pdev) struct s3c24xx_hsudc_platdata *pd = dev_get_platdata(&pdev->dev); int ret, i; - hsudc = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsudc) + - sizeof(struct s3c_hsudc_ep) * pd->epnum, - GFP_KERNEL); + hsudc = devm_kzalloc(&pdev->dev, struct_size(hsudc, ep, pd->epnum), + GFP_KERNEL); if (!hsudc) return -ENOMEM; diff --git a/drivers/usb/gadget/udc/s3c2410_udc.c b/drivers/usb/gadget/udc/s3c2410_udc.c index b154b62abefa..179777cb699f 100644 --- a/drivers/usb/gadget/udc/s3c2410_udc.c +++ b/drivers/usb/gadget/udc/s3c2410_udc.c @@ -198,7 +198,7 @@ static inline void s3c2410_udc_set_ep0_de(void __iomem *base) udc_writeb(base, S3C2410_UDC_EP0_CSR_DE, S3C2410_UDC_EP0_CSR_REG); } -inline void s3c2410_udc_set_ep0_ss(void __iomem *b) +static inline void s3c2410_udc_set_ep0_ss(void __iomem *b) { udc_writeb(b, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); udc_writeb(b, S3C2410_UDC_EP0_CSR_SENDSTL, S3C2410_UDC_EP0_CSR_REG); @@ -1843,9 +1843,8 @@ static int s3c2410_udc_probe(struct platform_device *pdev) if (retval) goto err_add_udc; - udc->regs_info = debugfs_create_file("registers", S_IRUGO, - s3c2410_udc_debugfs_root, udc, - &s3c2410_udc_debugfs_fops); + debugfs_create_file("registers", S_IRUGO, s3c2410_udc_debugfs_root, udc, + &s3c2410_udc_debugfs_fops); dev_dbg(dev, "probe ok\n"); @@ -1889,7 +1888,7 @@ static int s3c2410_udc_remove(struct platform_device *pdev) return -EBUSY; usb_del_gadget_udc(&udc->gadget); - debugfs_remove(udc->regs_info); + debugfs_remove(debugfs_lookup("registers", s3c2410_udc_debugfs_root)); if (udc_info && !udc_info->udc_command && gpio_is_valid(udc_info->pullup_pin)) diff --git a/drivers/usb/gadget/udc/s3c2410_udc.h b/drivers/usb/gadget/udc/s3c2410_udc.h index 68bdf3e5aac2..135a5bff3c74 100644 --- a/drivers/usb/gadget/udc/s3c2410_udc.h +++ b/drivers/usb/gadget/udc/s3c2410_udc.h @@ -89,7 +89,6 @@ struct s3c2410_udc { unsigned req_config : 1; unsigned req_pending : 1; u8 vbus; - struct dentry *regs_info; int irq; }; #define to_s3c2410(g) (container_of((g), struct s3c2410_udc, gadget)) diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c index 2319c9737c2b..a54d1cef17db 100644 --- a/drivers/usb/gadget/udc/tegra-xudc.c +++ b/drivers/usb/gadget/udc/tegra-xudc.c @@ -1907,7 +1907,7 @@ static void tegra_xudc_ep_free_request(struct usb_ep *usb_ep, kfree(req); } -static struct usb_ep_ops tegra_xudc_ep_ops = { +static const struct usb_ep_ops tegra_xudc_ep_ops = { .enable = tegra_xudc_ep_enable, .disable = tegra_xudc_ep_disable, .alloc_request = tegra_xudc_ep_alloc_request, @@ -1928,7 +1928,7 @@ static int tegra_xudc_ep0_disable(struct usb_ep *usb_ep) return -EBUSY; } -static struct usb_ep_ops tegra_xudc_ep0_ops = { +static const struct usb_ep_ops tegra_xudc_ep0_ops = { .enable = tegra_xudc_ep0_enable, .disable = tegra_xudc_ep0_disable, .alloc_request = tegra_xudc_ep_alloc_request, @@ -2168,7 +2168,7 @@ static int tegra_xudc_set_selfpowered(struct usb_gadget *gadget, int is_on) return 0; } -static struct usb_gadget_ops tegra_xudc_gadget_ops = { +static const struct usb_gadget_ops tegra_xudc_gadget_ops = { .get_frame = tegra_xudc_gadget_get_frame, .wakeup = tegra_xudc_gadget_wakeup, .pullup = tegra_xudc_gadget_pullup, @@ -3508,10 +3508,8 @@ static int tegra_xudc_phy_get(struct tegra_xudc *xudc) xudc->utmi_phy[i] = devm_phy_optional_get(xudc->dev, phy_name); if (IS_ERR(xudc->utmi_phy[i])) { err = PTR_ERR(xudc->utmi_phy[i]); - if (err != -EPROBE_DEFER) - dev_err(xudc->dev, "failed to get usb2-%d PHY: %d\n", - i, err); - + dev_err_probe(xudc->dev, err, + "failed to get usb2-%d PHY\n", i); goto clean_up; } else if (xudc->utmi_phy[i]) { /* Get usb-phy, if utmi phy is available */ @@ -3520,8 +3518,8 @@ static int tegra_xudc_phy_get(struct tegra_xudc *xudc) &xudc->vbus_nb); if (IS_ERR(xudc->usbphy[i])) { err = PTR_ERR(xudc->usbphy[i]); - dev_err(xudc->dev, "failed to get usbphy-%d: %d\n", - i, err); + dev_err_probe(xudc->dev, err, + "failed to get usbphy-%d\n", i); goto clean_up; } } else if (!xudc->utmi_phy[i]) { @@ -3538,10 +3536,8 @@ static int tegra_xudc_phy_get(struct tegra_xudc *xudc) xudc->usb3_phy[i] = devm_phy_optional_get(xudc->dev, phy_name); if (IS_ERR(xudc->usb3_phy[i])) { err = PTR_ERR(xudc->usb3_phy[i]); - if (err != -EPROBE_DEFER) - dev_err(xudc->dev, "failed to get usb3-%d PHY: %d\n", - usb3, err); - + dev_err_probe(xudc->dev, err, + "failed to get usb3-%d PHY\n", usb3); goto clean_up; } else if (xudc->usb3_phy[i]) dev_dbg(xudc->dev, "usb3-%d PHY registered", usb3); @@ -3781,9 +3777,7 @@ static int tegra_xudc_probe(struct platform_device *pdev) err = devm_clk_bulk_get(&pdev->dev, xudc->soc->num_clks, xudc->clks); if (err) { - if (err != -EPROBE_DEFER) - dev_err(xudc->dev, "failed to request clocks: %d\n", err); - + dev_err_probe(xudc->dev, err, "failed to request clocks\n"); return err; } @@ -3798,9 +3792,7 @@ static int tegra_xudc_probe(struct platform_device *pdev) err = devm_regulator_bulk_get(&pdev->dev, xudc->soc->num_supplies, xudc->supplies); if (err) { - if (err != -EPROBE_DEFER) - dev_err(xudc->dev, "failed to request regulators: %d\n", err); - + dev_err_probe(xudc->dev, err, "failed to request regulators\n"); return err; } diff --git a/drivers/usb/gadget/udc/trace.c b/drivers/usb/gadget/udc/trace.c index 7430624c0bd7..19e837de2a20 100644 --- a/drivers/usb/gadget/udc/trace.c +++ b/drivers/usb/gadget/udc/trace.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/** +/* * trace.c - USB Gadget Framework Trace Support * * Copyright (C) 2016 Intel Corporation diff --git a/drivers/usb/gadget/udc/trace.h b/drivers/usb/gadget/udc/trace.h index 2d1f68b5ea76..98584f6b6c66 100644 --- a/drivers/usb/gadget/udc/trace.h +++ b/drivers/usb/gadget/udc/trace.h @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/** +/* * udc.c - Core UDC Framework * * Copyright (C) 2016 Intel Corporation diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c index 72f2ea062d55..fb4ffedd6f0d 100644 --- a/drivers/usb/gadget/udc/udc-xilinx.c +++ b/drivers/usb/gadget/udc/udc-xilinx.c @@ -791,7 +791,7 @@ static int xudc_ep_set_halt(struct usb_ep *_ep, int value) } /** - * xudc_ep_enable - Enables the given endpoint. + * __xudc_ep_enable - Enables the given endpoint. * @ep: pointer to the xusb endpoint structure. * @desc: pointer to usb endpoint descriptor. * @@ -987,7 +987,7 @@ static void xudc_free_request(struct usb_ep *_ep, struct usb_request *_req) } /** - * xudc_ep0_queue - Adds the request to endpoint 0 queue. + * __xudc_ep0_queue - Adds the request to endpoint 0 queue. * @ep0: pointer to the xusb endpoint 0 structure. * @req: pointer to the xusb request structure. * diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 6f7bd6641694..385be30baad3 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -387,11 +387,11 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) /* EHCI registers start at offset 0x100 */ ehci->caps = hcd->regs + 0x100; -#ifdef CONFIG_PPC_83xx +#if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_85xx) /* - * Deal with MPC834X that need port power to be cycled after the power - * fault condition is removed. Otherwise the state machine does not - * reflect PORTSC[CSC] correctly. + * Deal with MPC834X/85XX that need port power to be cycled + * after the power fault condition is removed. Otherwise the + * state machine does not reflect PORTSC[CSC] correctly. */ ehci->need_oc_pp_cycle = 1; #endif diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 94b5e64ae9a2..36f5bf6a0752 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -76,12 +76,12 @@ static const char hcd_name [] = "ehci_hcd"; #define EHCI_TUNE_FLS 1 /* (medium) 512-frame schedule */ /* Initial IRQ latency: faster than hw default */ -static int log2_irq_thresh = 0; // 0 to 6 +static int log2_irq_thresh; // 0 to 6 module_param (log2_irq_thresh, int, S_IRUGO); MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes"); /* initial park setting: slower than hw default */ -static unsigned park = 0; +static unsigned park; module_param (park, uint, S_IRUGO); MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets"); @@ -1238,6 +1238,10 @@ static const struct hc_driver ehci_hc_driver = { * device support */ .free_dev = ehci_remove_device, +#ifdef CONFIG_USB_HCD_TEST_MODE + /* EH SINGLE_STEP_SET_FEATURE test support */ + .submit_single_step_set_feature = ehci_submit_single_step_set_feature, +#endif }; void ehci_init_driver(struct hc_driver *drv, diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 159cc27b1a36..c4f6a2559a98 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -727,145 +727,6 @@ ehci_hub_descriptor ( } /*-------------------------------------------------------------------------*/ -#ifdef CONFIG_USB_HCD_TEST_MODE - -#define EHSET_TEST_SINGLE_STEP_SET_FEATURE 0x06 - -static void usb_ehset_completion(struct urb *urb) -{ - struct completion *done = urb->context; - - complete(done); -} -static int submit_single_step_set_feature( - struct usb_hcd *hcd, - struct urb *urb, - int is_setup -); - -/* - * Allocate and initialize a control URB. This request will be used by the - * EHSET SINGLE_STEP_SET_FEATURE test in which the DATA and STATUS stages - * of the GetDescriptor request are sent 15 seconds after the SETUP stage. - * Return NULL if failed. - */ -static struct urb *request_single_step_set_feature_urb( - struct usb_device *udev, - void *dr, - void *buf, - struct completion *done -) { - struct urb *urb; - struct usb_hcd *hcd = bus_to_hcd(udev->bus); - struct usb_host_endpoint *ep; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - return NULL; - - urb->pipe = usb_rcvctrlpipe(udev, 0); - ep = (usb_pipein(urb->pipe) ? udev->ep_in : udev->ep_out) - [usb_pipeendpoint(urb->pipe)]; - if (!ep) { - usb_free_urb(urb); - return NULL; - } - - urb->ep = ep; - urb->dev = udev; - urb->setup_packet = (void *)dr; - urb->transfer_buffer = buf; - urb->transfer_buffer_length = USB_DT_DEVICE_SIZE; - urb->complete = usb_ehset_completion; - urb->status = -EINPROGRESS; - urb->actual_length = 0; - urb->transfer_flags = URB_DIR_IN; - usb_get_urb(urb); - atomic_inc(&urb->use_count); - atomic_inc(&urb->dev->urbnum); - urb->setup_dma = dma_map_single( - hcd->self.sysdev, - urb->setup_packet, - sizeof(struct usb_ctrlrequest), - DMA_TO_DEVICE); - urb->transfer_dma = dma_map_single( - hcd->self.sysdev, - urb->transfer_buffer, - urb->transfer_buffer_length, - DMA_FROM_DEVICE); - urb->context = done; - return urb; -} - -static int ehset_single_step_set_feature(struct usb_hcd *hcd, int port) -{ - int retval = -ENOMEM; - struct usb_ctrlrequest *dr; - struct urb *urb; - struct usb_device *udev; - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - struct usb_device_descriptor *buf; - DECLARE_COMPLETION_ONSTACK(done); - - /* Obtain udev of the rhub's child port */ - udev = usb_hub_find_child(hcd->self.root_hub, port); - if (!udev) { - ehci_err(ehci, "No device attached to the RootHub\n"); - return -ENODEV; - } - buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); - if (!dr) { - kfree(buf); - return -ENOMEM; - } - - /* Fill Setup packet for GetDescriptor */ - dr->bRequestType = USB_DIR_IN; - dr->bRequest = USB_REQ_GET_DESCRIPTOR; - dr->wValue = cpu_to_le16(USB_DT_DEVICE << 8); - dr->wIndex = 0; - dr->wLength = cpu_to_le16(USB_DT_DEVICE_SIZE); - urb = request_single_step_set_feature_urb(udev, dr, buf, &done); - if (!urb) - goto cleanup; - - /* Submit just the SETUP stage */ - retval = submit_single_step_set_feature(hcd, urb, 1); - if (retval) - goto out1; - if (!wait_for_completion_timeout(&done, msecs_to_jiffies(2000))) { - usb_kill_urb(urb); - retval = -ETIMEDOUT; - ehci_err(ehci, "%s SETUP stage timed out on ep0\n", __func__); - goto out1; - } - msleep(15 * 1000); - - /* Complete remaining DATA and STATUS stages using the same URB */ - urb->status = -EINPROGRESS; - usb_get_urb(urb); - atomic_inc(&urb->use_count); - atomic_inc(&urb->dev->urbnum); - retval = submit_single_step_set_feature(hcd, urb, 0); - if (!retval && !wait_for_completion_timeout(&done, - msecs_to_jiffies(2000))) { - usb_kill_urb(urb); - retval = -ETIMEDOUT; - ehci_err(ehci, "%s IN stage timed out on ep0\n", __func__); - } -out1: - usb_free_urb(urb); -cleanup: - kfree(dr); - kfree(buf); - return retval; -} -#endif /* CONFIG_USB_HCD_TEST_MODE */ -/*-------------------------------------------------------------------------*/ int ehci_hub_control( struct usb_hcd *hcd, diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index a826715ae9bd..2cbf4f85bff3 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1165,7 +1165,7 @@ submit_async ( * performed; TRUE - SETUP and FALSE - IN+STATUS * Returns 0 if success */ -static int submit_single_step_set_feature( +static int ehci_submit_single_step_set_feature( struct usb_hcd *hcd, struct urb *urb, int is_setup diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c index 9c2eda0918e1..05fb8d97cf02 100644 --- a/drivers/usb/host/fotg210-hcd.c +++ b/drivers/usb/host/fotg210-hcd.c @@ -850,7 +850,6 @@ static inline void create_debug_files(struct fotg210_hcd *fotg210) struct dentry *root; root = debugfs_create_dir(bus->bus_name, fotg210_debug_root); - fotg210->debug_dir = root; debugfs_create_file("async", S_IRUGO, root, bus, &debug_async_fops); debugfs_create_file("periodic", S_IRUGO, root, bus, @@ -861,7 +860,9 @@ static inline void create_debug_files(struct fotg210_hcd *fotg210) static inline void remove_debug_files(struct fotg210_hcd *fotg210) { - debugfs_remove_recursive(fotg210->debug_dir); + struct usb_bus *bus = &fotg210_to_hcd(fotg210)->self; + + debugfs_remove(debugfs_lookup(bus->bus_name, fotg210_debug_root)); } /* handshake - spin reading hc until handshake completes or fails diff --git a/drivers/usb/host/fotg210.h b/drivers/usb/host/fotg210.h index 6cee40ec65b4..0a91061a0551 100644 --- a/drivers/usb/host/fotg210.h +++ b/drivers/usb/host/fotg210.h @@ -184,9 +184,6 @@ struct fotg210_hcd { /* one per controller */ /* silicon clock */ struct clk *pclk; - - /* debug files */ - struct dentry *debug_dir; }; /* convert between an HCD pointer and the corresponding FOTG210_HCD */ diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 5a783c423d8e..ae882d76612b 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -2392,8 +2392,7 @@ static int dequeue_from_overflow_chain(struct u132 *u132, urb->error_count = 0; usb_hcd_giveback_urb(hcd, urb, 0); return 0; - } else - continue; + } } dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]=%p ring" "[%d] %c%c usb_endp=%d usb_addr=%d size=%d next=%04X last=%04X" @@ -2448,8 +2447,7 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp, urb_slot = &endp->urb_list[ENDP_QUEUE_MASK & queue_scan]; break; - } else - continue; + } } while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) { *urb_slot = endp->urb_list[ENDP_QUEUE_MASK & diff --git a/drivers/usb/host/xhci-dbgtty.c b/drivers/usb/host/xhci-dbgtty.c index ae4e4ab638b5..bef104511352 100644 --- a/drivers/usb/host/xhci-dbgtty.c +++ b/drivers/usb/host/xhci-dbgtty.c @@ -240,11 +240,11 @@ static void dbc_tty_flush_chars(struct tty_struct *tty) spin_unlock_irqrestore(&port->port_lock, flags); } -static int dbc_tty_write_room(struct tty_struct *tty) +static unsigned int dbc_tty_write_room(struct tty_struct *tty) { struct dbc_port *port = tty->driver_data; unsigned long flags; - int room = 0; + unsigned int room; spin_lock_irqsave(&port->port_lock, flags); room = kfifo_avail(&port->write_fifo); @@ -253,11 +253,11 @@ static int dbc_tty_write_room(struct tty_struct *tty) return room; } -static int dbc_tty_chars_in_buffer(struct tty_struct *tty) +static unsigned int dbc_tty_chars_in_buffer(struct tty_struct *tty) { struct dbc_port *port = tty->driver_data; unsigned long flags; - int chars = 0; + unsigned int chars; spin_lock_irqsave(&port->port_lock, flags); chars = kfifo_len(&port->write_fifo); diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index f66815fe8482..0e312066c5c6 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1924,6 +1924,7 @@ no_bw: xhci->hw_ports = NULL; xhci->rh_bw = NULL; xhci->ext_caps = NULL; + xhci->port_caps = NULL; xhci->page_size = 0; xhci->page_shift = 0; @@ -2547,6 +2548,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Wrote ERST address to ir_set 0."); + xhci->isoc_bei_interval = AVOID_BEI_INTERVAL_MAX; + /* * XXX: Might need to set the Interrupter Moderation Register to * something other than the default (~1ms minimum between interrupts). diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c index 8b90da5a6ed1..cffcaf4dfa9f 100644 --- a/drivers/usb/host/xhci-mtk-sch.c +++ b/drivers/usb/host/xhci-mtk-sch.c @@ -470,11 +470,12 @@ static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset) static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset) { - struct mu3h_sch_tt *tt = sch_ep->sch_tt; u32 extra_cs_count; u32 start_ss, last_ss; u32 start_cs, last_cs; - int i; + + if (!sch_ep->sch_tt) + return 0; start_ss = offset % 8; @@ -488,10 +489,6 @@ static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset) if (!(start_ss == 7 || last_ss < 6)) return -ESCH_SS_Y6; - for (i = 0; i < sch_ep->cs_count; i++) - if (test_bit(offset + i, tt->ss_bit_map)) - return -ESCH_SS_OVERLAP; - } else { u32 cs_count = DIV_ROUND_UP(sch_ep->maxpkt, FS_PAYLOAD_MAX); @@ -518,9 +515,6 @@ static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset) if (cs_count > 7) cs_count = 7; /* HW limit */ - if (test_bit(offset, tt->ss_bit_map)) - return -ESCH_SS_OVERLAP; - sch_ep->cs_count = cs_count; /* one for ss, the other for idle */ sch_ep->num_budget_microframes = cs_count + 2; @@ -541,11 +535,9 @@ static void update_sch_tt(struct mu3h_sch_ep_info *sch_ep, bool used) struct mu3h_sch_tt *tt = sch_ep->sch_tt; u32 base, num_esit; int bw_updated; - int bits; int i, j; num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit; - bits = (sch_ep->ep_type == ISOC_OUT_EP) ? sch_ep->cs_count : 1; if (used) bw_updated = sch_ep->bw_cost_per_microframe; @@ -555,13 +547,6 @@ static void update_sch_tt(struct mu3h_sch_ep_info *sch_ep, bool used) for (i = 0; i < num_esit; i++) { base = sch_ep->offset + i * sch_ep->esit; - for (j = 0; j < bits; j++) { - if (used) - set_bit(base + j, tt->ss_bit_map); - else - clear_bit(base + j, tt->ss_bit_map); - } - for (j = 0; j < sch_ep->cs_count; j++) tt->fs_bus_bw[base + j] += bw_updated; } @@ -603,54 +588,47 @@ static u32 get_esit_boundary(struct mu3h_sch_ep_info *sch_ep) static int check_sch_bw(struct mu3h_sch_bw_info *sch_bw, struct mu3h_sch_ep_info *sch_ep) { + const u32 esit_boundary = get_esit_boundary(sch_ep); + const u32 bw_boundary = get_bw_boundary(sch_ep->speed); u32 offset; - u32 min_bw; - u32 min_index; u32 worst_bw; - u32 bw_boundary; - u32 esit_boundary; - u32 min_num_budget; - u32 min_cs_count; + u32 min_bw = ~0; + int min_index = -1; int ret = 0; /* * Search through all possible schedule microframes. * and find a microframe where its worst bandwidth is minimum. */ - min_bw = ~0; - min_index = 0; - min_cs_count = sch_ep->cs_count; - min_num_budget = sch_ep->num_budget_microframes; - esit_boundary = get_esit_boundary(sch_ep); for (offset = 0; offset < sch_ep->esit; offset++) { - if (sch_ep->sch_tt) { - ret = check_sch_tt(sch_ep, offset); - if (ret) - continue; - } + ret = check_sch_tt(sch_ep, offset); + if (ret) + continue; if ((offset + sch_ep->num_budget_microframes) > esit_boundary) break; worst_bw = get_max_bw(sch_bw, sch_ep, offset); + if (worst_bw > bw_boundary) + continue; + if (min_bw > worst_bw) { min_bw = worst_bw; min_index = offset; - min_cs_count = sch_ep->cs_count; - min_num_budget = sch_ep->num_budget_microframes; } + + /* use first-fit for LS/FS */ + if (sch_ep->sch_tt && min_index >= 0) + break; + if (min_bw == 0) break; } - bw_boundary = get_bw_boundary(sch_ep->speed); - /* check bandwidth */ - if (min_bw > bw_boundary) + if (min_index < 0) return ret ? ret : -ESCH_BW_OVERFLOW; sch_ep->offset = min_index; - sch_ep->cs_count = min_cs_count; - sch_ep->num_budget_microframes = min_num_budget; return load_ep_bw(sch_bw, sch_ep, true); } diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index b2058b3bc834..2548976bcf05 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -495,8 +495,6 @@ static int xhci_mtk_probe(struct platform_device *pdev) goto put_usb2_hcd; } mtk->has_ippc = true; - } else { - mtk->has_ippc = false; } device_init_wakeup(dev, true); diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h index cd3a37bb73e6..ace432356c41 100644 --- a/drivers/usb/host/xhci-mtk.h +++ b/drivers/usb/host/xhci-mtk.h @@ -24,12 +24,10 @@ #define XHCI_MTK_MAX_ESIT 64 /** - * @ss_bit_map: used to avoid start split microframes overlay * @fs_bus_bw: array to keep track of bandwidth already used for FS * @ep_list: Endpoints using this TT */ struct mu3h_sch_tt { - DECLARE_BITMAP(ss_bit_map, XHCI_MTK_MAX_ESIT); u32 fs_bus_bw[XHCI_MTK_MAX_ESIT]; struct list_head ep_list; }; @@ -138,17 +136,17 @@ struct xhci_hcd_mtk { struct mu3h_sch_bw_info *sch_array; struct list_head bw_ep_chk_list; struct mu3c_ippc_regs __iomem *ippc_regs; - bool has_ippc; int num_u2_ports; int num_u3_ports; int u3p_dis_msk; struct regulator *vusb33; struct regulator *vbus; struct clk_bulk_data clks[BULK_CLKS_NUM]; - bool lpm_support; - bool u2_lpm_disable; + unsigned int has_ippc:1; + unsigned int lpm_support:1; + unsigned int u2_lpm_disable:1; /* usb remote wakeup */ - bool uwk_en; + unsigned int uwk_en:1; struct regmap *uwk; u32 uwk_reg_base; u32 uwk_vers; diff --git a/drivers/usb/host/xhci-pci-renesas.c b/drivers/usb/host/xhci-pci-renesas.c index f97ac9f52bf4..1da647961c25 100644 --- a/drivers/usb/host/xhci-pci-renesas.c +++ b/drivers/usb/host/xhci-pci-renesas.c @@ -197,7 +197,7 @@ static int renesas_check_rom_state(struct pci_dev *pdev) if (err) return pcibios_err_to_errno(err); - if (rom_state & BIT(15)) { + if (rom_state & RENESAS_ROM_STATUS_ROM_EXISTS) { /* ROM exists */ dev_dbg(&pdev->dev, "ROM exists\n"); @@ -207,7 +207,8 @@ static int renesas_check_rom_state(struct pci_dev *pdev) return 0; case RENESAS_ROM_STATUS_NO_RESULT: /* No result yet */ - return 0; + dev_dbg(&pdev->dev, "Unknown ROM status ...\n"); + break; case RENESAS_ROM_STATUS_ERROR: /* Error State */ default: /* All other states are marked as "Reserved states" */ @@ -224,13 +225,12 @@ static int renesas_fw_check_running(struct pci_dev *pdev) u8 fw_state; int err; - /* Check if device has ROM and loaded, if so skip everything */ - err = renesas_check_rom(pdev); - if (err) { /* we have rom */ - err = renesas_check_rom_state(pdev); - if (!err) - return err; - } + /* + * Only if device has ROM and loaded FW we can skip loading and + * return success. Otherwise (even unknown state), attempt to load FW. + */ + if (renesas_check_rom(pdev) && !renesas_check_rom_state(pdev)) + return 0; /* * Test if the device is actually needing the firmware. As most diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 6acd2329e08d..8fea44bbc266 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3076,6 +3076,11 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) if (event_loop++ < TRBS_PER_SEGMENT / 2) continue; xhci_update_erst_dequeue(xhci, event_ring_deq); + + /* ring is half-full, force isoc trbs to interrupt more often */ + if (xhci->isoc_bei_interval > AVOID_BEI_INTERVAL_MIN) + xhci->isoc_bei_interval = xhci->isoc_bei_interval / 2; + event_loop = 0; } @@ -3956,7 +3961,7 @@ static bool trb_block_event_intr(struct xhci_hcd *xhci, int num_tds, int i) * generate an event at least every 8th TD to clear the event ring */ if (i && xhci->quirks & XHCI_AVOID_BEI) - return !!(i % 8); + return !!(i % xhci->isoc_bei_interval); return true; } diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c index c7387677a26a..575fa89a783f 100644 --- a/drivers/usb/host/xhci-tegra.c +++ b/drivers/usb/host/xhci-tegra.c @@ -2,7 +2,7 @@ /* * NVIDIA Tegra xHCI host controller driver * - * Copyright (C) 2014 NVIDIA Corporation + * Copyright (c) 2014-2020, NVIDIA CORPORATION. All rights reserved. * Copyright (C) 2014 Google, Inc. */ @@ -15,9 +15,11 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of_device.h> +#include <linux/of_irq.h> #include <linux/phy/phy.h> #include <linux/phy/tegra/xusb.h> #include <linux/platform_device.h> +#include <linux/usb/ch9.h> #include <linux/pm.h> #include <linux/pm_domain.h> #include <linux/pm_runtime.h> @@ -224,6 +226,7 @@ struct tegra_xusb { int xhci_irq; int mbox_irq; + int padctl_irq; void __iomem *ipfs_base; void __iomem *fpci_base; @@ -249,8 +252,7 @@ struct tegra_xusb { struct device *genpd_dev_host; struct device *genpd_dev_ss; - struct device_link *genpd_dl_host; - struct device_link *genpd_dl_ss; + bool use_genpd; struct phy **phys; unsigned int num_phys; @@ -270,6 +272,7 @@ struct tegra_xusb { dma_addr_t phys; } fw; + bool suspended; struct tegra_xusb_context context; }; @@ -666,6 +669,9 @@ static irqreturn_t tegra_xusb_mbox_thread(int irq, void *data) mutex_lock(&tegra->lock); + if (pm_runtime_suspended(tegra->dev) || tegra->suspended) + goto out; + value = fpci_readl(tegra, tegra->soc->mbox.data_out); tegra_xusb_mbox_unpack(&msg, value); @@ -679,6 +685,7 @@ static irqreturn_t tegra_xusb_mbox_thread(int irq, void *data) tegra_xusb_mbox_handle(tegra, &msg); +out: mutex_unlock(&tegra->lock); return IRQ_HANDLED; } @@ -819,40 +826,6 @@ static void tegra_xusb_phy_disable(struct tegra_xusb *tegra) } } -static int tegra_xusb_runtime_suspend(struct device *dev) -{ - struct tegra_xusb *tegra = dev_get_drvdata(dev); - - regulator_bulk_disable(tegra->soc->num_supplies, tegra->supplies); - tegra_xusb_clk_disable(tegra); - - return 0; -} - -static int tegra_xusb_runtime_resume(struct device *dev) -{ - struct tegra_xusb *tegra = dev_get_drvdata(dev); - int err; - - err = tegra_xusb_clk_enable(tegra); - if (err) { - dev_err(dev, "failed to enable clocks: %d\n", err); - return err; - } - - err = regulator_bulk_enable(tegra->soc->num_supplies, tegra->supplies); - if (err) { - dev_err(dev, "failed to enable regulators: %d\n", err); - goto disable_clk; - } - - return 0; - -disable_clk: - tegra_xusb_clk_disable(tegra); - return err; -} - #ifdef CONFIG_PM_SLEEP static int tegra_xusb_init_context(struct tegra_xusb *tegra) { @@ -1022,10 +995,9 @@ static int tegra_xusb_load_firmware(struct tegra_xusb *tegra) static void tegra_xusb_powerdomain_remove(struct device *dev, struct tegra_xusb *tegra) { - if (tegra->genpd_dl_ss) - device_link_del(tegra->genpd_dl_ss); - if (tegra->genpd_dl_host) - device_link_del(tegra->genpd_dl_host); + if (!tegra->use_genpd) + return; + if (!IS_ERR_OR_NULL(tegra->genpd_dev_ss)) dev_pm_domain_detach(tegra->genpd_dev_ss, true); if (!IS_ERR_OR_NULL(tegra->genpd_dev_host)) @@ -1051,20 +1023,84 @@ static int tegra_xusb_powerdomain_init(struct device *dev, return err; } - tegra->genpd_dl_host = device_link_add(dev, tegra->genpd_dev_host, - DL_FLAG_PM_RUNTIME | - DL_FLAG_STATELESS); - if (!tegra->genpd_dl_host) { - dev_err(dev, "adding host device link failed!\n"); - return -ENODEV; + tegra->use_genpd = true; + + return 0; +} + +static int tegra_xusb_unpowergate_partitions(struct tegra_xusb *tegra) +{ + struct device *dev = tegra->dev; + int rc; + + if (tegra->use_genpd) { + rc = pm_runtime_get_sync(tegra->genpd_dev_ss); + if (rc < 0) { + dev_err(dev, "failed to enable XUSB SS partition\n"); + return rc; + } + + rc = pm_runtime_get_sync(tegra->genpd_dev_host); + if (rc < 0) { + dev_err(dev, "failed to enable XUSB Host partition\n"); + pm_runtime_put_sync(tegra->genpd_dev_ss); + return rc; + } + } else { + rc = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_XUSBA, + tegra->ss_clk, + tegra->ss_rst); + if (rc < 0) { + dev_err(dev, "failed to enable XUSB SS partition\n"); + return rc; + } + + rc = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_XUSBC, + tegra->host_clk, + tegra->host_rst); + if (rc < 0) { + dev_err(dev, "failed to enable XUSB Host partition\n"); + tegra_powergate_power_off(TEGRA_POWERGATE_XUSBA); + return rc; + } } - tegra->genpd_dl_ss = device_link_add(dev, tegra->genpd_dev_ss, - DL_FLAG_PM_RUNTIME | - DL_FLAG_STATELESS); - if (!tegra->genpd_dl_ss) { - dev_err(dev, "adding superspeed device link failed!\n"); - return -ENODEV; + return 0; +} + +static int tegra_xusb_powergate_partitions(struct tegra_xusb *tegra) +{ + struct device *dev = tegra->dev; + int rc; + + if (tegra->use_genpd) { + rc = pm_runtime_put_sync(tegra->genpd_dev_host); + if (rc < 0) { + dev_err(dev, "failed to disable XUSB Host partition\n"); + return rc; + } + + rc = pm_runtime_put_sync(tegra->genpd_dev_ss); + if (rc < 0) { + dev_err(dev, "failed to disable XUSB SS partition\n"); + pm_runtime_get_sync(tegra->genpd_dev_host); + return rc; + } + } else { + rc = tegra_powergate_power_off(TEGRA_POWERGATE_XUSBC); + if (rc < 0) { + dev_err(dev, "failed to disable XUSB Host partition\n"); + return rc; + } + + rc = tegra_powergate_power_off(TEGRA_POWERGATE_XUSBA); + if (rc < 0) { + dev_err(dev, "failed to disable XUSB SS partition\n"); + tegra_powergate_sequence_power_up(TEGRA_POWERGATE_XUSBC, + tegra->host_clk, + tegra->host_rst); + return rc; + } } return 0; @@ -1086,6 +1122,24 @@ static int __tegra_xusb_enable_firmware_messages(struct tegra_xusb *tegra) return err; } +static irqreturn_t tegra_xusb_padctl_irq(int irq, void *data) +{ + struct tegra_xusb *tegra = data; + + mutex_lock(&tegra->lock); + + if (tegra->suspended) { + mutex_unlock(&tegra->lock); + return IRQ_HANDLED; + } + + mutex_unlock(&tegra->lock); + + pm_runtime_resume(tegra->dev); + + return IRQ_HANDLED; +} + static int tegra_xusb_enable_firmware_messages(struct tegra_xusb *tegra) { int err; @@ -1209,6 +1263,52 @@ static void tegra_xhci_id_work(struct work_struct *work) } } +#if IS_ENABLED(CONFIG_PM) || IS_ENABLED(CONFIG_PM_SLEEP) +static bool is_usb2_otg_phy(struct tegra_xusb *tegra, unsigned int index) +{ + return (tegra->usbphy[index] != NULL); +} + +static bool is_usb3_otg_phy(struct tegra_xusb *tegra, unsigned int index) +{ + struct tegra_xusb_padctl *padctl = tegra->padctl; + unsigned int i; + int port; + + for (i = 0; i < tegra->num_usb_phys; i++) { + if (is_usb2_otg_phy(tegra, i)) { + port = tegra_xusb_padctl_get_usb3_companion(padctl, i); + if ((port >= 0) && (index == (unsigned int)port)) + return true; + } + } + + return false; +} + +static bool is_host_mode_phy(struct tegra_xusb *tegra, unsigned int phy_type, unsigned int index) +{ + if (strcmp(tegra->soc->phy_types[phy_type].name, "hsic") == 0) + return true; + + if (strcmp(tegra->soc->phy_types[phy_type].name, "usb2") == 0) { + if (is_usb2_otg_phy(tegra, index)) + return ((index == tegra->otg_usb2_port) && tegra->host_mode); + else + return true; + } + + if (strcmp(tegra->soc->phy_types[phy_type].name, "usb3") == 0) { + if (is_usb3_otg_phy(tegra, index)) + return ((index == tegra->otg_usb3_port) && tegra->host_mode); + else + return true; + } + + return false; +} +#endif + static int tegra_xusb_get_usb2_port(struct tegra_xusb *tegra, struct usb_phy *usbphy) { @@ -1301,6 +1401,7 @@ static void tegra_xusb_deinit_usb_phy(struct tegra_xusb *tegra) static int tegra_xusb_probe(struct platform_device *pdev) { struct tegra_xusb *tegra; + struct device_node *np; struct resource *regs; struct xhci_hcd *xhci; unsigned int i, j, k; @@ -1321,8 +1422,7 @@ static int tegra_xusb_probe(struct platform_device *pdev) if (err < 0) return err; - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - tegra->regs = devm_ioremap_resource(&pdev->dev, regs); + tegra->regs = devm_platform_get_and_ioremap_resource(pdev, 0, ®s); if (IS_ERR(tegra->regs)) return PTR_ERR(tegra->regs); @@ -1348,6 +1448,18 @@ static int tegra_xusb_probe(struct platform_device *pdev) if (IS_ERR(tegra->padctl)) return PTR_ERR(tegra->padctl); + np = of_parse_phandle(pdev->dev.of_node, "nvidia,xusb-padctl", 0); + if (!np) { + err = -ENODEV; + goto put_padctl; + } + + tegra->padctl_irq = of_irq_get(np, 0); + if (tegra->padctl_irq <= 0) { + err = (tegra->padctl_irq == 0) ? -ENODEV : tegra->padctl_irq; + goto put_padctl; + } + tegra->host_clk = devm_clk_get(&pdev->dev, "xusb_host"); if (IS_ERR(tegra->host_clk)) { err = PTR_ERR(tegra->host_clk); @@ -1428,25 +1540,6 @@ static int tegra_xusb_probe(struct platform_device *pdev) err); goto put_padctl; } - - err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_XUSBA, - tegra->ss_clk, - tegra->ss_rst); - if (err) { - dev_err(&pdev->dev, - "failed to enable XUSBA domain: %d\n", err); - goto put_padctl; - } - - err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_XUSBC, - tegra->host_clk, - tegra->host_rst); - if (err) { - tegra_powergate_power_off(TEGRA_POWERGATE_XUSBA); - dev_err(&pdev->dev, - "failed to enable XUSBC domain: %d\n", err); - goto put_padctl; - } } else { err = tegra_xusb_powerdomain_init(&pdev->dev, tegra); if (err) @@ -1511,6 +1604,7 @@ static int tegra_xusb_probe(struct platform_device *pdev) goto put_powerdomains; } + tegra->hcd->skip_phy_initialization = 1; tegra->hcd->regs = tegra->regs; tegra->hcd->rsrc_start = regs->start; tegra->hcd->rsrc_len = resource_size(regs); @@ -1521,10 +1615,22 @@ static int tegra_xusb_probe(struct platform_device *pdev) */ platform_set_drvdata(pdev, tegra); + err = tegra_xusb_clk_enable(tegra); + if (err) { + dev_err(tegra->dev, "failed to enable clocks: %d\n", err); + goto put_hcd; + } + + err = regulator_bulk_enable(tegra->soc->num_supplies, tegra->supplies); + if (err) { + dev_err(tegra->dev, "failed to enable regulators: %d\n", err); + goto disable_clk; + } + err = tegra_xusb_phy_enable(tegra); if (err < 0) { dev_err(&pdev->dev, "failed to enable PHYs: %d\n", err); - goto put_hcd; + goto disable_regulator; } /* @@ -1543,30 +1649,22 @@ static int tegra_xusb_probe(struct platform_device *pdev) goto disable_phy; } - pm_runtime_enable(&pdev->dev); - - if (!pm_runtime_enabled(&pdev->dev)) - err = tegra_xusb_runtime_resume(&pdev->dev); - else - err = pm_runtime_get_sync(&pdev->dev); - - if (err < 0) { - dev_err(&pdev->dev, "failed to enable device: %d\n", err); + err = tegra_xusb_unpowergate_partitions(tegra); + if (err) goto free_firmware; - } tegra_xusb_config(tegra); err = tegra_xusb_load_firmware(tegra); if (err < 0) { dev_err(&pdev->dev, "failed to load firmware: %d\n", err); - goto put_rpm; + goto powergate; } err = usb_add_hcd(tegra->hcd, tegra->xhci_irq, IRQF_SHARED); if (err < 0) { dev_err(&pdev->dev, "failed to add USB HCD: %d\n", err); - goto put_rpm; + goto powergate; } device_wakeup_enable(tegra->hcd->self.controller); @@ -1589,12 +1687,6 @@ static int tegra_xusb_probe(struct platform_device *pdev) goto put_usb3; } - err = tegra_xusb_enable_firmware_messages(tegra); - if (err < 0) { - dev_err(&pdev->dev, "failed to enable messages: %d\n", err); - goto remove_usb3; - } - err = devm_request_threaded_irq(&pdev->dev, tegra->mbox_irq, tegra_xusb_mbox_irq, tegra_xusb_mbox_thread, 0, @@ -1604,12 +1696,36 @@ static int tegra_xusb_probe(struct platform_device *pdev) goto remove_usb3; } + err = devm_request_threaded_irq(&pdev->dev, tegra->padctl_irq, NULL, tegra_xusb_padctl_irq, + IRQF_ONESHOT, dev_name(&pdev->dev), tegra); + if (err < 0) { + dev_err(&pdev->dev, "failed to request padctl IRQ: %d\n", err); + goto remove_usb3; + } + + err = tegra_xusb_enable_firmware_messages(tegra); + if (err < 0) { + dev_err(&pdev->dev, "failed to enable messages: %d\n", err); + goto remove_usb3; + } + err = tegra_xusb_init_usb_phy(tegra); if (err < 0) { dev_err(&pdev->dev, "failed to init USB PHY: %d\n", err); goto remove_usb3; } + /* Enable wake for both USB 2.0 and USB 3.0 roothubs */ + device_init_wakeup(&tegra->hcd->self.root_hub->dev, true); + device_init_wakeup(&xhci->shared_hcd->self.root_hub->dev, true); + device_init_wakeup(tegra->dev, true); + + pm_runtime_use_autosuspend(tegra->dev); + pm_runtime_set_autosuspend_delay(tegra->dev, 2000); + pm_runtime_mark_last_busy(tegra->dev); + pm_runtime_set_active(tegra->dev); + pm_runtime_enable(tegra->dev); + return 0; remove_usb3: @@ -1618,25 +1734,23 @@ put_usb3: usb_put_hcd(xhci->shared_hcd); remove_usb2: usb_remove_hcd(tegra->hcd); -put_rpm: - if (!pm_runtime_status_suspended(&pdev->dev)) - tegra_xusb_runtime_suspend(&pdev->dev); -put_hcd: - usb_put_hcd(tegra->hcd); +powergate: + tegra_xusb_powergate_partitions(tegra); free_firmware: dma_free_coherent(&pdev->dev, tegra->fw.size, tegra->fw.virt, tegra->fw.phys); disable_phy: tegra_xusb_phy_disable(tegra); - pm_runtime_disable(&pdev->dev); +disable_regulator: + regulator_bulk_disable(tegra->soc->num_supplies, tegra->supplies); +disable_clk: + tegra_xusb_clk_disable(tegra); +put_hcd: + usb_put_hcd(tegra->hcd); put_powerdomains: - if (!of_property_read_bool(pdev->dev.of_node, "power-domains")) { - tegra_powergate_power_off(TEGRA_POWERGATE_XUSBC); - tegra_powergate_power_off(TEGRA_POWERGATE_XUSBA); - } else { - tegra_xusb_powerdomain_remove(&pdev->dev, tegra); - } + tegra_xusb_powerdomain_remove(&pdev->dev, tegra); put_padctl: + of_node_put(np); tegra_xusb_padctl_put(tegra->padctl); return err; } @@ -1648,6 +1762,7 @@ static int tegra_xusb_remove(struct platform_device *pdev) tegra_xusb_deinit_usb_phy(tegra); + pm_runtime_get_sync(&pdev->dev); usb_remove_hcd(xhci->shared_hcd); usb_put_hcd(xhci->shared_hcd); xhci->shared_hcd = NULL; @@ -1657,24 +1772,22 @@ static int tegra_xusb_remove(struct platform_device *pdev) dma_free_coherent(&pdev->dev, tegra->fw.size, tegra->fw.virt, tegra->fw.phys); - pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); + pm_runtime_put(&pdev->dev); - if (!of_property_read_bool(pdev->dev.of_node, "power-domains")) { - tegra_powergate_power_off(TEGRA_POWERGATE_XUSBC); - tegra_powergate_power_off(TEGRA_POWERGATE_XUSBA); - } else { - tegra_xusb_powerdomain_remove(&pdev->dev, tegra); - } + tegra_xusb_powergate_partitions(tegra); - tegra_xusb_phy_disable(tegra); + tegra_xusb_powerdomain_remove(&pdev->dev, tegra); + tegra_xusb_phy_disable(tegra); + tegra_xusb_clk_disable(tegra); + regulator_bulk_disable(tegra->soc->num_supplies, tegra->supplies); tegra_xusb_padctl_put(tegra->padctl); return 0; } -#ifdef CONFIG_PM_SLEEP +#if IS_ENABLED(CONFIG_PM) || IS_ENABLED(CONFIG_PM_SLEEP) static bool xhci_hub_ports_suspended(struct xhci_hub *hub) { struct device *dev = hub->hcd->self.controller; @@ -1700,9 +1813,17 @@ static bool xhci_hub_ports_suspended(struct xhci_hub *hub) static int tegra_xusb_check_ports(struct tegra_xusb *tegra) { struct xhci_hcd *xhci = hcd_to_xhci(tegra->hcd); + struct xhci_bus_state *bus_state = &xhci->usb2_rhub.bus_state; unsigned long flags; int err = 0; + if (bus_state->bus_suspended) { + /* xusb_hub_suspend() has just directed one or more USB2 port(s) + * to U3 state, it takes 3ms to enter U3. + */ + usleep_range(3000, 4000); + } + spin_lock_irqsave(&xhci->lock, flags); if (!xhci_hub_ports_suspended(&xhci->usb2_rhub) || @@ -1748,45 +1869,186 @@ static void tegra_xusb_restore_context(struct tegra_xusb *tegra) } } -static int tegra_xusb_enter_elpg(struct tegra_xusb *tegra, bool wakeup) +static enum usb_device_speed tegra_xhci_portsc_to_speed(struct tegra_xusb *tegra, u32 portsc) { + if (DEV_LOWSPEED(portsc)) + return USB_SPEED_LOW; + + if (DEV_HIGHSPEED(portsc)) + return USB_SPEED_HIGH; + + if (DEV_FULLSPEED(portsc)) + return USB_SPEED_FULL; + + if (DEV_SUPERSPEED_ANY(portsc)) + return USB_SPEED_SUPER; + + return USB_SPEED_UNKNOWN; +} + +static void tegra_xhci_enable_phy_sleepwalk_wake(struct tegra_xusb *tegra) +{ + struct tegra_xusb_padctl *padctl = tegra->padctl; struct xhci_hcd *xhci = hcd_to_xhci(tegra->hcd); + enum usb_device_speed speed; + struct phy *phy; + unsigned int index, offset; + unsigned int i, j, k; + struct xhci_hub *rhub; + u32 portsc; + + for (i = 0, k = 0; i < tegra->soc->num_types; i++) { + if (strcmp(tegra->soc->phy_types[i].name, "usb3") == 0) + rhub = &xhci->usb3_rhub; + else + rhub = &xhci->usb2_rhub; + + if (strcmp(tegra->soc->phy_types[i].name, "hsic") == 0) + offset = tegra->soc->ports.usb2.count; + else + offset = 0; + + for (j = 0; j < tegra->soc->phy_types[i].num; j++) { + phy = tegra->phys[k++]; + + if (!phy) + continue; + + index = j + offset; + + if (index >= rhub->num_ports) + continue; + + if (!is_host_mode_phy(tegra, i, j)) + continue; + + portsc = readl(rhub->ports[index]->addr); + speed = tegra_xhci_portsc_to_speed(tegra, portsc); + tegra_xusb_padctl_enable_phy_sleepwalk(padctl, phy, speed); + tegra_xusb_padctl_enable_phy_wake(padctl, phy); + } + } +} + +static void tegra_xhci_disable_phy_wake(struct tegra_xusb *tegra) +{ + struct tegra_xusb_padctl *padctl = tegra->padctl; + unsigned int i; + + for (i = 0; i < tegra->num_phys; i++) { + if (!tegra->phys[i]) + continue; + + tegra_xusb_padctl_disable_phy_wake(padctl, tegra->phys[i]); + } +} + +static void tegra_xhci_disable_phy_sleepwalk(struct tegra_xusb *tegra) +{ + struct tegra_xusb_padctl *padctl = tegra->padctl; + unsigned int i; + + for (i = 0; i < tegra->num_phys; i++) { + if (!tegra->phys[i]) + continue; + + tegra_xusb_padctl_disable_phy_sleepwalk(padctl, tegra->phys[i]); + } +} + +static int tegra_xusb_enter_elpg(struct tegra_xusb *tegra, bool runtime) +{ + struct xhci_hcd *xhci = hcd_to_xhci(tegra->hcd); + struct device *dev = tegra->dev; + bool wakeup = runtime ? true : device_may_wakeup(dev); + unsigned int i; int err; + u32 usbcmd; + + dev_dbg(dev, "entering ELPG\n"); + + usbcmd = readl(&xhci->op_regs->command); + usbcmd &= ~CMD_EIE; + writel(usbcmd, &xhci->op_regs->command); err = tegra_xusb_check_ports(tegra); if (err < 0) { dev_err(tegra->dev, "not all ports suspended: %d\n", err); - return err; + goto out; } err = xhci_suspend(xhci, wakeup); if (err < 0) { dev_err(tegra->dev, "failed to suspend XHCI: %d\n", err); - return err; + goto out; } tegra_xusb_save_context(tegra); - tegra_xusb_phy_disable(tegra); + + if (wakeup) + tegra_xhci_enable_phy_sleepwalk_wake(tegra); + + tegra_xusb_powergate_partitions(tegra); + + for (i = 0; i < tegra->num_phys; i++) { + if (!tegra->phys[i]) + continue; + + phy_power_off(tegra->phys[i]); + if (!wakeup) + phy_exit(tegra->phys[i]); + } + tegra_xusb_clk_disable(tegra); - return 0; +out: + if (!err) + dev_dbg(tegra->dev, "entering ELPG done\n"); + else { + usbcmd = readl(&xhci->op_regs->command); + usbcmd |= CMD_EIE; + writel(usbcmd, &xhci->op_regs->command); + + dev_dbg(tegra->dev, "entering ELPG failed\n"); + pm_runtime_mark_last_busy(tegra->dev); + } + + return err; } -static int tegra_xusb_exit_elpg(struct tegra_xusb *tegra, bool wakeup) +static int tegra_xusb_exit_elpg(struct tegra_xusb *tegra, bool runtime) { struct xhci_hcd *xhci = hcd_to_xhci(tegra->hcd); + struct device *dev = tegra->dev; + bool wakeup = runtime ? true : device_may_wakeup(dev); + unsigned int i; + u32 usbcmd; int err; + dev_dbg(dev, "exiting ELPG\n"); + pm_runtime_mark_last_busy(tegra->dev); + err = tegra_xusb_clk_enable(tegra); if (err < 0) { dev_err(tegra->dev, "failed to enable clocks: %d\n", err); - return err; + goto out; } - err = tegra_xusb_phy_enable(tegra); - if (err < 0) { - dev_err(tegra->dev, "failed to enable PHYs: %d\n", err); - goto disable_clk; + err = tegra_xusb_unpowergate_partitions(tegra); + if (err) + goto disable_clks; + + if (wakeup) + tegra_xhci_disable_phy_wake(tegra); + + for (i = 0; i < tegra->num_phys; i++) { + if (!tegra->phys[i]) + continue; + + if (!wakeup) + phy_init(tegra->phys[i]); + + phy_power_on(tegra->phys[i]); } tegra_xusb_config(tegra); @@ -1804,31 +2066,79 @@ static int tegra_xusb_exit_elpg(struct tegra_xusb *tegra, bool wakeup) goto disable_phy; } - err = xhci_resume(xhci, true); + if (wakeup) + tegra_xhci_disable_phy_sleepwalk(tegra); + + err = xhci_resume(xhci, 0); if (err < 0) { dev_err(tegra->dev, "failed to resume XHCI: %d\n", err); goto disable_phy; } - return 0; + usbcmd = readl(&xhci->op_regs->command); + usbcmd |= CMD_EIE; + writel(usbcmd, &xhci->op_regs->command); + + goto out; disable_phy: - tegra_xusb_phy_disable(tegra); -disable_clk: + for (i = 0; i < tegra->num_phys; i++) { + if (!tegra->phys[i]) + continue; + + phy_power_off(tegra->phys[i]); + if (!wakeup) + phy_exit(tegra->phys[i]); + } + tegra_xusb_powergate_partitions(tegra); +disable_clks: tegra_xusb_clk_disable(tegra); +out: + if (!err) + dev_dbg(dev, "exiting ELPG done\n"); + else + dev_dbg(dev, "exiting ELPG failed\n"); + return err; } static int tegra_xusb_suspend(struct device *dev) { struct tegra_xusb *tegra = dev_get_drvdata(dev); - bool wakeup = device_may_wakeup(dev); int err; synchronize_irq(tegra->mbox_irq); mutex_lock(&tegra->lock); - err = tegra_xusb_enter_elpg(tegra, wakeup); + + if (pm_runtime_suspended(dev)) { + err = tegra_xusb_exit_elpg(tegra, true); + if (err < 0) + goto out; + } + + err = tegra_xusb_enter_elpg(tegra, false); + if (err < 0) { + if (pm_runtime_suspended(dev)) { + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + } + + goto out; + } + +out: + if (!err) { + tegra->suspended = true; + pm_runtime_disable(dev); + + if (device_may_wakeup(dev)) { + if (enable_irq_wake(tegra->padctl_irq)) + dev_err(dev, "failed to enable padctl wakes\n"); + } + } + mutex_unlock(&tegra->lock); return err; @@ -1837,11 +2147,56 @@ static int tegra_xusb_suspend(struct device *dev) static int tegra_xusb_resume(struct device *dev) { struct tegra_xusb *tegra = dev_get_drvdata(dev); - bool wakeup = device_may_wakeup(dev); int err; mutex_lock(&tegra->lock); - err = tegra_xusb_exit_elpg(tegra, wakeup); + + if (!tegra->suspended) { + mutex_unlock(&tegra->lock); + return 0; + } + + err = tegra_xusb_exit_elpg(tegra, false); + if (err < 0) { + mutex_unlock(&tegra->lock); + return err; + } + + if (device_may_wakeup(dev)) { + if (disable_irq_wake(tegra->padctl_irq)) + dev_err(dev, "failed to disable padctl wakes\n"); + } + tegra->suspended = false; + mutex_unlock(&tegra->lock); + + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + return 0; +} +#endif + +#ifdef CONFIG_PM +static int tegra_xusb_runtime_suspend(struct device *dev) +{ + struct tegra_xusb *tegra = dev_get_drvdata(dev); + int ret; + + synchronize_irq(tegra->mbox_irq); + mutex_lock(&tegra->lock); + ret = tegra_xusb_enter_elpg(tegra, true); + mutex_unlock(&tegra->lock); + + return ret; +} + +static int tegra_xusb_runtime_resume(struct device *dev) +{ + struct tegra_xusb *tegra = dev_get_drvdata(dev); + int err; + + mutex_lock(&tegra->lock); + err = tegra_xusb_exit_elpg(tegra, true); mutex_unlock(&tegra->lock); return err; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 27283654ca08..3618070eba78 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1361,12 +1361,17 @@ static void xhci_unmap_temp_buf(struct usb_hcd *hcd, struct urb *urb) urb->transfer_buffer_length, dir); - if (usb_urb_dir_in(urb)) + if (usb_urb_dir_in(urb)) { len = sg_pcopy_from_buffer(urb->sg, urb->num_sgs, urb->transfer_buffer, buf_len, 0); - + if (len != buf_len) { + xhci_dbg(hcd_to_xhci(hcd), + "Copy from tmp buf to urb sg list failed\n"); + urb->actual_length = len; + } + } urb->transfer_flags &= ~URB_DMA_MAP_SINGLE; kfree(urb->transfer_buffer); urb->transfer_buffer = NULL; @@ -4840,7 +4845,6 @@ static int xhci_update_timeout_for_interface(struct xhci_hcd *xhci, if (xhci_update_timeout_for_endpoint(xhci, udev, &alt->endpoint[j].desc, state, timeout)) return -E2BIG; - continue; } return 0; } diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index e417f5ce13d1..3c7d281672ae 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1526,6 +1526,12 @@ static inline const char *xhci_trb_type_string(u8 type) #define TRB_BUFF_LEN_UP_TO_BOUNDARY(addr) (TRB_MAX_BUFF_SIZE - \ (addr & (TRB_MAX_BUFF_SIZE - 1))) #define MAX_SOFT_RETRY 3 +/* + * Limits of consecutive isoc trbs that can Block Event Interrupt (BEI) if + * XHCI_AVOID_BEI quirk is in use. + */ +#define AVOID_BEI_INTERVAL_MIN 8 +#define AVOID_BEI_INTERVAL_MAX 32 struct xhci_segment { union xhci_trb *trbs; @@ -1663,10 +1669,6 @@ struct urb_priv { * meaning 64 ring segments. * Initial allocated size of the ERST, in number of entries */ #define ERST_NUM_SEGS 1 -/* Initial allocated size of the ERST, in number of entries */ -#define ERST_SIZE 64 -/* Initial number of event segment rings allocated */ -#define ERST_ENTRIES 1 /* Poll every 60 seconds */ #define POLL_TIMEOUT 60 /* Stop endpoint command timeout (secs) for URB cancellation watchdog timer */ @@ -1772,6 +1774,7 @@ struct xhci_hcd { u8 isoc_threshold; /* imod_interval in ns (I * 250ns) */ u32 imod_interval; + u32 isoc_bei_interval; int event_ring_max; /* 4KB min, 128MB max */ int page_size; diff --git a/drivers/usb/isp1760/Kconfig b/drivers/usb/isp1760/Kconfig index b1022cc490a2..2ed2b73291d1 100644 --- a/drivers/usb/isp1760/Kconfig +++ b/drivers/usb/isp1760/Kconfig @@ -1,10 +1,11 @@ # SPDX-License-Identifier: GPL-2.0 config USB_ISP1760 - tristate "NXP ISP 1760/1761 support" + tristate "NXP ISP 1760/1761/1763 support" depends on USB || USB_GADGET + select REGMAP_MMIO help - Say Y or M here if your system as an ISP1760 USB host controller + Say Y or M here if your system as an ISP1760/1763 USB host controller or an ISP1761 USB dual-role controller. This driver does not support isochronous transfers or OTG. diff --git a/drivers/usb/isp1760/isp1760-core.c b/drivers/usb/isp1760/isp1760-core.c index fdeb4cf97cc5..ff07e2890692 100644 --- a/drivers/usb/isp1760/isp1760-core.c +++ b/drivers/usb/isp1760/isp1760-core.c @@ -2,12 +2,14 @@ /* * Driver for the NXP ISP1760 chip * + * Copyright 2021 Linaro, Rui Miguel Silva * Copyright 2014 Laurent Pinchart * Copyright 2007 Sebastian Siewior * * Contacts: * Sebastian Siewior <bigeasy@linutronix.de> * Laurent Pinchart <laurent.pinchart@ideasonboard.com> + * Rui Miguel Silva <rui.silva@linaro.org> */ #include <linux/delay.h> @@ -15,6 +17,7 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/regmap.h> #include <linux/slab.h> #include <linux/usb.h> @@ -23,10 +26,10 @@ #include "isp1760-regs.h" #include "isp1760-udc.h" -static void isp1760_init_core(struct isp1760_device *isp) +static int isp1760_init_core(struct isp1760_device *isp) { - u32 otgctrl; - u32 hwmode; + struct isp1760_hcd *hcd = &isp->hcd; + struct isp1760_udc *udc = &isp->udc; /* Low-level chip reset */ if (isp->rst_gpio) { @@ -39,24 +42,29 @@ static void isp1760_init_core(struct isp1760_device *isp) * Reset the host controller, including the CPU interface * configuration. */ - isp1760_write32(isp->regs, HC_RESET_REG, SW_RESET_RESET_ALL); + isp1760_field_set(hcd->fields, SW_RESET_RESET_ALL); msleep(100); /* Setup HW Mode Control: This assumes a level active-low interrupt */ - hwmode = HW_DATA_BUS_32BIT; + if ((isp->devflags & ISP1760_FLAG_ANALOG_OC) && hcd->is_isp1763) { + dev_err(isp->dev, "isp1763 analog overcurrent not available\n"); + return -EINVAL; + } if (isp->devflags & ISP1760_FLAG_BUS_WIDTH_16) - hwmode &= ~HW_DATA_BUS_32BIT; + isp1760_field_clear(hcd->fields, HW_DATA_BUS_WIDTH); + if (isp->devflags & ISP1760_FLAG_BUS_WIDTH_8) + isp1760_field_set(hcd->fields, HW_DATA_BUS_WIDTH); if (isp->devflags & ISP1760_FLAG_ANALOG_OC) - hwmode |= HW_ANA_DIGI_OC; + isp1760_field_set(hcd->fields, HW_ANA_DIGI_OC); if (isp->devflags & ISP1760_FLAG_DACK_POL_HIGH) - hwmode |= HW_DACK_POL_HIGH; + isp1760_field_set(hcd->fields, HW_DACK_POL_HIGH); if (isp->devflags & ISP1760_FLAG_DREQ_POL_HIGH) - hwmode |= HW_DREQ_POL_HIGH; + isp1760_field_set(hcd->fields, HW_DREQ_POL_HIGH); if (isp->devflags & ISP1760_FLAG_INTR_POL_HIGH) - hwmode |= HW_INTR_HIGH_ACT; + isp1760_field_set(hcd->fields, HW_INTR_HIGH_ACT); if (isp->devflags & ISP1760_FLAG_INTR_EDGE_TRIG) - hwmode |= HW_INTR_EDGE_TRIG; + isp1760_field_set(hcd->fields, HW_INTR_EDGE_TRIG); /* * The ISP1761 has a dedicated DC IRQ line but supports sharing the HC @@ -65,59 +73,425 @@ static void isp1760_init_core(struct isp1760_device *isp) * spurious interrupts during HCD registration. */ if (isp->devflags & ISP1760_FLAG_ISP1761) { - isp1760_write32(isp->regs, DC_MODE, 0); - hwmode |= HW_COMN_IRQ; + isp1760_reg_write(udc->regs, ISP176x_DC_MODE, 0); + isp1760_field_set(hcd->fields, HW_COMN_IRQ); } /* - * We have to set this first in case we're in 16-bit mode. - * Write it twice to ensure correct upper bits if switching - * to 16-bit mode. - */ - isp1760_write32(isp->regs, HC_HW_MODE_CTRL, hwmode); - isp1760_write32(isp->regs, HC_HW_MODE_CTRL, hwmode); - - /* * PORT 1 Control register of the ISP1760 is the OTG control register * on ISP1761. * * TODO: Really support OTG. For now we configure port 1 in device mode - * when OTG is requested. */ - if ((isp->devflags & ISP1760_FLAG_ISP1761) && - (isp->devflags & ISP1760_FLAG_OTG_EN)) - otgctrl = ((HW_DM_PULLDOWN | HW_DP_PULLDOWN) << 16) - | HW_OTG_DISABLE; - else - otgctrl = (HW_SW_SEL_HC_DC << 16) - | (HW_VBUS_DRV | HW_SEL_CP_EXT); - - isp1760_write32(isp->regs, HC_PORT1_CTRL, otgctrl); + if (((isp->devflags & ISP1760_FLAG_ISP1761) || + (isp->devflags & ISP1760_FLAG_ISP1763)) && + (isp->devflags & ISP1760_FLAG_PERIPHERAL_EN)) { + isp1760_field_set(hcd->fields, HW_DM_PULLDOWN); + isp1760_field_set(hcd->fields, HW_DP_PULLDOWN); + isp1760_field_set(hcd->fields, HW_OTG_DISABLE); + } else { + isp1760_field_set(hcd->fields, HW_SW_SEL_HC_DC); + isp1760_field_set(hcd->fields, HW_VBUS_DRV); + isp1760_field_set(hcd->fields, HW_SEL_CP_EXT); + } - dev_info(isp->dev, "bus width: %u, oc: %s\n", + dev_info(isp->dev, "%s bus width: %u, oc: %s\n", + hcd->is_isp1763 ? "isp1763" : "isp1760", + isp->devflags & ISP1760_FLAG_BUS_WIDTH_8 ? 8 : isp->devflags & ISP1760_FLAG_BUS_WIDTH_16 ? 16 : 32, + hcd->is_isp1763 ? "not available" : isp->devflags & ISP1760_FLAG_ANALOG_OC ? "analog" : "digital"); + + return 0; } void isp1760_set_pullup(struct isp1760_device *isp, bool enable) { - isp1760_write32(isp->regs, HW_OTG_CTRL_SET, - enable ? HW_DP_PULLUP : HW_DP_PULLUP << 16); + struct isp1760_udc *udc = &isp->udc; + + if (enable) + isp1760_field_set(udc->fields, HW_DP_PULLUP); + else + isp1760_field_set(udc->fields, HW_DP_PULLUP_CLEAR); } +/* + * ISP1760/61: + * + * 60kb divided in: + * - 32 blocks @ 256 bytes + * - 20 blocks @ 1024 bytes + * - 4 blocks @ 8192 bytes + */ +static const struct isp1760_memory_layout isp176x_memory_conf = { + .blocks[0] = 32, + .blocks_size[0] = 256, + .blocks[1] = 20, + .blocks_size[1] = 1024, + .blocks[2] = 4, + .blocks_size[2] = 8192, + + .slot_num = 32, + .payload_blocks = 32 + 20 + 4, + .payload_area_size = 0xf000, +}; + +/* + * ISP1763: + * + * 20kb divided in: + * - 8 blocks @ 256 bytes + * - 2 blocks @ 1024 bytes + * - 4 blocks @ 4096 bytes + */ +static const struct isp1760_memory_layout isp1763_memory_conf = { + .blocks[0] = 8, + .blocks_size[0] = 256, + .blocks[1] = 2, + .blocks_size[1] = 1024, + .blocks[2] = 4, + .blocks_size[2] = 4096, + + .slot_num = 16, + .payload_blocks = 8 + 2 + 4, + .payload_area_size = 0x5000, +}; + +static const struct regmap_range isp176x_hc_volatile_ranges[] = { + regmap_reg_range(ISP176x_HC_USBCMD, ISP176x_HC_ATL_PTD_LASTPTD), + regmap_reg_range(ISP176x_HC_BUFFER_STATUS, ISP176x_HC_MEMORY), + regmap_reg_range(ISP176x_HC_INTERRUPT, ISP176x_HC_OTG_CTRL_CLEAR), +}; + +static const struct regmap_access_table isp176x_hc_volatile_table = { + .yes_ranges = isp176x_hc_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(isp176x_hc_volatile_ranges), +}; + +static const struct regmap_config isp1760_hc_regmap_conf = { + .name = "isp1760-hc", + .reg_bits = 16, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, + .max_register = ISP176x_HC_OTG_CTRL_CLEAR, + .volatile_table = &isp176x_hc_volatile_table, +}; + +static const struct reg_field isp1760_hc_reg_fields[] = { + [HCS_PPC] = REG_FIELD(ISP176x_HC_HCSPARAMS, 4, 4), + [HCS_N_PORTS] = REG_FIELD(ISP176x_HC_HCSPARAMS, 0, 3), + [HCC_ISOC_CACHE] = REG_FIELD(ISP176x_HC_HCCPARAMS, 7, 7), + [HCC_ISOC_THRES] = REG_FIELD(ISP176x_HC_HCCPARAMS, 4, 6), + [CMD_LRESET] = REG_FIELD(ISP176x_HC_USBCMD, 7, 7), + [CMD_RESET] = REG_FIELD(ISP176x_HC_USBCMD, 1, 1), + [CMD_RUN] = REG_FIELD(ISP176x_HC_USBCMD, 0, 0), + [STS_PCD] = REG_FIELD(ISP176x_HC_USBSTS, 2, 2), + [HC_FRINDEX] = REG_FIELD(ISP176x_HC_FRINDEX, 0, 13), + [FLAG_CF] = REG_FIELD(ISP176x_HC_CONFIGFLAG, 0, 0), + [HC_ISO_PTD_DONEMAP] = REG_FIELD(ISP176x_HC_ISO_PTD_DONEMAP, 0, 31), + [HC_ISO_PTD_SKIPMAP] = REG_FIELD(ISP176x_HC_ISO_PTD_SKIPMAP, 0, 31), + [HC_ISO_PTD_LASTPTD] = REG_FIELD(ISP176x_HC_ISO_PTD_LASTPTD, 0, 31), + [HC_INT_PTD_DONEMAP] = REG_FIELD(ISP176x_HC_INT_PTD_DONEMAP, 0, 31), + [HC_INT_PTD_SKIPMAP] = REG_FIELD(ISP176x_HC_INT_PTD_SKIPMAP, 0, 31), + [HC_INT_PTD_LASTPTD] = REG_FIELD(ISP176x_HC_INT_PTD_LASTPTD, 0, 31), + [HC_ATL_PTD_DONEMAP] = REG_FIELD(ISP176x_HC_ATL_PTD_DONEMAP, 0, 31), + [HC_ATL_PTD_SKIPMAP] = REG_FIELD(ISP176x_HC_ATL_PTD_SKIPMAP, 0, 31), + [HC_ATL_PTD_LASTPTD] = REG_FIELD(ISP176x_HC_ATL_PTD_LASTPTD, 0, 31), + [PORT_OWNER] = REG_FIELD(ISP176x_HC_PORTSC1, 13, 13), + [PORT_POWER] = REG_FIELD(ISP176x_HC_PORTSC1, 12, 12), + [PORT_LSTATUS] = REG_FIELD(ISP176x_HC_PORTSC1, 10, 11), + [PORT_RESET] = REG_FIELD(ISP176x_HC_PORTSC1, 8, 8), + [PORT_SUSPEND] = REG_FIELD(ISP176x_HC_PORTSC1, 7, 7), + [PORT_RESUME] = REG_FIELD(ISP176x_HC_PORTSC1, 6, 6), + [PORT_PE] = REG_FIELD(ISP176x_HC_PORTSC1, 2, 2), + [PORT_CSC] = REG_FIELD(ISP176x_HC_PORTSC1, 1, 1), + [PORT_CONNECT] = REG_FIELD(ISP176x_HC_PORTSC1, 0, 0), + [ALL_ATX_RESET] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 31, 31), + [HW_ANA_DIGI_OC] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 15, 15), + [HW_COMN_IRQ] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 10, 10), + [HW_DATA_BUS_WIDTH] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 8, 8), + [HW_DACK_POL_HIGH] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 6, 6), + [HW_DREQ_POL_HIGH] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 5, 5), + [HW_INTR_HIGH_ACT] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 2, 2), + [HW_INTR_EDGE_TRIG] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 1, 1), + [HW_GLOBAL_INTR_EN] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 0, 0), + [HC_CHIP_REV] = REG_FIELD(ISP176x_HC_CHIP_ID, 16, 31), + [HC_CHIP_ID_HIGH] = REG_FIELD(ISP176x_HC_CHIP_ID, 8, 15), + [HC_CHIP_ID_LOW] = REG_FIELD(ISP176x_HC_CHIP_ID, 0, 7), + [HC_SCRATCH] = REG_FIELD(ISP176x_HC_SCRATCH, 0, 31), + [SW_RESET_RESET_ALL] = REG_FIELD(ISP176x_HC_RESET, 0, 0), + [ISO_BUF_FILL] = REG_FIELD(ISP176x_HC_BUFFER_STATUS, 2, 2), + [INT_BUF_FILL] = REG_FIELD(ISP176x_HC_BUFFER_STATUS, 1, 1), + [ATL_BUF_FILL] = REG_FIELD(ISP176x_HC_BUFFER_STATUS, 0, 0), + [MEM_BANK_SEL] = REG_FIELD(ISP176x_HC_MEMORY, 16, 17), + [MEM_START_ADDR] = REG_FIELD(ISP176x_HC_MEMORY, 0, 15), + [HC_INTERRUPT] = REG_FIELD(ISP176x_HC_INTERRUPT, 0, 9), + [HC_ATL_IRQ_ENABLE] = REG_FIELD(ISP176x_HC_INTERRUPT_ENABLE, 8, 8), + [HC_INT_IRQ_ENABLE] = REG_FIELD(ISP176x_HC_INTERRUPT_ENABLE, 7, 7), + [HC_ISO_IRQ_MASK_OR] = REG_FIELD(ISP176x_HC_ISO_IRQ_MASK_OR, 0, 31), + [HC_INT_IRQ_MASK_OR] = REG_FIELD(ISP176x_HC_INT_IRQ_MASK_OR, 0, 31), + [HC_ATL_IRQ_MASK_OR] = REG_FIELD(ISP176x_HC_ATL_IRQ_MASK_OR, 0, 31), + [HC_ISO_IRQ_MASK_AND] = REG_FIELD(ISP176x_HC_ISO_IRQ_MASK_AND, 0, 31), + [HC_INT_IRQ_MASK_AND] = REG_FIELD(ISP176x_HC_INT_IRQ_MASK_AND, 0, 31), + [HC_ATL_IRQ_MASK_AND] = REG_FIELD(ISP176x_HC_ATL_IRQ_MASK_AND, 0, 31), + [HW_OTG_DISABLE] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 10, 10), + [HW_SW_SEL_HC_DC] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 7, 7), + [HW_VBUS_DRV] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 4, 4), + [HW_SEL_CP_EXT] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 3, 3), + [HW_DM_PULLDOWN] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 2, 2), + [HW_DP_PULLDOWN] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 1, 1), + [HW_DP_PULLUP] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 0, 0), + [HW_OTG_DISABLE_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 10, 10), + [HW_SW_SEL_HC_DC_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 7, 7), + [HW_VBUS_DRV_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 4, 4), + [HW_SEL_CP_EXT_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 3, 3), + [HW_DM_PULLDOWN_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 2, 2), + [HW_DP_PULLDOWN_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 1, 1), + [HW_DP_PULLUP_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 0, 0), +}; + +static const struct reg_field isp1763_hc_reg_fields[] = { + [CMD_LRESET] = REG_FIELD(ISP1763_HC_USBCMD, 7, 7), + [CMD_RESET] = REG_FIELD(ISP1763_HC_USBCMD, 1, 1), + [CMD_RUN] = REG_FIELD(ISP1763_HC_USBCMD, 0, 0), + [STS_PCD] = REG_FIELD(ISP1763_HC_USBSTS, 2, 2), + [HC_FRINDEX] = REG_FIELD(ISP1763_HC_FRINDEX, 0, 13), + [FLAG_CF] = REG_FIELD(ISP1763_HC_CONFIGFLAG, 0, 0), + [HC_ISO_PTD_DONEMAP] = REG_FIELD(ISP1763_HC_ISO_PTD_DONEMAP, 0, 15), + [HC_ISO_PTD_SKIPMAP] = REG_FIELD(ISP1763_HC_ISO_PTD_SKIPMAP, 0, 15), + [HC_ISO_PTD_LASTPTD] = REG_FIELD(ISP1763_HC_ISO_PTD_LASTPTD, 0, 15), + [HC_INT_PTD_DONEMAP] = REG_FIELD(ISP1763_HC_INT_PTD_DONEMAP, 0, 15), + [HC_INT_PTD_SKIPMAP] = REG_FIELD(ISP1763_HC_INT_PTD_SKIPMAP, 0, 15), + [HC_INT_PTD_LASTPTD] = REG_FIELD(ISP1763_HC_INT_PTD_LASTPTD, 0, 15), + [HC_ATL_PTD_DONEMAP] = REG_FIELD(ISP1763_HC_ATL_PTD_DONEMAP, 0, 15), + [HC_ATL_PTD_SKIPMAP] = REG_FIELD(ISP1763_HC_ATL_PTD_SKIPMAP, 0, 15), + [HC_ATL_PTD_LASTPTD] = REG_FIELD(ISP1763_HC_ATL_PTD_LASTPTD, 0, 15), + [PORT_OWNER] = REG_FIELD(ISP1763_HC_PORTSC1, 13, 13), + [PORT_POWER] = REG_FIELD(ISP1763_HC_PORTSC1, 12, 12), + [PORT_LSTATUS] = REG_FIELD(ISP1763_HC_PORTSC1, 10, 11), + [PORT_RESET] = REG_FIELD(ISP1763_HC_PORTSC1, 8, 8), + [PORT_SUSPEND] = REG_FIELD(ISP1763_HC_PORTSC1, 7, 7), + [PORT_RESUME] = REG_FIELD(ISP1763_HC_PORTSC1, 6, 6), + [PORT_PE] = REG_FIELD(ISP1763_HC_PORTSC1, 2, 2), + [PORT_CSC] = REG_FIELD(ISP1763_HC_PORTSC1, 1, 1), + [PORT_CONNECT] = REG_FIELD(ISP1763_HC_PORTSC1, 0, 0), + [HW_DATA_BUS_WIDTH] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 4, 4), + [HW_DACK_POL_HIGH] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 6, 6), + [HW_DREQ_POL_HIGH] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 5, 5), + [HW_INTF_LOCK] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 3, 3), + [HW_INTR_HIGH_ACT] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 2, 2), + [HW_INTR_EDGE_TRIG] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 1, 1), + [HW_GLOBAL_INTR_EN] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 0, 0), + [SW_RESET_RESET_ATX] = REG_FIELD(ISP1763_HC_RESET, 3, 3), + [SW_RESET_RESET_ALL] = REG_FIELD(ISP1763_HC_RESET, 0, 0), + [HC_CHIP_ID_HIGH] = REG_FIELD(ISP1763_HC_CHIP_ID, 0, 15), + [HC_CHIP_ID_LOW] = REG_FIELD(ISP1763_HC_CHIP_REV, 8, 15), + [HC_CHIP_REV] = REG_FIELD(ISP1763_HC_CHIP_REV, 0, 7), + [HC_SCRATCH] = REG_FIELD(ISP1763_HC_SCRATCH, 0, 15), + [ISO_BUF_FILL] = REG_FIELD(ISP1763_HC_BUFFER_STATUS, 2, 2), + [INT_BUF_FILL] = REG_FIELD(ISP1763_HC_BUFFER_STATUS, 1, 1), + [ATL_BUF_FILL] = REG_FIELD(ISP1763_HC_BUFFER_STATUS, 0, 0), + [MEM_START_ADDR] = REG_FIELD(ISP1763_HC_MEMORY, 0, 15), + [HC_DATA] = REG_FIELD(ISP1763_HC_DATA, 0, 15), + [HC_INTERRUPT] = REG_FIELD(ISP1763_HC_INTERRUPT, 0, 10), + [HC_ATL_IRQ_ENABLE] = REG_FIELD(ISP1763_HC_INTERRUPT_ENABLE, 8, 8), + [HC_INT_IRQ_ENABLE] = REG_FIELD(ISP1763_HC_INTERRUPT_ENABLE, 7, 7), + [HC_ISO_IRQ_MASK_OR] = REG_FIELD(ISP1763_HC_ISO_IRQ_MASK_OR, 0, 15), + [HC_INT_IRQ_MASK_OR] = REG_FIELD(ISP1763_HC_INT_IRQ_MASK_OR, 0, 15), + [HC_ATL_IRQ_MASK_OR] = REG_FIELD(ISP1763_HC_ATL_IRQ_MASK_OR, 0, 15), + [HC_ISO_IRQ_MASK_AND] = REG_FIELD(ISP1763_HC_ISO_IRQ_MASK_AND, 0, 15), + [HC_INT_IRQ_MASK_AND] = REG_FIELD(ISP1763_HC_INT_IRQ_MASK_AND, 0, 15), + [HC_ATL_IRQ_MASK_AND] = REG_FIELD(ISP1763_HC_ATL_IRQ_MASK_AND, 0, 15), + [HW_HC_2_DIS] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 15, 15), + [HW_OTG_DISABLE] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 10, 10), + [HW_SW_SEL_HC_DC] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 7, 7), + [HW_VBUS_DRV] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 4, 4), + [HW_SEL_CP_EXT] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 3, 3), + [HW_DM_PULLDOWN] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 2, 2), + [HW_DP_PULLDOWN] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 1, 1), + [HW_DP_PULLUP] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 0, 0), + [HW_HC_2_DIS_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 15, 15), + [HW_OTG_DISABLE_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 10, 10), + [HW_SW_SEL_HC_DC_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 7, 7), + [HW_VBUS_DRV_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 4, 4), + [HW_SEL_CP_EXT_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 3, 3), + [HW_DM_PULLDOWN_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 2, 2), + [HW_DP_PULLDOWN_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 1, 1), + [HW_DP_PULLUP_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 0, 0), +}; + +static const struct regmap_range isp1763_hc_volatile_ranges[] = { + regmap_reg_range(ISP1763_HC_USBCMD, ISP1763_HC_ATL_PTD_LASTPTD), + regmap_reg_range(ISP1763_HC_BUFFER_STATUS, ISP1763_HC_DATA), + regmap_reg_range(ISP1763_HC_INTERRUPT, ISP1763_HC_OTG_CTRL_CLEAR), +}; + +static const struct regmap_access_table isp1763_hc_volatile_table = { + .yes_ranges = isp1763_hc_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(isp1763_hc_volatile_ranges), +}; + +static const struct regmap_config isp1763_hc_regmap_conf = { + .name = "isp1763-hc", + .reg_bits = 8, + .reg_stride = 2, + .val_bits = 16, + .fast_io = true, + .max_register = ISP1763_HC_OTG_CTRL_CLEAR, + .volatile_table = &isp1763_hc_volatile_table, +}; + +static const struct regmap_range isp176x_dc_volatile_ranges[] = { + regmap_reg_range(ISP176x_DC_EPMAXPKTSZ, ISP176x_DC_EPTYPE), + regmap_reg_range(ISP176x_DC_BUFLEN, ISP176x_DC_EPINDEX), +}; + +static const struct regmap_access_table isp176x_dc_volatile_table = { + .yes_ranges = isp176x_dc_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(isp176x_dc_volatile_ranges), +}; + +static const struct regmap_config isp1761_dc_regmap_conf = { + .name = "isp1761-dc", + .reg_bits = 16, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, + .max_register = ISP176x_DC_TESTMODE, + .volatile_table = &isp176x_dc_volatile_table, +}; + +static const struct reg_field isp1761_dc_reg_fields[] = { + [DC_DEVEN] = REG_FIELD(ISP176x_DC_ADDRESS, 7, 7), + [DC_DEVADDR] = REG_FIELD(ISP176x_DC_ADDRESS, 0, 6), + [DC_VBUSSTAT] = REG_FIELD(ISP176x_DC_MODE, 8, 8), + [DC_SFRESET] = REG_FIELD(ISP176x_DC_MODE, 4, 4), + [DC_GLINTENA] = REG_FIELD(ISP176x_DC_MODE, 3, 3), + [DC_CDBGMOD_ACK] = REG_FIELD(ISP176x_DC_INTCONF, 6, 6), + [DC_DDBGMODIN_ACK] = REG_FIELD(ISP176x_DC_INTCONF, 4, 4), + [DC_DDBGMODOUT_ACK] = REG_FIELD(ISP176x_DC_INTCONF, 2, 2), + [DC_INTPOL] = REG_FIELD(ISP176x_DC_INTCONF, 0, 0), + [DC_IEPRXTX_7] = REG_FIELD(ISP176x_DC_INTENABLE, 25, 25), + [DC_IEPRXTX_6] = REG_FIELD(ISP176x_DC_INTENABLE, 23, 23), + [DC_IEPRXTX_5] = REG_FIELD(ISP176x_DC_INTENABLE, 21, 21), + [DC_IEPRXTX_4] = REG_FIELD(ISP176x_DC_INTENABLE, 19, 19), + [DC_IEPRXTX_3] = REG_FIELD(ISP176x_DC_INTENABLE, 17, 17), + [DC_IEPRXTX_2] = REG_FIELD(ISP176x_DC_INTENABLE, 15, 15), + [DC_IEPRXTX_1] = REG_FIELD(ISP176x_DC_INTENABLE, 13, 13), + [DC_IEPRXTX_0] = REG_FIELD(ISP176x_DC_INTENABLE, 11, 11), + [DC_IEP0SETUP] = REG_FIELD(ISP176x_DC_INTENABLE, 8, 8), + [DC_IEVBUS] = REG_FIELD(ISP176x_DC_INTENABLE, 7, 7), + [DC_IEHS_STA] = REG_FIELD(ISP176x_DC_INTENABLE, 5, 5), + [DC_IERESM] = REG_FIELD(ISP176x_DC_INTENABLE, 4, 4), + [DC_IESUSP] = REG_FIELD(ISP176x_DC_INTENABLE, 3, 3), + [DC_IEBRST] = REG_FIELD(ISP176x_DC_INTENABLE, 0, 0), + [DC_EP0SETUP] = REG_FIELD(ISP176x_DC_EPINDEX, 5, 5), + [DC_ENDPIDX] = REG_FIELD(ISP176x_DC_EPINDEX, 1, 4), + [DC_EPDIR] = REG_FIELD(ISP176x_DC_EPINDEX, 0, 0), + [DC_CLBUF] = REG_FIELD(ISP176x_DC_CTRLFUNC, 4, 4), + [DC_VENDP] = REG_FIELD(ISP176x_DC_CTRLFUNC, 3, 3), + [DC_DSEN] = REG_FIELD(ISP176x_DC_CTRLFUNC, 2, 2), + [DC_STATUS] = REG_FIELD(ISP176x_DC_CTRLFUNC, 1, 1), + [DC_STALL] = REG_FIELD(ISP176x_DC_CTRLFUNC, 0, 0), + [DC_BUFLEN] = REG_FIELD(ISP176x_DC_BUFLEN, 0, 15), + [DC_FFOSZ] = REG_FIELD(ISP176x_DC_EPMAXPKTSZ, 0, 10), + [DC_EPENABLE] = REG_FIELD(ISP176x_DC_EPTYPE, 3, 3), + [DC_ENDPTYP] = REG_FIELD(ISP176x_DC_EPTYPE, 0, 1), + [DC_UFRAMENUM] = REG_FIELD(ISP176x_DC_FRAMENUM, 11, 13), + [DC_FRAMENUM] = REG_FIELD(ISP176x_DC_FRAMENUM, 0, 10), + [DC_CHIP_ID_HIGH] = REG_FIELD(ISP176x_DC_CHIPID, 16, 31), + [DC_CHIP_ID_LOW] = REG_FIELD(ISP176x_DC_CHIPID, 0, 15), + [DC_SCRATCH] = REG_FIELD(ISP176x_DC_SCRATCH, 0, 15), +}; + +static const struct regmap_range isp1763_dc_volatile_ranges[] = { + regmap_reg_range(ISP1763_DC_EPMAXPKTSZ, ISP1763_DC_EPTYPE), + regmap_reg_range(ISP1763_DC_BUFLEN, ISP1763_DC_EPINDEX), +}; + +static const struct regmap_access_table isp1763_dc_volatile_table = { + .yes_ranges = isp1763_dc_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(isp1763_dc_volatile_ranges), +}; + +static const struct reg_field isp1763_dc_reg_fields[] = { + [DC_DEVEN] = REG_FIELD(ISP1763_DC_ADDRESS, 7, 7), + [DC_DEVADDR] = REG_FIELD(ISP1763_DC_ADDRESS, 0, 6), + [DC_VBUSSTAT] = REG_FIELD(ISP1763_DC_MODE, 8, 8), + [DC_SFRESET] = REG_FIELD(ISP1763_DC_MODE, 4, 4), + [DC_GLINTENA] = REG_FIELD(ISP1763_DC_MODE, 3, 3), + [DC_CDBGMOD_ACK] = REG_FIELD(ISP1763_DC_INTCONF, 6, 6), + [DC_DDBGMODIN_ACK] = REG_FIELD(ISP1763_DC_INTCONF, 4, 4), + [DC_DDBGMODOUT_ACK] = REG_FIELD(ISP1763_DC_INTCONF, 2, 2), + [DC_INTPOL] = REG_FIELD(ISP1763_DC_INTCONF, 0, 0), + [DC_IEPRXTX_7] = REG_FIELD(ISP1763_DC_INTENABLE, 25, 25), + [DC_IEPRXTX_6] = REG_FIELD(ISP1763_DC_INTENABLE, 23, 23), + [DC_IEPRXTX_5] = REG_FIELD(ISP1763_DC_INTENABLE, 21, 21), + [DC_IEPRXTX_4] = REG_FIELD(ISP1763_DC_INTENABLE, 19, 19), + [DC_IEPRXTX_3] = REG_FIELD(ISP1763_DC_INTENABLE, 17, 17), + [DC_IEPRXTX_2] = REG_FIELD(ISP1763_DC_INTENABLE, 15, 15), + [DC_IEPRXTX_1] = REG_FIELD(ISP1763_DC_INTENABLE, 13, 13), + [DC_IEPRXTX_0] = REG_FIELD(ISP1763_DC_INTENABLE, 11, 11), + [DC_IEP0SETUP] = REG_FIELD(ISP1763_DC_INTENABLE, 8, 8), + [DC_IEVBUS] = REG_FIELD(ISP1763_DC_INTENABLE, 7, 7), + [DC_IEHS_STA] = REG_FIELD(ISP1763_DC_INTENABLE, 5, 5), + [DC_IERESM] = REG_FIELD(ISP1763_DC_INTENABLE, 4, 4), + [DC_IESUSP] = REG_FIELD(ISP1763_DC_INTENABLE, 3, 3), + [DC_IEBRST] = REG_FIELD(ISP1763_DC_INTENABLE, 0, 0), + [DC_EP0SETUP] = REG_FIELD(ISP1763_DC_EPINDEX, 5, 5), + [DC_ENDPIDX] = REG_FIELD(ISP1763_DC_EPINDEX, 1, 4), + [DC_EPDIR] = REG_FIELD(ISP1763_DC_EPINDEX, 0, 0), + [DC_CLBUF] = REG_FIELD(ISP1763_DC_CTRLFUNC, 4, 4), + [DC_VENDP] = REG_FIELD(ISP1763_DC_CTRLFUNC, 3, 3), + [DC_DSEN] = REG_FIELD(ISP1763_DC_CTRLFUNC, 2, 2), + [DC_STATUS] = REG_FIELD(ISP1763_DC_CTRLFUNC, 1, 1), + [DC_STALL] = REG_FIELD(ISP1763_DC_CTRLFUNC, 0, 0), + [DC_BUFLEN] = REG_FIELD(ISP1763_DC_BUFLEN, 0, 15), + [DC_FFOSZ] = REG_FIELD(ISP1763_DC_EPMAXPKTSZ, 0, 10), + [DC_EPENABLE] = REG_FIELD(ISP1763_DC_EPTYPE, 3, 3), + [DC_ENDPTYP] = REG_FIELD(ISP1763_DC_EPTYPE, 0, 1), + [DC_UFRAMENUM] = REG_FIELD(ISP1763_DC_FRAMENUM, 11, 13), + [DC_FRAMENUM] = REG_FIELD(ISP1763_DC_FRAMENUM, 0, 10), + [DC_CHIP_ID_HIGH] = REG_FIELD(ISP1763_DC_CHIPID_HIGH, 0, 15), + [DC_CHIP_ID_LOW] = REG_FIELD(ISP1763_DC_CHIPID_LOW, 0, 15), + [DC_SCRATCH] = REG_FIELD(ISP1763_DC_SCRATCH, 0, 15), +}; + +static const struct regmap_config isp1763_dc_regmap_conf = { + .name = "isp1763-dc", + .reg_bits = 8, + .reg_stride = 2, + .val_bits = 16, + .fast_io = true, + .max_register = ISP1763_DC_TESTMODE, + .volatile_table = &isp1763_dc_volatile_table, +}; + int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, struct device *dev, unsigned int devflags) { + const struct regmap_config *hc_regmap; + const struct reg_field *hc_reg_fields; + const struct regmap_config *dc_regmap; + const struct reg_field *dc_reg_fields; struct isp1760_device *isp; - bool udc_disabled = !(devflags & ISP1760_FLAG_ISP1761); + struct isp1760_hcd *hcd; + struct isp1760_udc *udc; + struct regmap_field *f; + bool udc_enabled; int ret; + int i; /* * If neither the HCD not the UDC is enabled return an error, as no * device would be registered. */ + udc_enabled = ((devflags & ISP1760_FLAG_ISP1763) || + (devflags & ISP1760_FLAG_ISP1761)); + if ((!IS_ENABLED(CONFIG_USB_ISP1760_HCD) || usb_disabled()) && - (!IS_ENABLED(CONFIG_USB_ISP1761_UDC) || udc_disabled)) + (!IS_ENABLED(CONFIG_USB_ISP1761_UDC) || !udc_enabled)) return -ENODEV; isp = devm_kzalloc(dev, sizeof(*isp), GFP_KERNEL); @@ -126,28 +500,81 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, isp->dev = dev; isp->devflags = devflags; + hcd = &isp->hcd; + udc = &isp->udc; + + hcd->is_isp1763 = !!(devflags & ISP1760_FLAG_ISP1763); + udc->is_isp1763 = !!(devflags & ISP1760_FLAG_ISP1763); + + if (!hcd->is_isp1763 && (devflags & ISP1760_FLAG_BUS_WIDTH_8)) { + dev_err(dev, "isp1760/61 do not support data width 8\n"); + return -EINVAL; + } + + if (hcd->is_isp1763) { + hc_regmap = &isp1763_hc_regmap_conf; + hc_reg_fields = &isp1763_hc_reg_fields[0]; + dc_regmap = &isp1763_dc_regmap_conf; + dc_reg_fields = &isp1763_dc_reg_fields[0]; + } else { + hc_regmap = &isp1760_hc_regmap_conf; + hc_reg_fields = &isp1760_hc_reg_fields[0]; + dc_regmap = &isp1761_dc_regmap_conf; + dc_reg_fields = &isp1761_dc_reg_fields[0]; + } isp->rst_gpio = devm_gpiod_get_optional(dev, NULL, GPIOD_OUT_HIGH); if (IS_ERR(isp->rst_gpio)) return PTR_ERR(isp->rst_gpio); - isp->regs = devm_ioremap_resource(dev, mem); - if (IS_ERR(isp->regs)) - return PTR_ERR(isp->regs); + hcd->base = devm_ioremap_resource(dev, mem); + if (IS_ERR(hcd->base)) + return PTR_ERR(hcd->base); + + hcd->regs = devm_regmap_init_mmio(dev, hcd->base, hc_regmap); + if (IS_ERR(hcd->regs)) + return PTR_ERR(hcd->regs); + + for (i = 0; i < HC_FIELD_MAX; i++) { + f = devm_regmap_field_alloc(dev, hcd->regs, hc_reg_fields[i]); + if (IS_ERR(f)) + return PTR_ERR(f); + + hcd->fields[i] = f; + } + + udc->regs = devm_regmap_init_mmio(dev, hcd->base, dc_regmap); + if (IS_ERR(udc->regs)) + return PTR_ERR(udc->regs); + + for (i = 0; i < DC_FIELD_MAX; i++) { + f = devm_regmap_field_alloc(dev, udc->regs, dc_reg_fields[i]); + if (IS_ERR(f)) + return PTR_ERR(f); + + udc->fields[i] = f; + } + + if (hcd->is_isp1763) + hcd->memory_layout = &isp1763_memory_conf; + else + hcd->memory_layout = &isp176x_memory_conf; - isp1760_init_core(isp); + ret = isp1760_init_core(isp); + if (ret < 0) + return ret; if (IS_ENABLED(CONFIG_USB_ISP1760_HCD) && !usb_disabled()) { - ret = isp1760_hcd_register(&isp->hcd, isp->regs, mem, irq, + ret = isp1760_hcd_register(hcd, mem, irq, irqflags | IRQF_SHARED, dev); if (ret < 0) return ret; } - if (IS_ENABLED(CONFIG_USB_ISP1761_UDC) && !udc_disabled) { + if (IS_ENABLED(CONFIG_USB_ISP1761_UDC) && udc_enabled) { ret = isp1760_udc_register(isp, irq, irqflags); if (ret < 0) { - isp1760_hcd_unregister(&isp->hcd); + isp1760_hcd_unregister(hcd); return ret; } } diff --git a/drivers/usb/isp1760/isp1760-core.h b/drivers/usb/isp1760/isp1760-core.h index d9a0a4cc467c..91e0ee3992a7 100644 --- a/drivers/usb/isp1760/isp1760-core.h +++ b/drivers/usb/isp1760/isp1760-core.h @@ -2,18 +2,21 @@ /* * Driver for the NXP ISP1760 chip * + * Copyright 2021 Linaro, Rui Miguel Silva * Copyright 2014 Laurent Pinchart * Copyright 2007 Sebastian Siewior * * Contacts: * Sebastian Siewior <bigeasy@linutronix.de> * Laurent Pinchart <laurent.pinchart@ideasonboard.com> + * Rui Miguel Silva <rui.silva@linaro.org> */ #ifndef _ISP1760_CORE_H_ #define _ISP1760_CORE_H_ #include <linux/ioport.h> +#include <linux/regmap.h> #include "isp1760-hcd.h" #include "isp1760-udc.h" @@ -27,18 +30,19 @@ struct gpio_desc; * a sane default configuration. */ #define ISP1760_FLAG_BUS_WIDTH_16 0x00000002 /* 16-bit data bus width */ -#define ISP1760_FLAG_OTG_EN 0x00000004 /* Port 1 supports OTG */ +#define ISP1760_FLAG_PERIPHERAL_EN 0x00000004 /* Port 1 supports Peripheral mode*/ #define ISP1760_FLAG_ANALOG_OC 0x00000008 /* Analog overcurrent */ #define ISP1760_FLAG_DACK_POL_HIGH 0x00000010 /* DACK active high */ #define ISP1760_FLAG_DREQ_POL_HIGH 0x00000020 /* DREQ active high */ #define ISP1760_FLAG_ISP1761 0x00000040 /* Chip is ISP1761 */ #define ISP1760_FLAG_INTR_POL_HIGH 0x00000080 /* Interrupt polarity active high */ #define ISP1760_FLAG_INTR_EDGE_TRIG 0x00000100 /* Interrupt edge triggered */ +#define ISP1760_FLAG_ISP1763 0x00000200 /* Chip is ISP1763 */ +#define ISP1760_FLAG_BUS_WIDTH_8 0x00000400 /* 8-bit data bus width */ struct isp1760_device { struct device *dev; - void __iomem *regs; unsigned int devflags; struct gpio_desc *rst_gpio; @@ -52,14 +56,42 @@ void isp1760_unregister(struct device *dev); void isp1760_set_pullup(struct isp1760_device *isp, bool enable); -static inline u32 isp1760_read32(void __iomem *base, u32 reg) +static inline u32 isp1760_field_read(struct regmap_field **fields, u32 field) { - return readl(base + reg); + unsigned int val; + + regmap_field_read(fields[field], &val); + + return val; +} + +static inline void isp1760_field_write(struct regmap_field **fields, u32 field, + u32 val) +{ + regmap_field_write(fields[field], val); +} + +static inline void isp1760_field_set(struct regmap_field **fields, u32 field) +{ + isp1760_field_write(fields, field, 0xFFFFFFFF); } -static inline void isp1760_write32(void __iomem *base, u32 reg, u32 val) +static inline void isp1760_field_clear(struct regmap_field **fields, u32 field) { - writel(val, base + reg); + isp1760_field_write(fields, field, 0); } +static inline u32 isp1760_reg_read(struct regmap *regs, u32 reg) +{ + unsigned int val; + + regmap_read(regs, reg, &val); + + return val; +} + +static inline void isp1760_reg_write(struct regmap *regs, u32 reg, u32 val) +{ + regmap_write(regs, reg, val); +} #endif diff --git a/drivers/usb/isp1760/isp1760-hcd.c b/drivers/usb/isp1760/isp1760-hcd.c index 33ae656c4b68..27168b4a4ef2 100644 --- a/drivers/usb/isp1760/isp1760-hcd.c +++ b/drivers/usb/isp1760/isp1760-hcd.c @@ -11,6 +11,8 @@ * * (c) 2011 Arvid Brodin <arvid.brodin@enea.com> * + * Copyright 2021 Linaro, Rui Miguel Silva <rui.silva@linaro.org> + * */ #include <linux/gpio/consumer.h> #include <linux/module.h> @@ -44,6 +46,9 @@ static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd) return *(struct isp1760_hcd **)hcd->hcd_priv; } +#define dw_to_le32(x) (cpu_to_le32((__force u32)x)) +#define le32_to_dw(x) ((__force __dw)(le32_to_cpu(x))) + /* urb state*/ #define DELETE_URB (0x0008) #define NO_TRANSFER_ACTIVE (0xffffffff) @@ -60,50 +65,69 @@ struct ptd { __dw dw6; __dw dw7; }; + +struct ptd_le32 { + __le32 dw0; + __le32 dw1; + __le32 dw2; + __le32 dw3; + __le32 dw4; + __le32 dw5; + __le32 dw6; + __le32 dw7; +}; + #define PTD_OFFSET 0x0400 #define ISO_PTD_OFFSET 0x0400 #define INT_PTD_OFFSET 0x0800 #define ATL_PTD_OFFSET 0x0c00 #define PAYLOAD_OFFSET 0x1000 - -/* ATL */ -/* DW0 */ -#define DW0_VALID_BIT 1 -#define FROM_DW0_VALID(x) ((x) & 0x01) -#define TO_DW0_LENGTH(x) (((u32) x) << 3) -#define TO_DW0_MAXPACKET(x) (((u32) x) << 18) -#define TO_DW0_MULTI(x) (((u32) x) << 29) -#define TO_DW0_ENDPOINT(x) (((u32) x) << 31) +#define ISP_BANK_0 0x00 +#define ISP_BANK_1 0x01 +#define ISP_BANK_2 0x02 +#define ISP_BANK_3 0x03 + +#define TO_DW(x) ((__force __dw)x) +#define TO_U32(x) ((__force u32)x) + + /* ATL */ + /* DW0 */ +#define DW0_VALID_BIT TO_DW(1) +#define FROM_DW0_VALID(x) (TO_U32(x) & 0x01) +#define TO_DW0_LENGTH(x) TO_DW((((u32)x) << 3)) +#define TO_DW0_MAXPACKET(x) TO_DW((((u32)x) << 18)) +#define TO_DW0_MULTI(x) TO_DW((((u32)x) << 29)) +#define TO_DW0_ENDPOINT(x) TO_DW((((u32)x) << 31)) /* DW1 */ -#define TO_DW1_DEVICE_ADDR(x) (((u32) x) << 3) -#define TO_DW1_PID_TOKEN(x) (((u32) x) << 10) -#define DW1_TRANS_BULK ((u32) 2 << 12) -#define DW1_TRANS_INT ((u32) 3 << 12) -#define DW1_TRANS_SPLIT ((u32) 1 << 14) -#define DW1_SE_USB_LOSPEED ((u32) 2 << 16) -#define TO_DW1_PORT_NUM(x) (((u32) x) << 18) -#define TO_DW1_HUB_NUM(x) (((u32) x) << 25) +#define TO_DW1_DEVICE_ADDR(x) TO_DW((((u32)x) << 3)) +#define TO_DW1_PID_TOKEN(x) TO_DW((((u32)x) << 10)) +#define DW1_TRANS_BULK TO_DW(((u32)2 << 12)) +#define DW1_TRANS_INT TO_DW(((u32)3 << 12)) +#define DW1_TRANS_SPLIT TO_DW(((u32)1 << 14)) +#define DW1_SE_USB_LOSPEED TO_DW(((u32)2 << 16)) +#define TO_DW1_PORT_NUM(x) TO_DW((((u32)x) << 18)) +#define TO_DW1_HUB_NUM(x) TO_DW((((u32)x) << 25)) /* DW2 */ -#define TO_DW2_DATA_START_ADDR(x) (((u32) x) << 8) -#define TO_DW2_RL(x) ((x) << 25) -#define FROM_DW2_RL(x) (((x) >> 25) & 0xf) +#define TO_DW2_DATA_START_ADDR(x) TO_DW((((u32)x) << 8)) +#define TO_DW2_RL(x) TO_DW(((x) << 25)) +#define FROM_DW2_RL(x) ((TO_U32(x) >> 25) & 0xf) /* DW3 */ -#define FROM_DW3_NRBYTESTRANSFERRED(x) ((x) & 0x7fff) -#define FROM_DW3_SCS_NRBYTESTRANSFERRED(x) ((x) & 0x07ff) -#define TO_DW3_NAKCOUNT(x) ((x) << 19) -#define FROM_DW3_NAKCOUNT(x) (((x) >> 19) & 0xf) -#define TO_DW3_CERR(x) ((x) << 23) -#define FROM_DW3_CERR(x) (((x) >> 23) & 0x3) -#define TO_DW3_DATA_TOGGLE(x) ((x) << 25) -#define FROM_DW3_DATA_TOGGLE(x) (((x) >> 25) & 0x1) -#define TO_DW3_PING(x) ((x) << 26) -#define FROM_DW3_PING(x) (((x) >> 26) & 0x1) -#define DW3_ERROR_BIT (1 << 28) -#define DW3_BABBLE_BIT (1 << 29) -#define DW3_HALT_BIT (1 << 30) -#define DW3_ACTIVE_BIT (1 << 31) -#define FROM_DW3_ACTIVE(x) (((x) >> 31) & 0x01) +#define FROM_DW3_NRBYTESTRANSFERRED(x) TO_U32((x) & 0x3fff) +#define FROM_DW3_SCS_NRBYTESTRANSFERRED(x) TO_U32((x) & 0x07ff) +#define TO_DW3_NAKCOUNT(x) TO_DW(((x) << 19)) +#define FROM_DW3_NAKCOUNT(x) ((TO_U32(x) >> 19) & 0xf) +#define TO_DW3_CERR(x) TO_DW(((x) << 23)) +#define FROM_DW3_CERR(x) ((TO_U32(x) >> 23) & 0x3) +#define TO_DW3_DATA_TOGGLE(x) TO_DW(((x) << 25)) +#define FROM_DW3_DATA_TOGGLE(x) ((TO_U32(x) >> 25) & 0x1) +#define TO_DW3_PING(x) TO_DW(((x) << 26)) +#define FROM_DW3_PING(x) ((TO_U32(x) >> 26) & 0x1) +#define DW3_ERROR_BIT TO_DW((1 << 28)) +#define DW3_BABBLE_BIT TO_DW((1 << 29)) +#define DW3_HALT_BIT TO_DW((1 << 30)) +#define DW3_ACTIVE_BIT TO_DW((1 << 31)) +#define FROM_DW3_ACTIVE(x) ((TO_U32(x) >> 31) & 0x01) #define INT_UNDERRUN (1 << 2) #define INT_BABBLE (1 << 1) @@ -116,7 +140,7 @@ struct ptd { /* Errata 1 */ #define RL_COUNTER (0) #define NAK_COUNTER (0) -#define ERR_COUNTER (2) +#define ERR_COUNTER (3) struct isp1760_qtd { u8 packet_type; @@ -158,17 +182,124 @@ struct urb_listitem { struct urb *urb; }; +static const u32 isp1763_hc_portsc1_fields[] = { + [PORT_OWNER] = BIT(13), + [PORT_POWER] = BIT(12), + [PORT_LSTATUS] = BIT(10), + [PORT_RESET] = BIT(8), + [PORT_SUSPEND] = BIT(7), + [PORT_RESUME] = BIT(6), + [PORT_PE] = BIT(2), + [PORT_CSC] = BIT(1), + [PORT_CONNECT] = BIT(0), +}; + +/* + * Access functions for isp176x registers regmap fields + */ +static u32 isp1760_hcd_read(struct usb_hcd *hcd, u32 field) +{ + struct isp1760_hcd *priv = hcd_to_priv(hcd); + + return isp1760_field_read(priv->fields, field); +} + /* - * Access functions for isp176x registers (addresses 0..0x03FF). + * We need, in isp1763, to write directly the values to the portsc1 + * register so it will make the other values to trigger. */ -static u32 reg_read32(void __iomem *base, u32 reg) +static void isp1760_hcd_portsc1_set_clear(struct isp1760_hcd *priv, u32 field, + u32 val) +{ + u32 bit = isp1763_hc_portsc1_fields[field]; + u32 port_status = readl(priv->base + ISP1763_HC_PORTSC1); + + if (val) + writel(port_status | bit, priv->base + ISP1763_HC_PORTSC1); + else + writel(port_status & ~bit, priv->base + ISP1763_HC_PORTSC1); +} + +static void isp1760_hcd_write(struct usb_hcd *hcd, u32 field, u32 val) +{ + struct isp1760_hcd *priv = hcd_to_priv(hcd); + + if (unlikely(priv->is_isp1763 && + (field >= PORT_OWNER && field <= PORT_CONNECT))) + return isp1760_hcd_portsc1_set_clear(priv, field, val); + + isp1760_field_write(priv->fields, field, val); +} + +static void isp1760_hcd_set(struct usb_hcd *hcd, u32 field) +{ + isp1760_hcd_write(hcd, field, 0xFFFFFFFF); +} + +static void isp1760_hcd_clear(struct usb_hcd *hcd, u32 field) { - return isp1760_read32(base, reg); + isp1760_hcd_write(hcd, field, 0); +} + +static int isp1760_hcd_set_and_wait(struct usb_hcd *hcd, u32 field, + u32 timeout_us) +{ + struct isp1760_hcd *priv = hcd_to_priv(hcd); + u32 val; + + isp1760_hcd_set(hcd, field); + + return regmap_field_read_poll_timeout(priv->fields[field], val, + val, 10, timeout_us); +} + +static int isp1760_hcd_set_and_wait_swap(struct usb_hcd *hcd, u32 field, + u32 timeout_us) +{ + struct isp1760_hcd *priv = hcd_to_priv(hcd); + u32 val; + + isp1760_hcd_set(hcd, field); + + return regmap_field_read_poll_timeout(priv->fields[field], val, + !val, 10, timeout_us); +} + +static int isp1760_hcd_clear_and_wait(struct usb_hcd *hcd, u32 field, + u32 timeout_us) +{ + struct isp1760_hcd *priv = hcd_to_priv(hcd); + u32 val; + + isp1760_hcd_clear(hcd, field); + + return regmap_field_read_poll_timeout(priv->fields[field], val, + !val, 10, timeout_us); +} + +static bool isp1760_hcd_is_set(struct usb_hcd *hcd, u32 field) +{ + return !!isp1760_hcd_read(hcd, field); +} + +static bool isp1760_hcd_ppc_is_set(struct usb_hcd *hcd) +{ + struct isp1760_hcd *priv = hcd_to_priv(hcd); + + if (priv->is_isp1763) + return true; + + return isp1760_hcd_is_set(hcd, HCS_PPC); } -static void reg_write32(void __iomem *base, u32 reg, u32 val) +static u32 isp1760_hcd_n_ports(struct usb_hcd *hcd) { - isp1760_write32(base, reg, val); + struct isp1760_hcd *priv = hcd_to_priv(hcd); + + if (priv->is_isp1763) + return 1; + + return isp1760_hcd_read(hcd, HCS_N_PORTS); } /* @@ -176,7 +307,7 @@ static void reg_write32(void __iomem *base, u32 reg, u32 val) * * bank_reads8() reads memory locations prefetched by an earlier write to * HC_MEMORY_REG (see isp176x datasheet). Unless you want to do fancy multi- - * bank optimizations, you should use the more generic mem_reads8() below. + * bank optimizations, you should use the more generic mem_read() below. * * For access to ptd memory, use the specialized ptd_read() and ptd_write() * below. @@ -196,7 +327,7 @@ static void bank_reads8(void __iomem *src_base, u32 src_offset, u32 bank_addr, if (src_offset < PAYLOAD_OFFSET) { while (bytes >= 4) { - *dst = le32_to_cpu(__raw_readl(src)); + *dst = readl_relaxed(src); bytes -= 4; src++; dst++; @@ -217,7 +348,7 @@ static void bank_reads8(void __iomem *src_base, u32 src_offset, u32 bank_addr, * allocated. */ if (src_offset < PAYLOAD_OFFSET) - val = le32_to_cpu(__raw_readl(src)); + val = readl_relaxed(src); else val = __raw_readl(src); @@ -231,16 +362,59 @@ static void bank_reads8(void __iomem *src_base, u32 src_offset, u32 bank_addr, } } -static void mem_reads8(void __iomem *src_base, u32 src_offset, void *dst, - u32 bytes) +static void isp1760_mem_read(struct usb_hcd *hcd, u32 src_offset, void *dst, + u32 bytes) { - reg_write32(src_base, HC_MEMORY_REG, src_offset + ISP_BANK(0)); - ndelay(90); - bank_reads8(src_base, src_offset, ISP_BANK(0), dst, bytes); + struct isp1760_hcd *priv = hcd_to_priv(hcd); + + isp1760_hcd_write(hcd, MEM_BANK_SEL, ISP_BANK_0); + isp1760_hcd_write(hcd, MEM_START_ADDR, src_offset); + ndelay(100); + + bank_reads8(priv->base, src_offset, ISP_BANK_0, dst, bytes); } -static void mem_writes8(void __iomem *dst_base, u32 dst_offset, - __u32 const *src, u32 bytes) +/* + * ISP1763 does not have the banks direct host controller memory access, + * needs to use the HC_DATA register. Add data read/write according to this, + * and also adjust 16bit access. + */ +static void isp1763_mem_read(struct usb_hcd *hcd, u16 srcaddr, + u16 *dstptr, u32 bytes) +{ + struct isp1760_hcd *priv = hcd_to_priv(hcd); + + /* Write the starting device address to the hcd memory register */ + isp1760_reg_write(priv->regs, ISP1763_HC_MEMORY, srcaddr); + ndelay(100); /* Delay between consecutive access */ + + /* As long there are at least 16-bit to read ... */ + while (bytes >= 2) { + *dstptr = __raw_readw(priv->base + ISP1763_HC_DATA); + bytes -= 2; + dstptr++; + } + + /* If there are no more bytes to read, return */ + if (bytes <= 0) + return; + + *((u8 *)dstptr) = (u8)(readw(priv->base + ISP1763_HC_DATA) & 0xFF); +} + +static void mem_read(struct usb_hcd *hcd, u32 src_offset, __u32 *dst, + u32 bytes) +{ + struct isp1760_hcd *priv = hcd_to_priv(hcd); + + if (!priv->is_isp1763) + return isp1760_mem_read(hcd, src_offset, (u16 *)dst, bytes); + + isp1763_mem_read(hcd, (u16)src_offset, (u16 *)dst, bytes); +} + +static void isp1760_mem_write(void __iomem *dst_base, u32 dst_offset, + __u32 const *src, u32 bytes) { __u32 __iomem *dst; @@ -248,7 +422,7 @@ static void mem_writes8(void __iomem *dst_base, u32 dst_offset, if (dst_offset < PAYLOAD_OFFSET) { while (bytes >= 4) { - __raw_writel(cpu_to_le32(*src), dst); + writel_relaxed(*src, dst); bytes -= 4; src++; dst++; @@ -269,74 +443,168 @@ static void mem_writes8(void __iomem *dst_base, u32 dst_offset, */ if (dst_offset < PAYLOAD_OFFSET) - __raw_writel(cpu_to_le32(*src), dst); + writel_relaxed(*src, dst); else __raw_writel(*src, dst); } +static void isp1763_mem_write(struct usb_hcd *hcd, u16 dstaddr, u16 *src, + u32 bytes) +{ + struct isp1760_hcd *priv = hcd_to_priv(hcd); + + /* Write the starting device address to the hcd memory register */ + isp1760_reg_write(priv->regs, ISP1763_HC_MEMORY, dstaddr); + ndelay(100); /* Delay between consecutive access */ + + while (bytes >= 2) { + /* Get and write the data; then adjust the data ptr and len */ + __raw_writew(*src, priv->base + ISP1763_HC_DATA); + bytes -= 2; + src++; + } + + /* If there are no more bytes to process, return */ + if (bytes <= 0) + return; + + /* + * The only way to get here is if there is a single byte left, + * get it and write it to the data reg; + */ + writew(*((u8 *)src), priv->base + ISP1763_HC_DATA); +} + +static void mem_write(struct usb_hcd *hcd, u32 dst_offset, __u32 *src, + u32 bytes) +{ + struct isp1760_hcd *priv = hcd_to_priv(hcd); + + if (!priv->is_isp1763) + return isp1760_mem_write(priv->base, dst_offset, src, bytes); + + isp1763_mem_write(hcd, dst_offset, (u16 *)src, bytes); +} + /* * Read and write ptds. 'ptd_offset' should be one of ISO_PTD_OFFSET, * INT_PTD_OFFSET, and ATL_PTD_OFFSET. 'slot' should be less than 32. */ -static void ptd_read(void __iomem *base, u32 ptd_offset, u32 slot, - struct ptd *ptd) +static void isp1760_ptd_read(struct usb_hcd *hcd, u32 ptd_offset, u32 slot, + struct ptd *ptd) { - reg_write32(base, HC_MEMORY_REG, - ISP_BANK(0) + ptd_offset + slot*sizeof(*ptd)); + u16 src_offset = ptd_offset + slot * sizeof(*ptd); + struct isp1760_hcd *priv = hcd_to_priv(hcd); + + isp1760_hcd_write(hcd, MEM_BANK_SEL, ISP_BANK_0); + isp1760_hcd_write(hcd, MEM_START_ADDR, src_offset); ndelay(90); - bank_reads8(base, ptd_offset + slot*sizeof(*ptd), ISP_BANK(0), - (void *) ptd, sizeof(*ptd)); + + bank_reads8(priv->base, src_offset, ISP_BANK_0, (void *)ptd, + sizeof(*ptd)); +} + +static void isp1763_ptd_read(struct usb_hcd *hcd, u32 ptd_offset, u32 slot, + struct ptd *ptd) +{ + u16 src_offset = ptd_offset + slot * sizeof(*ptd); + struct ptd_le32 le32_ptd; + + isp1763_mem_read(hcd, src_offset, (u16 *)&le32_ptd, sizeof(le32_ptd)); + /* Normalize the data obtained */ + ptd->dw0 = le32_to_dw(le32_ptd.dw0); + ptd->dw1 = le32_to_dw(le32_ptd.dw1); + ptd->dw2 = le32_to_dw(le32_ptd.dw2); + ptd->dw3 = le32_to_dw(le32_ptd.dw3); + ptd->dw4 = le32_to_dw(le32_ptd.dw4); + ptd->dw5 = le32_to_dw(le32_ptd.dw5); + ptd->dw6 = le32_to_dw(le32_ptd.dw6); + ptd->dw7 = le32_to_dw(le32_ptd.dw7); +} + +static void ptd_read(struct usb_hcd *hcd, u32 ptd_offset, u32 slot, + struct ptd *ptd) +{ + struct isp1760_hcd *priv = hcd_to_priv(hcd); + + if (!priv->is_isp1763) + return isp1760_ptd_read(hcd, ptd_offset, slot, ptd); + + isp1763_ptd_read(hcd, ptd_offset, slot, ptd); +} + +static void isp1763_ptd_write(struct usb_hcd *hcd, u32 ptd_offset, u32 slot, + struct ptd *cpu_ptd) +{ + u16 dst_offset = ptd_offset + slot * sizeof(*cpu_ptd); + struct ptd_le32 ptd; + + ptd.dw0 = dw_to_le32(cpu_ptd->dw0); + ptd.dw1 = dw_to_le32(cpu_ptd->dw1); + ptd.dw2 = dw_to_le32(cpu_ptd->dw2); + ptd.dw3 = dw_to_le32(cpu_ptd->dw3); + ptd.dw4 = dw_to_le32(cpu_ptd->dw4); + ptd.dw5 = dw_to_le32(cpu_ptd->dw5); + ptd.dw6 = dw_to_le32(cpu_ptd->dw6); + ptd.dw7 = dw_to_le32(cpu_ptd->dw7); + + isp1763_mem_write(hcd, dst_offset, (u16 *)&ptd.dw0, + 8 * sizeof(ptd.dw0)); } -static void ptd_write(void __iomem *base, u32 ptd_offset, u32 slot, - struct ptd *ptd) +static void isp1760_ptd_write(void __iomem *base, u32 ptd_offset, u32 slot, + struct ptd *ptd) { - mem_writes8(base, ptd_offset + slot*sizeof(*ptd) + sizeof(ptd->dw0), - &ptd->dw1, 7*sizeof(ptd->dw1)); - /* Make sure dw0 gets written last (after other dw's and after payload) - since it contains the enable bit */ + u32 dst_offset = ptd_offset + slot * sizeof(*ptd); + + /* + * Make sure dw0 gets written last (after other dw's and after payload) + * since it contains the enable bit + */ + isp1760_mem_write(base, dst_offset + sizeof(ptd->dw0), + (__force u32 *)&ptd->dw1, 7 * sizeof(ptd->dw1)); wmb(); - mem_writes8(base, ptd_offset + slot*sizeof(*ptd), &ptd->dw0, - sizeof(ptd->dw0)); + isp1760_mem_write(base, dst_offset, (__force u32 *)&ptd->dw0, + sizeof(ptd->dw0)); } +static void ptd_write(struct usb_hcd *hcd, u32 ptd_offset, u32 slot, + struct ptd *ptd) +{ + struct isp1760_hcd *priv = hcd_to_priv(hcd); + + if (!priv->is_isp1763) + return isp1760_ptd_write(priv->base, ptd_offset, slot, ptd); + + isp1763_ptd_write(hcd, ptd_offset, slot, ptd); +} /* memory management of the 60kb on the chip from 0x1000 to 0xffff */ static void init_memory(struct isp1760_hcd *priv) { - int i, curr; + const struct isp1760_memory_layout *mem = priv->memory_layout; + int i, j, curr; u32 payload_addr; payload_addr = PAYLOAD_OFFSET; - for (i = 0; i < BLOCK_1_NUM; i++) { - priv->memory_pool[i].start = payload_addr; - priv->memory_pool[i].size = BLOCK_1_SIZE; - priv->memory_pool[i].free = 1; - payload_addr += priv->memory_pool[i].size; - } - - curr = i; - for (i = 0; i < BLOCK_2_NUM; i++) { - priv->memory_pool[curr + i].start = payload_addr; - priv->memory_pool[curr + i].size = BLOCK_2_SIZE; - priv->memory_pool[curr + i].free = 1; - payload_addr += priv->memory_pool[curr + i].size; - } - curr = i; - for (i = 0; i < BLOCK_3_NUM; i++) { - priv->memory_pool[curr + i].start = payload_addr; - priv->memory_pool[curr + i].size = BLOCK_3_SIZE; - priv->memory_pool[curr + i].free = 1; - payload_addr += priv->memory_pool[curr + i].size; + for (i = 0, curr = 0; i < ARRAY_SIZE(mem->blocks); i++) { + for (j = 0; j < mem->blocks[i]; j++, curr++) { + priv->memory_pool[curr + j].start = payload_addr; + priv->memory_pool[curr + j].size = mem->blocks_size[i]; + priv->memory_pool[curr + j].free = 1; + payload_addr += priv->memory_pool[curr + j].size; + } } - WARN_ON(payload_addr - priv->memory_pool[0].start > PAYLOAD_AREA_SIZE); + WARN_ON(payload_addr - priv->memory_pool[0].start > + mem->payload_area_size); } static void alloc_mem(struct usb_hcd *hcd, struct isp1760_qtd *qtd) { struct isp1760_hcd *priv = hcd_to_priv(hcd); + const struct isp1760_memory_layout *mem = priv->memory_layout; int i; WARN_ON(qtd->payload_addr); @@ -344,7 +612,7 @@ static void alloc_mem(struct usb_hcd *hcd, struct isp1760_qtd *qtd) if (!qtd->length) return; - for (i = 0; i < BLOCKS; i++) { + for (i = 0; i < mem->payload_blocks; i++) { if (priv->memory_pool[i].size >= qtd->length && priv->memory_pool[i].free) { priv->memory_pool[i].free = 0; @@ -357,12 +625,13 @@ static void alloc_mem(struct usb_hcd *hcd, struct isp1760_qtd *qtd) static void free_mem(struct usb_hcd *hcd, struct isp1760_qtd *qtd) { struct isp1760_hcd *priv = hcd_to_priv(hcd); + const struct isp1760_memory_layout *mem = priv->memory_layout; int i; if (!qtd->payload_addr) return; - for (i = 0; i < BLOCKS; i++) { + for (i = 0; i < mem->payload_blocks; i++) { if (priv->memory_pool[i].start == qtd->payload_addr) { WARN_ON(priv->memory_pool[i].free); priv->memory_pool[i].free = 1; @@ -377,34 +646,15 @@ static void free_mem(struct usb_hcd *hcd, struct isp1760_qtd *qtd) qtd->payload_addr = 0; } -static int handshake(struct usb_hcd *hcd, u32 reg, - u32 mask, u32 done, int usec) -{ - u32 result; - int ret; - - ret = readl_poll_timeout_atomic(hcd->regs + reg, result, - ((result & mask) == done || - result == U32_MAX), 1, usec); - if (result == U32_MAX) - return -ENODEV; - - return ret; -} - /* reset a non-running (STS_HALT == 1) controller */ static int ehci_reset(struct usb_hcd *hcd) { struct isp1760_hcd *priv = hcd_to_priv(hcd); - u32 command = reg_read32(hcd->regs, HC_USBCMD); - - command |= CMD_RESET; - reg_write32(hcd->regs, HC_USBCMD, command); hcd->state = HC_STATE_HALT; priv->next_statechange = jiffies; - return handshake(hcd, HC_USBCMD, CMD_RESET, 0, 250 * 1000); + return isp1760_hcd_set_and_wait_swap(hcd, CMD_RESET, 250 * 1000); } static struct isp1760_qh *qh_alloc(gfp_t flags) @@ -432,8 +682,9 @@ static void qh_free(struct isp1760_qh *qh) /* one-time init, only for memory state */ static int priv_init(struct usb_hcd *hcd) { - struct isp1760_hcd *priv = hcd_to_priv(hcd); - u32 hcc_params; + struct isp1760_hcd *priv = hcd_to_priv(hcd); + u32 isoc_cache; + u32 isoc_thres; int i; spin_lock_init(&priv->lock); @@ -447,13 +698,20 @@ static int priv_init(struct usb_hcd *hcd) */ priv->periodic_size = DEFAULT_I_TDPS; + if (priv->is_isp1763) { + priv->i_thresh = 2; + return 0; + } + /* controllers may cache some of the periodic schedule ... */ - hcc_params = reg_read32(hcd->regs, HC_HCCPARAMS); + isoc_cache = isp1760_hcd_read(hcd, HCC_ISOC_CACHE); + isoc_thres = isp1760_hcd_read(hcd, HCC_ISOC_THRES); + /* full frame cache */ - if (HCC_ISOC_CACHE(hcc_params)) + if (isoc_cache) priv->i_thresh = 8; else /* N microframes cached */ - priv->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); + priv->i_thresh = 2 + isoc_thres; return 0; } @@ -461,15 +719,24 @@ static int priv_init(struct usb_hcd *hcd) static int isp1760_hc_setup(struct usb_hcd *hcd) { struct isp1760_hcd *priv = hcd_to_priv(hcd); + u32 atx_reset; int result; - u32 scratch, hwmode; + u32 scratch; + u32 pattern; + + if (priv->is_isp1763) + pattern = 0xcafe; + else + pattern = 0xdeadcafe; + + isp1760_hcd_write(hcd, HC_SCRATCH, pattern); - reg_write32(hcd->regs, HC_SCRATCH_REG, 0xdeadbabe); /* Change bus pattern */ - scratch = reg_read32(hcd->regs, HC_CHIP_ID_REG); - scratch = reg_read32(hcd->regs, HC_SCRATCH_REG); - if (scratch != 0xdeadbabe) { - dev_err(hcd->self.controller, "Scratch test failed.\n"); + scratch = isp1760_hcd_read(hcd, HC_CHIP_ID_HIGH); + dev_err(hcd->self.controller, "Scratch test 0x%08x\n", scratch); + scratch = isp1760_hcd_read(hcd, HC_SCRATCH); + if (scratch != pattern) { + dev_err(hcd->self.controller, "Scratch test failed. 0x%08x\n", scratch); return -ENODEV; } @@ -481,10 +748,13 @@ static int isp1760_hc_setup(struct usb_hcd *hcd) * the host controller through the EHCI USB Command register. The device * has been reset in core code anyway, so this shouldn't matter. */ - reg_write32(hcd->regs, HC_BUFFER_STATUS_REG, 0); - reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE); - reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE); - reg_write32(hcd->regs, HC_ISO_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE); + isp1760_hcd_clear(hcd, ISO_BUF_FILL); + isp1760_hcd_clear(hcd, INT_BUF_FILL); + isp1760_hcd_clear(hcd, ATL_BUF_FILL); + + isp1760_hcd_set(hcd, HC_ATL_PTD_SKIPMAP); + isp1760_hcd_set(hcd, HC_INT_PTD_SKIPMAP); + isp1760_hcd_set(hcd, HC_ISO_PTD_SKIPMAP); result = ehci_reset(hcd); if (result) @@ -493,14 +763,26 @@ static int isp1760_hc_setup(struct usb_hcd *hcd) /* Step 11 passed */ /* ATL reset */ - hwmode = reg_read32(hcd->regs, HC_HW_MODE_CTRL) & ~ALL_ATX_RESET; - reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode | ALL_ATX_RESET); + if (priv->is_isp1763) + atx_reset = SW_RESET_RESET_ATX; + else + atx_reset = ALL_ATX_RESET; + + isp1760_hcd_set(hcd, atx_reset); mdelay(10); - reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode); + isp1760_hcd_clear(hcd, atx_reset); - reg_write32(hcd->regs, HC_INTERRUPT_ENABLE, INTERRUPT_ENABLE_MASK); + if (priv->is_isp1763) { + isp1760_hcd_set(hcd, HW_OTG_DISABLE); + isp1760_hcd_set(hcd, HW_SW_SEL_HC_DC_CLEAR); + isp1760_hcd_set(hcd, HW_HC_2_DIS_CLEAR); + mdelay(10); - priv->hcs_params = reg_read32(hcd->regs, HC_HCSPARAMS); + isp1760_hcd_set(hcd, HW_INTF_LOCK); + } + + isp1760_hcd_set(hcd, HC_INT_IRQ_ENABLE); + isp1760_hcd_set(hcd, HC_ATL_IRQ_ENABLE); return priv_init(hcd); } @@ -553,7 +835,7 @@ static void create_ptd_atl(struct isp1760_qh *qh, ptd->dw0 |= TO_DW0_ENDPOINT(usb_pipeendpoint(qtd->urb->pipe)); /* DW1 */ - ptd->dw1 = usb_pipeendpoint(qtd->urb->pipe) >> 1; + ptd->dw1 = TO_DW((usb_pipeendpoint(qtd->urb->pipe) >> 1)); ptd->dw1 |= TO_DW1_DEVICE_ADDR(usb_pipedevice(qtd->urb->pipe)); ptd->dw1 |= TO_DW1_PID_TOKEN(qtd->packet_type); @@ -575,7 +857,7 @@ static void create_ptd_atl(struct isp1760_qh *qh, /* SE bit for Split INT transfers */ if (usb_pipeint(qtd->urb->pipe) && (qtd->urb->dev->speed == USB_SPEED_LOW)) - ptd->dw1 |= 2 << 16; + ptd->dw1 |= DW1_SE_USB_LOSPEED; rl = 0; nak = 0; @@ -647,14 +929,14 @@ static void transform_add_int(struct isp1760_qh *qh, * that number come from? 0xff seems to work fine... */ /* ptd->dw5 = 0x1c; */ - ptd->dw5 = 0xff; /* Execute Complete Split on any uFrame */ + ptd->dw5 = TO_DW(0xff); /* Execute Complete Split on any uFrame */ } period = period >> 1;/* Ensure equal or shorter period than requested */ period &= 0xf8; /* Mask off too large values and lowest unused 3 bits */ - ptd->dw2 |= period; - ptd->dw4 = usof; + ptd->dw2 |= TO_DW(period); + ptd->dw4 = TO_DW(usof); } static void create_ptd_int(struct isp1760_qh *qh, @@ -720,41 +1002,45 @@ static void start_bus_transfer(struct usb_hcd *hcd, u32 ptd_offset, int slot, struct ptd *ptd) { struct isp1760_hcd *priv = hcd_to_priv(hcd); + const struct isp1760_memory_layout *mem = priv->memory_layout; int skip_map; - WARN_ON((slot < 0) || (slot > 31)); + WARN_ON((slot < 0) || (slot > mem->slot_num - 1)); WARN_ON(qtd->length && !qtd->payload_addr); WARN_ON(slots[slot].qtd); WARN_ON(slots[slot].qh); WARN_ON(qtd->status != QTD_PAYLOAD_ALLOC); + if (priv->is_isp1763) + ndelay(100); + /* Make sure done map has not triggered from some unlinked transfer */ if (ptd_offset == ATL_PTD_OFFSET) { - priv->atl_done_map |= reg_read32(hcd->regs, - HC_ATL_PTD_DONEMAP_REG); + skip_map = isp1760_hcd_read(hcd, HC_ATL_PTD_SKIPMAP); + isp1760_hcd_write(hcd, HC_ATL_PTD_SKIPMAP, + skip_map | (1 << slot)); + priv->atl_done_map |= isp1760_hcd_read(hcd, HC_ATL_PTD_DONEMAP); priv->atl_done_map &= ~(1 << slot); } else { - priv->int_done_map |= reg_read32(hcd->regs, - HC_INT_PTD_DONEMAP_REG); + skip_map = isp1760_hcd_read(hcd, HC_INT_PTD_SKIPMAP); + isp1760_hcd_write(hcd, HC_INT_PTD_SKIPMAP, + skip_map | (1 << slot)); + priv->int_done_map |= isp1760_hcd_read(hcd, HC_INT_PTD_DONEMAP); priv->int_done_map &= ~(1 << slot); } + skip_map &= ~(1 << slot); qh->slot = slot; qtd->status = QTD_XFER_STARTED; slots[slot].timestamp = jiffies; slots[slot].qtd = qtd; slots[slot].qh = qh; - ptd_write(hcd->regs, ptd_offset, slot, ptd); + ptd_write(hcd, ptd_offset, slot, ptd); - if (ptd_offset == ATL_PTD_OFFSET) { - skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG); - skip_map &= ~(1 << qh->slot); - reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, skip_map); - } else { - skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG); - skip_map &= ~(1 << qh->slot); - reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, skip_map); - } + if (ptd_offset == ATL_PTD_OFFSET) + isp1760_hcd_write(hcd, HC_ATL_PTD_SKIPMAP, skip_map); + else + isp1760_hcd_write(hcd, HC_INT_PTD_SKIPMAP, skip_map); } static int is_short_bulk(struct isp1760_qtd *qtd) @@ -766,9 +1052,9 @@ static int is_short_bulk(struct isp1760_qtd *qtd) static void collect_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh, struct list_head *urb_list) { - int last_qtd; struct isp1760_qtd *qtd, *qtd_next; struct urb_listitem *urb_listitem; + int last_qtd; list_for_each_entry_safe(qtd, qtd_next, &qh->qtd_list, qtd_list) { if (qtd->status < QTD_XFER_COMPLETE) @@ -783,9 +1069,9 @@ static void collect_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh, if (qtd->actual_length) { switch (qtd->packet_type) { case IN_PID: - mem_reads8(hcd->regs, qtd->payload_addr, - qtd->data_buffer, - qtd->actual_length); + mem_read(hcd, qtd->payload_addr, + qtd->data_buffer, + qtd->actual_length); fallthrough; case OUT_PID: qtd->urb->actual_length += @@ -829,6 +1115,8 @@ static void collect_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh, static void enqueue_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh) { struct isp1760_hcd *priv = hcd_to_priv(hcd); + const struct isp1760_memory_layout *mem = priv->memory_layout; + int slot_num = mem->slot_num; int ptd_offset; struct isp1760_slotinfo *slots; int curr_slot, free_slot; @@ -855,7 +1143,7 @@ static void enqueue_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh) } free_slot = -1; - for (curr_slot = 0; curr_slot < 32; curr_slot++) { + for (curr_slot = 0; curr_slot < slot_num; curr_slot++) { if ((free_slot == -1) && (slots[curr_slot].qtd == NULL)) free_slot = curr_slot; if (slots[curr_slot].qh == qh) @@ -870,11 +1158,10 @@ static void enqueue_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh) if ((qtd->length) && (!qtd->payload_addr)) break; - if ((qtd->length) && - ((qtd->packet_type == SETUP_PID) || - (qtd->packet_type == OUT_PID))) { - mem_writes8(hcd->regs, qtd->payload_addr, - qtd->data_buffer, qtd->length); + if (qtd->length && (qtd->packet_type == SETUP_PID || + qtd->packet_type == OUT_PID)) { + mem_write(hcd, qtd->payload_addr, + qtd->data_buffer, qtd->length); } qtd->status = QTD_PAYLOAD_ALLOC; @@ -887,7 +1174,7 @@ static void enqueue_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh) "available for transfer\n", __func__); */ /* Start xfer for this endpoint if not already done */ - if ((curr_slot > 31) && (free_slot > -1)) { + if ((curr_slot > slot_num - 1) && (free_slot > -1)) { if (usb_pipeint(qtd->urb->pipe)) create_ptd_int(qh, qtd, &ptd); else @@ -977,10 +1264,10 @@ static void schedule_ptds(struct usb_hcd *hcd) static int check_int_transfer(struct usb_hcd *hcd, struct ptd *ptd, struct urb *urb) { - __dw dw4; + u32 dw4; int i; - dw4 = ptd->dw4; + dw4 = TO_U32(ptd->dw4); dw4 >>= 8; /* FIXME: ISP1761 datasheet does not say what to do with these. Do we @@ -1074,9 +1361,9 @@ static void handle_done_ptds(struct usb_hcd *hcd) int modified; int skip_map; - skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG); + skip_map = isp1760_hcd_read(hcd, HC_INT_PTD_SKIPMAP); priv->int_done_map &= ~skip_map; - skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG); + skip_map = isp1760_hcd_read(hcd, HC_ATL_PTD_SKIPMAP); priv->atl_done_map &= ~skip_map; modified = priv->int_done_map || priv->atl_done_map; @@ -1094,7 +1381,7 @@ static void handle_done_ptds(struct usb_hcd *hcd) continue; } ptd_offset = INT_PTD_OFFSET; - ptd_read(hcd->regs, INT_PTD_OFFSET, slot, &ptd); + ptd_read(hcd, INT_PTD_OFFSET, slot, &ptd); state = check_int_transfer(hcd, &ptd, slots[slot].qtd->urb); } else { @@ -1109,7 +1396,7 @@ static void handle_done_ptds(struct usb_hcd *hcd) continue; } ptd_offset = ATL_PTD_OFFSET; - ptd_read(hcd->regs, ATL_PTD_OFFSET, slot, &ptd); + ptd_read(hcd, ATL_PTD_OFFSET, slot, &ptd); state = check_atl_transfer(hcd, &ptd, slots[slot].qtd->urb); } @@ -1134,7 +1421,7 @@ static void handle_done_ptds(struct usb_hcd *hcd) qtd->status = QTD_XFER_COMPLETE; if (list_is_last(&qtd->qtd_list, &qh->qtd_list) || - is_short_bulk(qtd)) + is_short_bulk(qtd)) qtd = NULL; else qtd = list_entry(qtd->qtd_list.next, @@ -1202,25 +1489,30 @@ static void handle_done_ptds(struct usb_hcd *hcd) static irqreturn_t isp1760_irq(struct usb_hcd *hcd) { struct isp1760_hcd *priv = hcd_to_priv(hcd); - u32 imask; irqreturn_t irqret = IRQ_NONE; + u32 int_reg; + u32 imask; spin_lock(&priv->lock); if (!(hcd->state & HC_STATE_RUNNING)) goto leave; - imask = reg_read32(hcd->regs, HC_INTERRUPT_REG); + imask = isp1760_hcd_read(hcd, HC_INTERRUPT); if (unlikely(!imask)) goto leave; - reg_write32(hcd->regs, HC_INTERRUPT_REG, imask); /* Clear */ - priv->int_done_map |= reg_read32(hcd->regs, HC_INT_PTD_DONEMAP_REG); - priv->atl_done_map |= reg_read32(hcd->regs, HC_ATL_PTD_DONEMAP_REG); + int_reg = priv->is_isp1763 ? ISP1763_HC_INTERRUPT : + ISP176x_HC_INTERRUPT; + isp1760_reg_write(priv->regs, int_reg, imask); + + priv->int_done_map |= isp1760_hcd_read(hcd, HC_INT_PTD_DONEMAP); + priv->atl_done_map |= isp1760_hcd_read(hcd, HC_ATL_PTD_DONEMAP); handle_done_ptds(hcd); irqret = IRQ_HANDLED; + leave: spin_unlock(&priv->lock); @@ -1261,17 +1553,18 @@ static void errata2_function(struct timer_list *unused) { struct usb_hcd *hcd = errata2_timer_hcd; struct isp1760_hcd *priv = hcd_to_priv(hcd); + const struct isp1760_memory_layout *mem = priv->memory_layout; int slot; struct ptd ptd; unsigned long spinflags; spin_lock_irqsave(&priv->lock, spinflags); - for (slot = 0; slot < 32; slot++) + for (slot = 0; slot < mem->slot_num; slot++) if (priv->atl_slots[slot].qh && time_after(jiffies, priv->atl_slots[slot].timestamp + msecs_to_jiffies(SLOT_TIMEOUT))) { - ptd_read(hcd->regs, ATL_PTD_OFFSET, slot, &ptd); + ptd_read(hcd, ATL_PTD_OFFSET, slot, &ptd); if (!FROM_DW0_VALID(ptd.dw0) && !FROM_DW3_ACTIVE(ptd.dw3)) priv->atl_done_map |= 1 << slot; @@ -1286,35 +1579,120 @@ static void errata2_function(struct timer_list *unused) add_timer(&errata2_timer); } +static int isp1763_run(struct usb_hcd *hcd) +{ + struct isp1760_hcd *priv = hcd_to_priv(hcd); + int retval; + u32 chipid_h; + u32 chipid_l; + u32 chip_rev; + u32 ptd_atl_int; + u32 ptd_iso; + + hcd->uses_new_polling = 1; + hcd->state = HC_STATE_RUNNING; + + chipid_h = isp1760_hcd_read(hcd, HC_CHIP_ID_HIGH); + chipid_l = isp1760_hcd_read(hcd, HC_CHIP_ID_LOW); + chip_rev = isp1760_hcd_read(hcd, HC_CHIP_REV); + dev_info(hcd->self.controller, "USB ISP %02x%02x HW rev. %d started\n", + chipid_h, chipid_l, chip_rev); + + isp1760_hcd_clear(hcd, ISO_BUF_FILL); + isp1760_hcd_clear(hcd, INT_BUF_FILL); + isp1760_hcd_clear(hcd, ATL_BUF_FILL); + + isp1760_hcd_set(hcd, HC_ATL_PTD_SKIPMAP); + isp1760_hcd_set(hcd, HC_INT_PTD_SKIPMAP); + isp1760_hcd_set(hcd, HC_ISO_PTD_SKIPMAP); + ndelay(100); + isp1760_hcd_clear(hcd, HC_ATL_PTD_DONEMAP); + isp1760_hcd_clear(hcd, HC_INT_PTD_DONEMAP); + isp1760_hcd_clear(hcd, HC_ISO_PTD_DONEMAP); + + isp1760_hcd_set(hcd, HW_OTG_DISABLE); + isp1760_reg_write(priv->regs, ISP1763_HC_OTG_CTRL_CLEAR, BIT(7)); + isp1760_reg_write(priv->regs, ISP1763_HC_OTG_CTRL_CLEAR, BIT(15)); + mdelay(10); + + isp1760_hcd_set(hcd, HC_INT_IRQ_ENABLE); + isp1760_hcd_set(hcd, HC_ATL_IRQ_ENABLE); + + isp1760_hcd_set(hcd, HW_GLOBAL_INTR_EN); + + isp1760_hcd_clear(hcd, HC_ATL_IRQ_MASK_AND); + isp1760_hcd_clear(hcd, HC_INT_IRQ_MASK_AND); + isp1760_hcd_clear(hcd, HC_ISO_IRQ_MASK_AND); + + isp1760_hcd_set(hcd, HC_ATL_IRQ_MASK_OR); + isp1760_hcd_set(hcd, HC_INT_IRQ_MASK_OR); + isp1760_hcd_set(hcd, HC_ISO_IRQ_MASK_OR); + + ptd_atl_int = 0x8000; + ptd_iso = 0x0001; + + isp1760_hcd_write(hcd, HC_ATL_PTD_LASTPTD, ptd_atl_int); + isp1760_hcd_write(hcd, HC_INT_PTD_LASTPTD, ptd_atl_int); + isp1760_hcd_write(hcd, HC_ISO_PTD_LASTPTD, ptd_iso); + + isp1760_hcd_set(hcd, ATL_BUF_FILL); + isp1760_hcd_set(hcd, INT_BUF_FILL); + + isp1760_hcd_clear(hcd, CMD_LRESET); + isp1760_hcd_clear(hcd, CMD_RESET); + + retval = isp1760_hcd_set_and_wait(hcd, CMD_RUN, 250 * 1000); + if (retval) + return retval; + + down_write(&ehci_cf_port_reset_rwsem); + retval = isp1760_hcd_set_and_wait(hcd, FLAG_CF, 250 * 1000); + up_write(&ehci_cf_port_reset_rwsem); + if (retval) + return retval; + + return 0; +} + static int isp1760_run(struct usb_hcd *hcd) { + struct isp1760_hcd *priv = hcd_to_priv(hcd); int retval; - u32 temp; - u32 command; - u32 chipid; + u32 chipid_h; + u32 chipid_l; + u32 chip_rev; + u32 ptd_atl_int; + u32 ptd_iso; + + /* + * ISP1763 have some differences in the setup and order to enable + * the ports, disable otg, setup buffers, and ATL, INT, ISO status. + * So, just handle it a separate sequence. + */ + if (priv->is_isp1763) + return isp1763_run(hcd); hcd->uses_new_polling = 1; hcd->state = HC_STATE_RUNNING; /* Set PTD interrupt AND & OR maps */ - reg_write32(hcd->regs, HC_ATL_IRQ_MASK_AND_REG, 0); - reg_write32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG, 0xffffffff); - reg_write32(hcd->regs, HC_INT_IRQ_MASK_AND_REG, 0); - reg_write32(hcd->regs, HC_INT_IRQ_MASK_OR_REG, 0xffffffff); - reg_write32(hcd->regs, HC_ISO_IRQ_MASK_AND_REG, 0); - reg_write32(hcd->regs, HC_ISO_IRQ_MASK_OR_REG, 0xffffffff); + isp1760_hcd_clear(hcd, HC_ATL_IRQ_MASK_AND); + isp1760_hcd_clear(hcd, HC_INT_IRQ_MASK_AND); + isp1760_hcd_clear(hcd, HC_ISO_IRQ_MASK_AND); + + isp1760_hcd_set(hcd, HC_ATL_IRQ_MASK_OR); + isp1760_hcd_set(hcd, HC_INT_IRQ_MASK_OR); + isp1760_hcd_set(hcd, HC_ISO_IRQ_MASK_OR); + /* step 23 passed */ - temp = reg_read32(hcd->regs, HC_HW_MODE_CTRL); - reg_write32(hcd->regs, HC_HW_MODE_CTRL, temp | HW_GLOBAL_INTR_EN); + isp1760_hcd_set(hcd, HW_GLOBAL_INTR_EN); - command = reg_read32(hcd->regs, HC_USBCMD); - command &= ~(CMD_LRESET|CMD_RESET); - command |= CMD_RUN; - reg_write32(hcd->regs, HC_USBCMD, command); + isp1760_hcd_clear(hcd, CMD_LRESET); + isp1760_hcd_clear(hcd, CMD_RESET); - retval = handshake(hcd, HC_USBCMD, CMD_RUN, CMD_RUN, 250 * 1000); + retval = isp1760_hcd_set_and_wait(hcd, CMD_RUN, 250 * 1000); if (retval) return retval; @@ -1324,9 +1702,8 @@ static int isp1760_run(struct usb_hcd *hcd) * the semaphore while doing so. */ down_write(&ehci_cf_port_reset_rwsem); - reg_write32(hcd->regs, HC_CONFIGFLAG, FLAG_CF); - retval = handshake(hcd, HC_CONFIGFLAG, FLAG_CF, FLAG_CF, 250 * 1000); + retval = isp1760_hcd_set_and_wait(hcd, FLAG_CF, 250 * 1000); up_write(&ehci_cf_port_reset_rwsem); if (retval) return retval; @@ -1336,21 +1713,28 @@ static int isp1760_run(struct usb_hcd *hcd) errata2_timer.expires = jiffies + msecs_to_jiffies(SLOT_CHECK_PERIOD); add_timer(&errata2_timer); - chipid = reg_read32(hcd->regs, HC_CHIP_ID_REG); - dev_info(hcd->self.controller, "USB ISP %04x HW rev. %d started\n", - chipid & 0xffff, chipid >> 16); + chipid_h = isp1760_hcd_read(hcd, HC_CHIP_ID_HIGH); + chipid_l = isp1760_hcd_read(hcd, HC_CHIP_ID_LOW); + chip_rev = isp1760_hcd_read(hcd, HC_CHIP_REV); + dev_info(hcd->self.controller, "USB ISP %02x%02x HW rev. %d started\n", + chipid_h, chipid_l, chip_rev); /* PTD Register Init Part 2, Step 28 */ /* Setup registers controlling PTD checking */ - reg_write32(hcd->regs, HC_ATL_PTD_LASTPTD_REG, 0x80000000); - reg_write32(hcd->regs, HC_INT_PTD_LASTPTD_REG, 0x80000000); - reg_write32(hcd->regs, HC_ISO_PTD_LASTPTD_REG, 0x00000001); - reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, 0xffffffff); - reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, 0xffffffff); - reg_write32(hcd->regs, HC_ISO_PTD_SKIPMAP_REG, 0xffffffff); - reg_write32(hcd->regs, HC_BUFFER_STATUS_REG, - ATL_BUF_FILL | INT_BUF_FILL); + ptd_atl_int = 0x80000000; + ptd_iso = 0x00000001; + + isp1760_hcd_write(hcd, HC_ATL_PTD_LASTPTD, ptd_atl_int); + isp1760_hcd_write(hcd, HC_INT_PTD_LASTPTD, ptd_atl_int); + isp1760_hcd_write(hcd, HC_ISO_PTD_LASTPTD, ptd_iso); + + isp1760_hcd_set(hcd, HC_ATL_PTD_SKIPMAP); + isp1760_hcd_set(hcd, HC_INT_PTD_SKIPMAP); + isp1760_hcd_set(hcd, HC_ISO_PTD_SKIPMAP); + + isp1760_hcd_set(hcd, ATL_BUF_FILL); + isp1760_hcd_set(hcd, INT_BUF_FILL); /* GRR this is run-once init(), being done every time the HC starts. * So long as they're part of class devices, we can't do it init() @@ -1363,8 +1747,6 @@ static int qtd_fill(struct isp1760_qtd *qtd, void *databuffer, size_t len) { qtd->data_buffer = databuffer; - if (len > MAX_PAYLOAD_SIZE) - len = MAX_PAYLOAD_SIZE; qtd->length = len; return qtd->length; @@ -1388,6 +1770,8 @@ static void qtd_list_free(struct list_head *qtd_list) static void packetize_urb(struct usb_hcd *hcd, struct urb *urb, struct list_head *head, gfp_t flags) { + struct isp1760_hcd *priv = hcd_to_priv(hcd); + const struct isp1760_memory_layout *mem = priv->memory_layout; struct isp1760_qtd *qtd; void *buf; int len, maxpacketsize; @@ -1440,6 +1824,10 @@ static void packetize_urb(struct usb_hcd *hcd, qtd = qtd_alloc(flags, urb, packet_type); if (!qtd) goto cleanup; + + if (len > mem->blocks_size[ISP176x_BLOCK_NUM - 1]) + len = mem->blocks_size[ISP176x_BLOCK_NUM - 1]; + this_qtd_len = qtd_fill(qtd, buf, len); list_add_tail(&qtd->qtd_list, head); @@ -1584,15 +1972,16 @@ static void kill_transfer(struct usb_hcd *hcd, struct urb *urb, /* We need to forcefully reclaim the slot since some transfers never return, e.g. interrupt transfers and NAKed bulk transfers. */ if (usb_pipecontrol(urb->pipe) || usb_pipebulk(urb->pipe)) { - skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG); + skip_map = isp1760_hcd_read(hcd, HC_ATL_PTD_SKIPMAP); skip_map |= (1 << qh->slot); - reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, skip_map); + isp1760_hcd_write(hcd, HC_ATL_PTD_SKIPMAP, skip_map); + ndelay(100); priv->atl_slots[qh->slot].qh = NULL; priv->atl_slots[qh->slot].qtd = NULL; } else { - skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG); + skip_map = isp1760_hcd_read(hcd, HC_INT_PTD_SKIPMAP); skip_map |= (1 << qh->slot); - reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, skip_map); + isp1760_hcd_write(hcd, HC_INT_PTD_SKIPMAP, skip_map); priv->int_slots[qh->slot].qh = NULL; priv->int_slots[qh->slot].qtd = NULL; } @@ -1705,8 +2094,7 @@ out: static int isp1760_hub_status_data(struct usb_hcd *hcd, char *buf) { struct isp1760_hcd *priv = hcd_to_priv(hcd); - u32 temp, status = 0; - u32 mask; + u32 status = 0; int retval = 1; unsigned long flags; @@ -1716,17 +2104,13 @@ static int isp1760_hub_status_data(struct usb_hcd *hcd, char *buf) /* init status to no-changes */ buf[0] = 0; - mask = PORT_CSC; spin_lock_irqsave(&priv->lock, flags); - temp = reg_read32(hcd->regs, HC_PORTSC1); - if (temp & PORT_OWNER) { - if (temp & PORT_CSC) { - temp &= ~PORT_CSC; - reg_write32(hcd->regs, HC_PORTSC1, temp); - goto done; - } + if (isp1760_hcd_is_set(hcd, PORT_OWNER) && + isp1760_hcd_is_set(hcd, PORT_CSC)) { + isp1760_hcd_clear(hcd, PORT_CSC); + goto done; } /* @@ -1735,11 +2119,9 @@ static int isp1760_hub_status_data(struct usb_hcd *hcd, char *buf) * high-speed device is switched over to the companion * controller by the user. */ - - if ((temp & mask) != 0 - || ((temp & PORT_RESUME) != 0 - && time_after_eq(jiffies, - priv->reset_done))) { + if (isp1760_hcd_is_set(hcd, PORT_CSC) || + (isp1760_hcd_is_set(hcd, PORT_RESUME) && + time_after_eq(jiffies, priv->reset_done))) { buf [0] |= 1 << (0 + 1); status = STS_PCD; } @@ -1752,9 +2134,11 @@ done: static void isp1760_hub_descriptor(struct isp1760_hcd *priv, struct usb_hub_descriptor *desc) { - int ports = HCS_N_PORTS(priv->hcs_params); + int ports; u16 temp; + ports = isp1760_hcd_n_ports(priv->hcd); + desc->bDescriptorType = USB_DT_HUB; /* priv 1.0, 2.3.9 says 20ms max */ desc->bPwrOn2PwrGood = 10; @@ -1770,7 +2154,7 @@ static void isp1760_hub_descriptor(struct isp1760_hcd *priv, /* per-port overcurrent reporting */ temp = HUB_CHAR_INDV_PORT_OCPM; - if (HCS_PPC(priv->hcs_params)) + if (isp1760_hcd_ppc_is_set(priv->hcd)) /* per-port power control */ temp |= HUB_CHAR_INDV_PORT_LPSM; else @@ -1781,38 +2165,37 @@ static void isp1760_hub_descriptor(struct isp1760_hcd *priv, #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) -static int check_reset_complete(struct usb_hcd *hcd, int index, - int port_status) +static void check_reset_complete(struct usb_hcd *hcd, int index) { - if (!(port_status & PORT_CONNECT)) - return port_status; + if (!(isp1760_hcd_is_set(hcd, PORT_CONNECT))) + return; /* if reset finished and it's still not enabled -- handoff */ - if (!(port_status & PORT_PE)) { - + if (!isp1760_hcd_is_set(hcd, PORT_PE)) { dev_info(hcd->self.controller, - "port %d full speed --> companion\n", - index + 1); + "port %d full speed --> companion\n", index + 1); - port_status |= PORT_OWNER; - port_status &= ~PORT_RWC_BITS; - reg_write32(hcd->regs, HC_PORTSC1, port_status); + isp1760_hcd_set(hcd, PORT_OWNER); - } else + isp1760_hcd_clear(hcd, PORT_CSC); + } else { dev_info(hcd->self.controller, "port %d high speed\n", - index + 1); + index + 1); + } - return port_status; + return; } static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { struct isp1760_hcd *priv = hcd_to_priv(hcd); - int ports = HCS_N_PORTS(priv->hcs_params); - u32 temp, status; + u32 status; unsigned long flags; int retval = 0; + int ports; + + ports = isp1760_hcd_n_ports(hcd); /* * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR. @@ -1837,7 +2220,6 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq, if (!wIndex || wIndex > ports) goto error; wIndex--; - temp = reg_read32(hcd->regs, HC_PORTSC1); /* * Even if OWNER is set, so the port is owned by the @@ -1848,22 +2230,22 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq, switch (wValue) { case USB_PORT_FEAT_ENABLE: - reg_write32(hcd->regs, HC_PORTSC1, temp & ~PORT_PE); + isp1760_hcd_clear(hcd, PORT_PE); break; case USB_PORT_FEAT_C_ENABLE: /* XXX error? */ break; case USB_PORT_FEAT_SUSPEND: - if (temp & PORT_RESET) + if (isp1760_hcd_is_set(hcd, PORT_RESET)) goto error; - if (temp & PORT_SUSPEND) { - if ((temp & PORT_PE) == 0) + if (isp1760_hcd_is_set(hcd, PORT_SUSPEND)) { + if (!isp1760_hcd_is_set(hcd, PORT_PE)) goto error; /* resume signaling for 20 msec */ - temp &= ~(PORT_RWC_BITS); - reg_write32(hcd->regs, HC_PORTSC1, - temp | PORT_RESUME); + isp1760_hcd_clear(hcd, PORT_CSC); + isp1760_hcd_set(hcd, PORT_RESUME); + priv->reset_done = jiffies + msecs_to_jiffies(USB_RESUME_TIMEOUT); } @@ -1872,12 +2254,11 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq, /* we auto-clear this feature */ break; case USB_PORT_FEAT_POWER: - if (HCS_PPC(priv->hcs_params)) - reg_write32(hcd->regs, HC_PORTSC1, - temp & ~PORT_POWER); + if (isp1760_hcd_ppc_is_set(hcd)) + isp1760_hcd_clear(hcd, PORT_POWER); break; case USB_PORT_FEAT_C_CONNECTION: - reg_write32(hcd->regs, HC_PORTSC1, temp | PORT_CSC); + isp1760_hcd_set(hcd, PORT_CSC); break; case USB_PORT_FEAT_C_OVER_CURRENT: /* XXX error ?*/ @@ -1888,7 +2269,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq, default: goto error; } - reg_read32(hcd->regs, HC_USBCMD); + isp1760_hcd_read(hcd, CMD_RUN); break; case GetHubDescriptor: isp1760_hub_descriptor(priv, (struct usb_hub_descriptor *) @@ -1903,15 +2284,13 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq, goto error; wIndex--; status = 0; - temp = reg_read32(hcd->regs, HC_PORTSC1); /* wPortChange bits */ - if (temp & PORT_CSC) + if (isp1760_hcd_is_set(hcd, PORT_CSC)) status |= USB_PORT_STAT_C_CONNECTION << 16; - /* whoever resumes must GetPortStatus to complete it!! */ - if (temp & PORT_RESUME) { + if (isp1760_hcd_is_set(hcd, PORT_RESUME)) { dev_err(hcd->self.controller, "Port resume should be skipped.\n"); /* Remote Wakeup received? */ @@ -1930,44 +2309,39 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq, priv->reset_done = 0; /* stop resume signaling */ - temp = reg_read32(hcd->regs, HC_PORTSC1); - reg_write32(hcd->regs, HC_PORTSC1, - temp & ~(PORT_RWC_BITS | PORT_RESUME)); - retval = handshake(hcd, HC_PORTSC1, - PORT_RESUME, 0, 2000 /* 2msec */); + isp1760_hcd_clear(hcd, PORT_CSC); + + retval = isp1760_hcd_clear_and_wait(hcd, + PORT_RESUME, 2000); if (retval != 0) { dev_err(hcd->self.controller, "port %d resume error %d\n", wIndex + 1, retval); goto error; } - temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10)); } } /* whoever resets must GetPortStatus to complete it!! */ - if ((temp & PORT_RESET) - && time_after_eq(jiffies, - priv->reset_done)) { + if (isp1760_hcd_is_set(hcd, PORT_RESET) && + time_after_eq(jiffies, priv->reset_done)) { status |= USB_PORT_STAT_C_RESET << 16; priv->reset_done = 0; /* force reset to complete */ - reg_write32(hcd->regs, HC_PORTSC1, temp & ~PORT_RESET); /* REVISIT: some hardware needs 550+ usec to clear * this bit; seems too long to spin routinely... */ - retval = handshake(hcd, HC_PORTSC1, - PORT_RESET, 0, 750); + retval = isp1760_hcd_clear_and_wait(hcd, PORT_RESET, + 750); if (retval != 0) { dev_err(hcd->self.controller, "port %d reset error %d\n", - wIndex + 1, retval); + wIndex + 1, retval); goto error; } /* see what we found out */ - temp = check_reset_complete(hcd, wIndex, - reg_read32(hcd->regs, HC_PORTSC1)); + check_reset_complete(hcd, wIndex); } /* * Even if OWNER is set, there's no harm letting hub_wq @@ -1975,21 +2349,22 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq, * for PORT_POWER anyway). */ - if (temp & PORT_OWNER) + if (isp1760_hcd_is_set(hcd, PORT_OWNER)) dev_err(hcd->self.controller, "PORT_OWNER is set\n"); - if (temp & PORT_CONNECT) { + if (isp1760_hcd_is_set(hcd, PORT_CONNECT)) { status |= USB_PORT_STAT_CONNECTION; /* status may be from integrated TT */ status |= USB_PORT_STAT_HIGH_SPEED; } - if (temp & PORT_PE) + if (isp1760_hcd_is_set(hcd, PORT_PE)) status |= USB_PORT_STAT_ENABLE; - if (temp & (PORT_SUSPEND|PORT_RESUME)) + if (isp1760_hcd_is_set(hcd, PORT_SUSPEND) && + isp1760_hcd_is_set(hcd, PORT_RESUME)) status |= USB_PORT_STAT_SUSPEND; - if (temp & PORT_RESET) + if (isp1760_hcd_is_set(hcd, PORT_RESET)) status |= USB_PORT_STAT_RESET; - if (temp & PORT_POWER) + if (isp1760_hcd_is_set(hcd, PORT_POWER)) status |= USB_PORT_STAT_POWER; put_unaligned(cpu_to_le32(status), (__le32 *) buf); @@ -2009,41 +2384,40 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq, if (!wIndex || wIndex > ports) goto error; wIndex--; - temp = reg_read32(hcd->regs, HC_PORTSC1); - if (temp & PORT_OWNER) + + if (isp1760_hcd_is_set(hcd, PORT_OWNER)) break; -/* temp &= ~PORT_RWC_BITS; */ switch (wValue) { case USB_PORT_FEAT_ENABLE: - reg_write32(hcd->regs, HC_PORTSC1, temp | PORT_PE); + isp1760_hcd_set(hcd, PORT_PE); break; case USB_PORT_FEAT_SUSPEND: - if ((temp & PORT_PE) == 0 - || (temp & PORT_RESET) != 0) + if (!isp1760_hcd_is_set(hcd, PORT_PE) || + isp1760_hcd_is_set(hcd, PORT_RESET)) goto error; - reg_write32(hcd->regs, HC_PORTSC1, temp | PORT_SUSPEND); + isp1760_hcd_set(hcd, PORT_SUSPEND); break; case USB_PORT_FEAT_POWER: - if (HCS_PPC(priv->hcs_params)) - reg_write32(hcd->regs, HC_PORTSC1, - temp | PORT_POWER); + if (isp1760_hcd_ppc_is_set(hcd)) + isp1760_hcd_set(hcd, PORT_POWER); break; case USB_PORT_FEAT_RESET: - if (temp & PORT_RESUME) + if (isp1760_hcd_is_set(hcd, PORT_RESUME)) goto error; /* line status bits may report this as low speed, * which can be fine if this root hub has a * transaction translator built in. */ - if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT - && PORT_USB11(temp)) { - temp |= PORT_OWNER; + if ((isp1760_hcd_is_set(hcd, PORT_CONNECT) && + !isp1760_hcd_is_set(hcd, PORT_PE)) && + (isp1760_hcd_read(hcd, PORT_LSTATUS) == 1)) { + isp1760_hcd_set(hcd, PORT_OWNER); } else { - temp |= PORT_RESET; - temp &= ~PORT_PE; + isp1760_hcd_set(hcd, PORT_RESET); + isp1760_hcd_clear(hcd, PORT_PE); /* * caller must wait, then call GetPortStatus @@ -2052,12 +2426,10 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq, priv->reset_done = jiffies + msecs_to_jiffies(50); } - reg_write32(hcd->regs, HC_PORTSC1, temp); break; default: goto error; } - reg_read32(hcd->regs, HC_USBCMD); break; default: @@ -2074,14 +2446,13 @@ static int isp1760_get_frame(struct usb_hcd *hcd) struct isp1760_hcd *priv = hcd_to_priv(hcd); u32 fr; - fr = reg_read32(hcd->regs, HC_FRINDEX); + fr = isp1760_hcd_read(hcd, HC_FRINDEX); return (fr >> 3) % priv->periodic_size; } static void isp1760_stop(struct usb_hcd *hcd) { struct isp1760_hcd *priv = hcd_to_priv(hcd); - u32 temp; del_timer(&errata2_timer); @@ -2092,24 +2463,19 @@ static void isp1760_stop(struct usb_hcd *hcd) spin_lock_irq(&priv->lock); ehci_reset(hcd); /* Disable IRQ */ - temp = reg_read32(hcd->regs, HC_HW_MODE_CTRL); - reg_write32(hcd->regs, HC_HW_MODE_CTRL, temp &= ~HW_GLOBAL_INTR_EN); + isp1760_hcd_clear(hcd, HW_GLOBAL_INTR_EN); spin_unlock_irq(&priv->lock); - reg_write32(hcd->regs, HC_CONFIGFLAG, 0); + isp1760_hcd_clear(hcd, FLAG_CF); } static void isp1760_shutdown(struct usb_hcd *hcd) { - u32 command, temp; - isp1760_stop(hcd); - temp = reg_read32(hcd->regs, HC_HW_MODE_CTRL); - reg_write32(hcd->regs, HC_HW_MODE_CTRL, temp &= ~HW_GLOBAL_INTR_EN); - command = reg_read32(hcd->regs, HC_USBCMD); - command &= ~CMD_RUN; - reg_write32(hcd->regs, HC_USBCMD, command); + isp1760_hcd_clear(hcd, HW_GLOBAL_INTR_EN); + + isp1760_hcd_clear(hcd, CMD_RUN); } static void isp1760_clear_tt_buffer_complete(struct usb_hcd *hcd, @@ -2182,10 +2548,11 @@ void isp1760_deinit_kmem_cache(void) kmem_cache_destroy(urb_listitem_cachep); } -int isp1760_hcd_register(struct isp1760_hcd *priv, void __iomem *regs, - struct resource *mem, int irq, unsigned long irqflags, +int isp1760_hcd_register(struct isp1760_hcd *priv, struct resource *mem, + int irq, unsigned long irqflags, struct device *dev) { + const struct isp1760_memory_layout *mem_layout = priv->memory_layout; struct usb_hcd *hcd; int ret; @@ -2197,10 +2564,23 @@ int isp1760_hcd_register(struct isp1760_hcd *priv, void __iomem *regs, priv->hcd = hcd; + priv->atl_slots = kcalloc(mem_layout->slot_num, + sizeof(struct isp1760_slotinfo), GFP_KERNEL); + if (!priv->atl_slots) { + ret = -ENOMEM; + goto put_hcd; + } + + priv->int_slots = kcalloc(mem_layout->slot_num, + sizeof(struct isp1760_slotinfo), GFP_KERNEL); + if (!priv->int_slots) { + ret = -ENOMEM; + goto free_atl_slots; + } + init_memory(priv); hcd->irq = irq; - hcd->regs = regs; hcd->rsrc_start = mem->start; hcd->rsrc_len = resource_size(mem); @@ -2209,13 +2589,17 @@ int isp1760_hcd_register(struct isp1760_hcd *priv, void __iomem *regs, ret = usb_add_hcd(hcd, irq, irqflags); if (ret) - goto error; + goto free_int_slots; device_wakeup_enable(hcd->self.controller); return 0; -error: +free_int_slots: + kfree(priv->int_slots); +free_atl_slots: + kfree(priv->atl_slots); +put_hcd: usb_put_hcd(hcd); return ret; } @@ -2227,4 +2611,6 @@ void isp1760_hcd_unregister(struct isp1760_hcd *priv) usb_remove_hcd(priv->hcd); usb_put_hcd(priv->hcd); + kfree(priv->atl_slots); + kfree(priv->int_slots); } diff --git a/drivers/usb/isp1760/isp1760-hcd.h b/drivers/usb/isp1760/isp1760-hcd.h index f1bb2deb1ccf..ee3063a34de3 100644 --- a/drivers/usb/isp1760/isp1760-hcd.h +++ b/drivers/usb/isp1760/isp1760-hcd.h @@ -3,30 +3,15 @@ #define _ISP1760_HCD_H_ #include <linux/spinlock.h> +#include <linux/regmap.h> + +#include "isp1760-regs.h" struct isp1760_qh; struct isp1760_qtd; struct resource; struct usb_hcd; -/* - * 60kb divided in: - * - 32 blocks @ 256 bytes - * - 20 blocks @ 1024 bytes - * - 4 blocks @ 8192 bytes - */ - -#define BLOCK_1_NUM 32 -#define BLOCK_2_NUM 20 -#define BLOCK_3_NUM 4 - -#define BLOCK_1_SIZE 256 -#define BLOCK_2_SIZE 1024 -#define BLOCK_3_SIZE 8192 -#define BLOCKS (BLOCK_1_NUM + BLOCK_2_NUM + BLOCK_3_NUM) -#define MAX_PAYLOAD_SIZE BLOCK_3_SIZE -#define PAYLOAD_AREA_SIZE 0xf000 - struct isp1760_slotinfo { struct isp1760_qh *qh; struct isp1760_qtd *qtd; @@ -34,6 +19,18 @@ struct isp1760_slotinfo { }; /* chip memory management */ +#define ISP176x_BLOCK_MAX (32 + 20 + 4) +#define ISP176x_BLOCK_NUM 3 + +struct isp1760_memory_layout { + unsigned int blocks[ISP176x_BLOCK_NUM]; + unsigned int blocks_size[ISP176x_BLOCK_NUM]; + + unsigned int slot_num; + unsigned int payload_blocks; + unsigned int payload_area_size; +}; + struct isp1760_memory_chunk { unsigned int start; unsigned int size; @@ -48,16 +45,22 @@ enum isp1760_queue_head_types { }; struct isp1760_hcd { -#ifdef CONFIG_USB_ISP1760_HCD struct usb_hcd *hcd; - u32 hcs_params; + void __iomem *base; + + struct regmap *regs; + struct regmap_field *fields[HC_FIELD_MAX]; + + bool is_isp1763; + const struct isp1760_memory_layout *memory_layout; + spinlock_t lock; - struct isp1760_slotinfo atl_slots[32]; + struct isp1760_slotinfo *atl_slots; int atl_done_map; - struct isp1760_slotinfo int_slots[32]; + struct isp1760_slotinfo *int_slots; int int_done_map; - struct isp1760_memory_chunk memory_pool[BLOCKS]; + struct isp1760_memory_chunk memory_pool[ISP176x_BLOCK_MAX]; struct list_head qh_list[QH_END]; /* periodic schedule support */ @@ -66,20 +69,18 @@ struct isp1760_hcd { unsigned i_thresh; unsigned long reset_done; unsigned long next_statechange; -#endif }; #ifdef CONFIG_USB_ISP1760_HCD -int isp1760_hcd_register(struct isp1760_hcd *priv, void __iomem *regs, - struct resource *mem, int irq, unsigned long irqflags, - struct device *dev); +int isp1760_hcd_register(struct isp1760_hcd *priv, struct resource *mem, + int irq, unsigned long irqflags, struct device *dev); void isp1760_hcd_unregister(struct isp1760_hcd *priv); int isp1760_init_kmem_once(void); void isp1760_deinit_kmem_cache(void); #else static inline int isp1760_hcd_register(struct isp1760_hcd *priv, - void __iomem *regs, struct resource *mem, + struct resource *mem, int irq, unsigned long irqflags, struct device *dev) { diff --git a/drivers/usb/isp1760/isp1760-if.c b/drivers/usb/isp1760/isp1760-if.c index ccd30f835888..7cc349c0b2ad 100644 --- a/drivers/usb/isp1760/isp1760-if.c +++ b/drivers/usb/isp1760/isp1760-if.c @@ -7,6 +7,7 @@ * - PDEV (generic platform device centralized driver model) * * (c) 2007 Sebastian Siewior <bigeasy@linutronix.de> + * Copyright 2021 Linaro, Rui Miguel Silva <rui.silva@linaro.org> * */ @@ -16,8 +17,8 @@ #include <linux/of.h> #include <linux/platform_device.h> #include <linux/slab.h> -#include <linux/usb/isp1760.h> #include <linux/usb/hcd.h> +#include <linux/usb/otg.h> #include "isp1760-core.h" #include "isp1760-regs.h" @@ -75,9 +76,9 @@ static int isp1761_pci_init(struct pci_dev *dev) /*by default host is in 16bit mode, so * io operations at this stage must be 16 bit * */ - writel(0xface, iobase + HC_SCRATCH_REG); + writel(0xface, iobase + ISP176x_HC_SCRATCH); udelay(100); - reg_data = readl(iobase + HC_SCRATCH_REG) & 0x0000ffff; + reg_data = readl(iobase + ISP176x_HC_SCRATCH) & 0x0000ffff; retry_count--; } @@ -209,13 +210,21 @@ static int isp1760_plat_probe(struct platform_device *pdev) if (of_device_is_compatible(dp, "nxp,usb-isp1761")) devflags |= ISP1760_FLAG_ISP1761; - /* Some systems wire up only 16 of the 32 data lines */ + if (of_device_is_compatible(dp, "nxp,usb-isp1763")) + devflags |= ISP1760_FLAG_ISP1763; + + /* + * Some systems wire up only 8 of 16 data lines or + * 16 of the 32 data lines + */ of_property_read_u32(dp, "bus-width", &bus_width); if (bus_width == 16) devflags |= ISP1760_FLAG_BUS_WIDTH_16; + else if (bus_width == 8) + devflags |= ISP1760_FLAG_BUS_WIDTH_8; - if (of_property_read_bool(dp, "port1-otg")) - devflags |= ISP1760_FLAG_OTG_EN; + if (usb_get_dr_mode(&pdev->dev) == USB_DR_MODE_PERIPHERAL) + devflags |= ISP1760_FLAG_PERIPHERAL_EN; if (of_property_read_bool(dp, "analog-oc")) devflags |= ISP1760_FLAG_ANALOG_OC; @@ -225,22 +234,9 @@ static int isp1760_plat_probe(struct platform_device *pdev) if (of_property_read_bool(dp, "dreq-polarity")) devflags |= ISP1760_FLAG_DREQ_POL_HIGH; - } else if (dev_get_platdata(&pdev->dev)) { - struct isp1760_platform_data *pdata = - dev_get_platdata(&pdev->dev); - - if (pdata->is_isp1761) - devflags |= ISP1760_FLAG_ISP1761; - if (pdata->bus_width_16) - devflags |= ISP1760_FLAG_BUS_WIDTH_16; - if (pdata->port1_otg) - devflags |= ISP1760_FLAG_OTG_EN; - if (pdata->analog_oc) - devflags |= ISP1760_FLAG_ANALOG_OC; - if (pdata->dack_polarity_high) - devflags |= ISP1760_FLAG_DACK_POL_HIGH; - if (pdata->dreq_polarity_high) - devflags |= ISP1760_FLAG_DREQ_POL_HIGH; + } else { + pr_err("isp1760: no platform data\n"); + return -ENXIO; } ret = isp1760_register(mem_res, irq_res->start, irqflags, &pdev->dev, @@ -263,6 +259,7 @@ static int isp1760_plat_remove(struct platform_device *pdev) static const struct of_device_id isp1760_of_match[] = { { .compatible = "nxp,usb-isp1760", }, { .compatible = "nxp,usb-isp1761", }, + { .compatible = "nxp,usb-isp1763", }, { }, }; MODULE_DEVICE_TABLE(of, isp1760_of_match); diff --git a/drivers/usb/isp1760/isp1760-regs.h b/drivers/usb/isp1760/isp1760-regs.h index fedc4f5cded0..94ea60c20b2a 100644 --- a/drivers/usb/isp1760/isp1760-regs.h +++ b/drivers/usb/isp1760/isp1760-regs.h @@ -2,226 +2,291 @@ /* * Driver for the NXP ISP1760 chip * + * Copyright 2021 Linaro, Rui Miguel Silva * Copyright 2014 Laurent Pinchart * Copyright 2007 Sebastian Siewior * * Contacts: * Sebastian Siewior <bigeasy@linutronix.de> * Laurent Pinchart <laurent.pinchart@ideasonboard.com> + * Rui Miguel Silva <rui.silva@linaro.org> */ -#ifndef _ISP1760_REGS_H_ -#define _ISP1760_REGS_H_ +#ifndef _ISP176x_REGS_H_ +#define _ISP176x_REGS_H_ /* ----------------------------------------------------------------------------- * Host Controller */ +/* ISP1760/31 */ /* EHCI capability registers */ -#define HC_CAPLENGTH 0x000 -#define HC_LENGTH(p) (((p) >> 00) & 0x00ff) /* bits 7:0 */ -#define HC_VERSION(p) (((p) >> 16) & 0xffff) /* bits 31:16 */ +#define ISP176x_HC_VERSION 0x002 +#define ISP176x_HC_HCSPARAMS 0x004 +#define ISP176x_HC_HCCPARAMS 0x008 -#define HC_HCSPARAMS 0x004 -#define HCS_INDICATOR(p) ((p) & (1 << 16)) /* true: has port indicators */ -#define HCS_PPC(p) ((p) & (1 << 4)) /* true: port power control */ -#define HCS_N_PORTS(p) (((p) >> 0) & 0xf) /* bits 3:0, ports on HC */ +/* EHCI operational registers */ +#define ISP176x_HC_USBCMD 0x020 +#define ISP176x_HC_USBSTS 0x024 +#define ISP176x_HC_FRINDEX 0x02c + +#define ISP176x_HC_CONFIGFLAG 0x060 +#define ISP176x_HC_PORTSC1 0x064 + +#define ISP176x_HC_ISO_PTD_DONEMAP 0x130 +#define ISP176x_HC_ISO_PTD_SKIPMAP 0x134 +#define ISP176x_HC_ISO_PTD_LASTPTD 0x138 +#define ISP176x_HC_INT_PTD_DONEMAP 0x140 +#define ISP176x_HC_INT_PTD_SKIPMAP 0x144 +#define ISP176x_HC_INT_PTD_LASTPTD 0x148 +#define ISP176x_HC_ATL_PTD_DONEMAP 0x150 +#define ISP176x_HC_ATL_PTD_SKIPMAP 0x154 +#define ISP176x_HC_ATL_PTD_LASTPTD 0x158 -#define HC_HCCPARAMS 0x008 -#define HCC_ISOC_CACHE(p) ((p) & (1 << 7)) /* true: can cache isoc frame */ -#define HCC_ISOC_THRES(p) (((p) >> 4) & 0x7) /* bits 6:4, uframes cached */ +/* Configuration Register */ +#define ISP176x_HC_HW_MODE_CTRL 0x300 +#define ISP176x_HC_CHIP_ID 0x304 +#define ISP176x_HC_SCRATCH 0x308 +#define ISP176x_HC_RESET 0x30c +#define ISP176x_HC_BUFFER_STATUS 0x334 +#define ISP176x_HC_MEMORY 0x33c +/* Interrupt Register */ +#define ISP176x_HC_INTERRUPT 0x310 +#define ISP176x_HC_INTERRUPT_ENABLE 0x314 +#define ISP176x_HC_ISO_IRQ_MASK_OR 0x318 +#define ISP176x_HC_INT_IRQ_MASK_OR 0x31c +#define ISP176x_HC_ATL_IRQ_MASK_OR 0x320 +#define ISP176x_HC_ISO_IRQ_MASK_AND 0x324 +#define ISP176x_HC_INT_IRQ_MASK_AND 0x328 +#define ISP176x_HC_ATL_IRQ_MASK_AND 0x32c + +#define ISP176x_HC_OTG_CTRL_SET 0x374 +#define ISP176x_HC_OTG_CTRL_CLEAR 0x376 + +enum isp176x_host_controller_fields { + /* HC_PORTSC1 */ + PORT_OWNER, PORT_POWER, PORT_LSTATUS, PORT_RESET, PORT_SUSPEND, + PORT_RESUME, PORT_PE, PORT_CSC, PORT_CONNECT, + /* HC_HCSPARAMS */ + HCS_PPC, HCS_N_PORTS, + /* HC_HCCPARAMS */ + HCC_ISOC_CACHE, HCC_ISOC_THRES, + /* HC_USBCMD */ + CMD_LRESET, CMD_RESET, CMD_RUN, + /* HC_USBSTS */ + STS_PCD, + /* HC_FRINDEX */ + HC_FRINDEX, + /* HC_CONFIGFLAG */ + FLAG_CF, + /* ISO/INT/ATL PTD */ + HC_ISO_PTD_DONEMAP, HC_ISO_PTD_SKIPMAP, HC_ISO_PTD_LASTPTD, + HC_INT_PTD_DONEMAP, HC_INT_PTD_SKIPMAP, HC_INT_PTD_LASTPTD, + HC_ATL_PTD_DONEMAP, HC_ATL_PTD_SKIPMAP, HC_ATL_PTD_LASTPTD, + /* HC_HW_MODE_CTRL */ + ALL_ATX_RESET, HW_ANA_DIGI_OC, HW_DEV_DMA, HW_COMN_IRQ, HW_COMN_DMA, + HW_DATA_BUS_WIDTH, HW_DACK_POL_HIGH, HW_DREQ_POL_HIGH, HW_INTR_HIGH_ACT, + HW_INTF_LOCK, HW_INTR_EDGE_TRIG, HW_GLOBAL_INTR_EN, + /* HC_CHIP_ID */ + HC_CHIP_ID_HIGH, HC_CHIP_ID_LOW, HC_CHIP_REV, + /* HC_SCRATCH */ + HC_SCRATCH, + /* HC_RESET */ + SW_RESET_RESET_ATX, SW_RESET_RESET_HC, SW_RESET_RESET_ALL, + /* HC_BUFFER_STATUS */ + ISO_BUF_FILL, INT_BUF_FILL, ATL_BUF_FILL, + /* HC_MEMORY */ + MEM_BANK_SEL, MEM_START_ADDR, + /* HC_DATA */ + HC_DATA, + /* HC_INTERRUPT */ + HC_INTERRUPT, + /* HC_INTERRUPT_ENABLE */ + HC_INT_IRQ_ENABLE, HC_ATL_IRQ_ENABLE, + /* INTERRUPT MASKS */ + HC_ISO_IRQ_MASK_OR, HC_INT_IRQ_MASK_OR, HC_ATL_IRQ_MASK_OR, + HC_ISO_IRQ_MASK_AND, HC_INT_IRQ_MASK_AND, HC_ATL_IRQ_MASK_AND, + /* HW_OTG_CTRL_SET */ + HW_OTG_DISABLE, HW_SW_SEL_HC_DC, HW_VBUS_DRV, HW_SEL_CP_EXT, + HW_DM_PULLDOWN, HW_DP_PULLDOWN, HW_DP_PULLUP, HW_HC_2_DIS, + /* HW_OTG_CTRL_CLR */ + HW_OTG_DISABLE_CLEAR, HW_SW_SEL_HC_DC_CLEAR, HW_VBUS_DRV_CLEAR, + HW_SEL_CP_EXT_CLEAR, HW_DM_PULLDOWN_CLEAR, HW_DP_PULLDOWN_CLEAR, + HW_DP_PULLUP_CLEAR, HW_HC_2_DIS_CLEAR, + /* Last element */ + HC_FIELD_MAX, +}; + +/* ISP1763 */ /* EHCI operational registers */ -#define HC_USBCMD 0x020 -#define CMD_LRESET (1 << 7) /* partial reset (no ports, etc) */ -#define CMD_RESET (1 << 1) /* reset HC not bus */ -#define CMD_RUN (1 << 0) /* start/stop HC */ - -#define HC_USBSTS 0x024 -#define STS_PCD (1 << 2) /* port change detect */ - -#define HC_FRINDEX 0x02c - -#define HC_CONFIGFLAG 0x060 -#define FLAG_CF (1 << 0) /* true: we'll support "high speed" */ - -#define HC_PORTSC1 0x064 -#define PORT_OWNER (1 << 13) /* true: companion hc owns this port */ -#define PORT_POWER (1 << 12) /* true: has power (see PPC) */ -#define PORT_USB11(x) (((x) & (3 << 10)) == (1 << 10)) /* USB 1.1 device */ -#define PORT_RESET (1 << 8) /* reset port */ -#define PORT_SUSPEND (1 << 7) /* suspend port */ -#define PORT_RESUME (1 << 6) /* resume it */ -#define PORT_PE (1 << 2) /* port enable */ -#define PORT_CSC (1 << 1) /* connect status change */ -#define PORT_CONNECT (1 << 0) /* device connected */ -#define PORT_RWC_BITS (PORT_CSC) - -#define HC_ISO_PTD_DONEMAP_REG 0x130 -#define HC_ISO_PTD_SKIPMAP_REG 0x134 -#define HC_ISO_PTD_LASTPTD_REG 0x138 -#define HC_INT_PTD_DONEMAP_REG 0x140 -#define HC_INT_PTD_SKIPMAP_REG 0x144 -#define HC_INT_PTD_LASTPTD_REG 0x148 -#define HC_ATL_PTD_DONEMAP_REG 0x150 -#define HC_ATL_PTD_SKIPMAP_REG 0x154 -#define HC_ATL_PTD_LASTPTD_REG 0x158 +#define ISP1763_HC_USBCMD 0x8c +#define ISP1763_HC_USBSTS 0x90 +#define ISP1763_HC_FRINDEX 0x98 + +#define ISP1763_HC_CONFIGFLAG 0x9c +#define ISP1763_HC_PORTSC1 0xa0 + +#define ISP1763_HC_ISO_PTD_DONEMAP 0xa4 +#define ISP1763_HC_ISO_PTD_SKIPMAP 0xa6 +#define ISP1763_HC_ISO_PTD_LASTPTD 0xa8 +#define ISP1763_HC_INT_PTD_DONEMAP 0xaa +#define ISP1763_HC_INT_PTD_SKIPMAP 0xac +#define ISP1763_HC_INT_PTD_LASTPTD 0xae +#define ISP1763_HC_ATL_PTD_DONEMAP 0xb0 +#define ISP1763_HC_ATL_PTD_SKIPMAP 0xb2 +#define ISP1763_HC_ATL_PTD_LASTPTD 0xb4 /* Configuration Register */ -#define HC_HW_MODE_CTRL 0x300 -#define ALL_ATX_RESET (1 << 31) -#define HW_ANA_DIGI_OC (1 << 15) -#define HW_DEV_DMA (1 << 11) -#define HW_COMN_IRQ (1 << 10) -#define HW_COMN_DMA (1 << 9) -#define HW_DATA_BUS_32BIT (1 << 8) -#define HW_DACK_POL_HIGH (1 << 6) -#define HW_DREQ_POL_HIGH (1 << 5) -#define HW_INTR_HIGH_ACT (1 << 2) -#define HW_INTR_EDGE_TRIG (1 << 1) -#define HW_GLOBAL_INTR_EN (1 << 0) - -#define HC_CHIP_ID_REG 0x304 -#define HC_SCRATCH_REG 0x308 - -#define HC_RESET_REG 0x30c -#define SW_RESET_RESET_HC (1 << 1) -#define SW_RESET_RESET_ALL (1 << 0) - -#define HC_BUFFER_STATUS_REG 0x334 -#define ISO_BUF_FILL (1 << 2) -#define INT_BUF_FILL (1 << 1) -#define ATL_BUF_FILL (1 << 0) - -#define HC_MEMORY_REG 0x33c -#define ISP_BANK(x) ((x) << 16) - -#define HC_PORT1_CTRL 0x374 -#define PORT1_POWER (3 << 3) -#define PORT1_INIT1 (1 << 7) -#define PORT1_INIT2 (1 << 23) -#define HW_OTG_CTRL_SET 0x374 -#define HW_OTG_CTRL_CLR 0x376 -#define HW_OTG_DISABLE (1 << 10) -#define HW_OTG_SE0_EN (1 << 9) -#define HW_BDIS_ACON_EN (1 << 8) -#define HW_SW_SEL_HC_DC (1 << 7) -#define HW_VBUS_CHRG (1 << 6) -#define HW_VBUS_DISCHRG (1 << 5) -#define HW_VBUS_DRV (1 << 4) -#define HW_SEL_CP_EXT (1 << 3) -#define HW_DM_PULLDOWN (1 << 2) -#define HW_DP_PULLDOWN (1 << 1) -#define HW_DP_PULLUP (1 << 0) +#define ISP1763_HC_HW_MODE_CTRL 0xb6 +#define ISP1763_HC_CHIP_REV 0x70 +#define ISP1763_HC_CHIP_ID 0x72 +#define ISP1763_HC_SCRATCH 0x78 +#define ISP1763_HC_RESET 0xb8 +#define ISP1763_HC_BUFFER_STATUS 0xba +#define ISP1763_HC_MEMORY 0xc4 +#define ISP1763_HC_DATA 0xc6 /* Interrupt Register */ -#define HC_INTERRUPT_REG 0x310 - -#define HC_INTERRUPT_ENABLE 0x314 -#define HC_ISO_INT (1 << 9) -#define HC_ATL_INT (1 << 8) -#define HC_INTL_INT (1 << 7) -#define HC_EOT_INT (1 << 3) -#define HC_SOT_INT (1 << 1) -#define INTERRUPT_ENABLE_MASK (HC_INTL_INT | HC_ATL_INT) - -#define HC_ISO_IRQ_MASK_OR_REG 0x318 -#define HC_INT_IRQ_MASK_OR_REG 0x31c -#define HC_ATL_IRQ_MASK_OR_REG 0x320 -#define HC_ISO_IRQ_MASK_AND_REG 0x324 -#define HC_INT_IRQ_MASK_AND_REG 0x328 -#define HC_ATL_IRQ_MASK_AND_REG 0x32c +#define ISP1763_HC_INTERRUPT 0xd4 +#define ISP1763_HC_INTERRUPT_ENABLE 0xd6 +#define ISP1763_HC_ISO_IRQ_MASK_OR 0xd8 +#define ISP1763_HC_INT_IRQ_MASK_OR 0xda +#define ISP1763_HC_ATL_IRQ_MASK_OR 0xdc +#define ISP1763_HC_ISO_IRQ_MASK_AND 0xde +#define ISP1763_HC_INT_IRQ_MASK_AND 0xe0 +#define ISP1763_HC_ATL_IRQ_MASK_AND 0xe2 + +#define ISP1763_HC_OTG_CTRL_SET 0xe4 +#define ISP1763_HC_OTG_CTRL_CLEAR 0xe6 /* ----------------------------------------------------------------------------- * Peripheral Controller */ -/* Initialization Registers */ -#define DC_ADDRESS 0x0200 -#define DC_DEVEN (1 << 7) - -#define DC_MODE 0x020c -#define DC_DMACLKON (1 << 9) -#define DC_VBUSSTAT (1 << 8) -#define DC_CLKAON (1 << 7) -#define DC_SNDRSU (1 << 6) -#define DC_GOSUSP (1 << 5) -#define DC_SFRESET (1 << 4) -#define DC_GLINTENA (1 << 3) -#define DC_WKUPCS (1 << 2) - -#define DC_INTCONF 0x0210 -#define DC_CDBGMOD_ACK_NAK (0 << 6) -#define DC_CDBGMOD_ACK (1 << 6) -#define DC_CDBGMOD_ACK_1NAK (2 << 6) -#define DC_DDBGMODIN_ACK_NAK (0 << 4) -#define DC_DDBGMODIN_ACK (1 << 4) -#define DC_DDBGMODIN_ACK_1NAK (2 << 4) -#define DC_DDBGMODOUT_ACK_NYET_NAK (0 << 2) -#define DC_DDBGMODOUT_ACK_NYET (1 << 2) -#define DC_DDBGMODOUT_ACK_NYET_1NAK (2 << 2) -#define DC_INTLVL (1 << 1) -#define DC_INTPOL (1 << 0) - -#define DC_DEBUG 0x0212 -#define DC_INTENABLE 0x0214 #define DC_IEPTX(n) (1 << (11 + 2 * (n))) #define DC_IEPRX(n) (1 << (10 + 2 * (n))) #define DC_IEPRXTX(n) (3 << (10 + 2 * (n))) -#define DC_IEP0SETUP (1 << 8) -#define DC_IEVBUS (1 << 7) -#define DC_IEDMA (1 << 6) -#define DC_IEHS_STA (1 << 5) -#define DC_IERESM (1 << 4) -#define DC_IESUSP (1 << 3) -#define DC_IEPSOF (1 << 2) -#define DC_IESOF (1 << 1) -#define DC_IEBRST (1 << 0) + +#define ISP176x_DC_CDBGMOD_ACK BIT(6) +#define ISP176x_DC_DDBGMODIN_ACK BIT(4) +#define ISP176x_DC_DDBGMODOUT_ACK BIT(2) + +#define ISP176x_DC_IEP0SETUP BIT(8) +#define ISP176x_DC_IEVBUS BIT(7) +#define ISP176x_DC_IEHS_STA BIT(5) +#define ISP176x_DC_IERESM BIT(4) +#define ISP176x_DC_IESUSP BIT(3) +#define ISP176x_DC_IEBRST BIT(0) + +#define ISP176x_DC_ENDPTYP_ISOC 0x01 +#define ISP176x_DC_ENDPTYP_BULK 0x02 +#define ISP176x_DC_ENDPTYP_INTERRUPT 0x03 + +/* Initialization Registers */ +#define ISP176x_DC_ADDRESS 0x0200 +#define ISP176x_DC_MODE 0x020c +#define ISP176x_DC_INTCONF 0x0210 +#define ISP176x_DC_DEBUG 0x0212 +#define ISP176x_DC_INTENABLE 0x0214 + +/* Data Flow Registers */ +#define ISP176x_DC_EPMAXPKTSZ 0x0204 +#define ISP176x_DC_EPTYPE 0x0208 + +#define ISP176x_DC_BUFLEN 0x021c +#define ISP176x_DC_BUFSTAT 0x021e +#define ISP176x_DC_DATAPORT 0x0220 + +#define ISP176x_DC_CTRLFUNC 0x0228 +#define ISP176x_DC_EPINDEX 0x022c + +/* DMA Registers */ +#define ISP176x_DC_DMACMD 0x0230 +#define ISP176x_DC_DMATXCOUNT 0x0234 +#define ISP176x_DC_DMACONF 0x0238 +#define ISP176x_DC_DMAHW 0x023c +#define ISP176x_DC_DMAINTREASON 0x0250 +#define ISP176x_DC_DMAINTEN 0x0254 +#define ISP176x_DC_DMAEP 0x0258 +#define ISP176x_DC_DMABURSTCOUNT 0x0264 + +/* General Registers */ +#define ISP176x_DC_INTERRUPT 0x0218 +#define ISP176x_DC_CHIPID 0x0270 +#define ISP176x_DC_FRAMENUM 0x0274 +#define ISP176x_DC_SCRATCH 0x0278 +#define ISP176x_DC_UNLOCKDEV 0x027c +#define ISP176x_DC_INTPULSEWIDTH 0x0280 +#define ISP176x_DC_TESTMODE 0x0284 + +enum isp176x_device_controller_fields { + /* DC_ADDRESS */ + DC_DEVEN, DC_DEVADDR, + /* DC_MODE */ + DC_VBUSSTAT, DC_SFRESET, DC_GLINTENA, + /* DC_INTCONF */ + DC_CDBGMOD_ACK, DC_DDBGMODIN_ACK, DC_DDBGMODOUT_ACK, DC_INTPOL, + /* DC_INTENABLE */ + DC_IEPRXTX_7, DC_IEPRXTX_6, DC_IEPRXTX_5, DC_IEPRXTX_4, DC_IEPRXTX_3, + DC_IEPRXTX_2, DC_IEPRXTX_1, DC_IEPRXTX_0, + DC_IEP0SETUP, DC_IEVBUS, DC_IEHS_STA, DC_IERESM, DC_IESUSP, DC_IEBRST, + /* DC_EPINDEX */ + DC_EP0SETUP, DC_ENDPIDX, DC_EPDIR, + /* DC_CTRLFUNC */ + DC_CLBUF, DC_VENDP, DC_DSEN, DC_STATUS, DC_STALL, + /* DC_BUFLEN */ + DC_BUFLEN, + /* DC_EPMAXPKTSZ */ + DC_FFOSZ, + /* DC_EPTYPE */ + DC_EPENABLE, DC_ENDPTYP, + /* DC_FRAMENUM */ + DC_FRAMENUM, DC_UFRAMENUM, + /* DC_CHIP_ID */ + DC_CHIP_ID_HIGH, DC_CHIP_ID_LOW, + /* DC_SCRATCH */ + DC_SCRATCH, + /* Last element */ + DC_FIELD_MAX, +}; + +/* ISP1763 */ +/* Initialization Registers */ +#define ISP1763_DC_ADDRESS 0x00 +#define ISP1763_DC_MODE 0x0c +#define ISP1763_DC_INTCONF 0x10 +#define ISP1763_DC_INTENABLE 0x14 /* Data Flow Registers */ -#define DC_EPINDEX 0x022c -#define DC_EP0SETUP (1 << 5) -#define DC_ENDPIDX(n) ((n) << 1) -#define DC_EPDIR (1 << 0) - -#define DC_CTRLFUNC 0x0228 -#define DC_CLBUF (1 << 4) -#define DC_VENDP (1 << 3) -#define DC_DSEN (1 << 2) -#define DC_STATUS (1 << 1) -#define DC_STALL (1 << 0) - -#define DC_DATAPORT 0x0220 -#define DC_BUFLEN 0x021c -#define DC_DATACOUNT_MASK 0xffff -#define DC_BUFSTAT 0x021e -#define DC_EPMAXPKTSZ 0x0204 - -#define DC_EPTYPE 0x0208 -#define DC_NOEMPKT (1 << 4) -#define DC_EPENABLE (1 << 3) -#define DC_DBLBUF (1 << 2) -#define DC_ENDPTYP_ISOC (1 << 0) -#define DC_ENDPTYP_BULK (2 << 0) -#define DC_ENDPTYP_INTERRUPT (3 << 0) +#define ISP1763_DC_EPMAXPKTSZ 0x04 +#define ISP1763_DC_EPTYPE 0x08 + +#define ISP1763_DC_BUFLEN 0x1c +#define ISP1763_DC_BUFSTAT 0x1e +#define ISP1763_DC_DATAPORT 0x20 + +#define ISP1763_DC_CTRLFUNC 0x28 +#define ISP1763_DC_EPINDEX 0x2c /* DMA Registers */ -#define DC_DMACMD 0x0230 -#define DC_DMATXCOUNT 0x0234 -#define DC_DMACONF 0x0238 -#define DC_DMAHW 0x023c -#define DC_DMAINTREASON 0x0250 -#define DC_DMAINTEN 0x0254 -#define DC_DMAEP 0x0258 -#define DC_DMABURSTCOUNT 0x0264 +#define ISP1763_DC_DMACMD 0x30 +#define ISP1763_DC_DMATXCOUNT 0x34 +#define ISP1763_DC_DMACONF 0x38 +#define ISP1763_DC_DMAHW 0x3c +#define ISP1763_DC_DMAINTREASON 0x50 +#define ISP1763_DC_DMAINTEN 0x54 +#define ISP1763_DC_DMAEP 0x58 +#define ISP1763_DC_DMABURSTCOUNT 0x64 /* General Registers */ -#define DC_INTERRUPT 0x0218 -#define DC_CHIPID 0x0270 -#define DC_FRAMENUM 0x0274 -#define DC_SCRATCH 0x0278 -#define DC_UNLOCKDEV 0x027c -#define DC_INTPULSEWIDTH 0x0280 -#define DC_TESTMODE 0x0284 +#define ISP1763_DC_INTERRUPT 0x18 +#define ISP1763_DC_CHIPID_LOW 0x70 +#define ISP1763_DC_CHIPID_HIGH 0x72 +#define ISP1763_DC_FRAMENUM 0x74 +#define ISP1763_DC_SCRATCH 0x78 +#define ISP1763_DC_UNLOCKDEV 0x7c +#define ISP1763_DC_INTPULSEWIDTH 0x80 +#define ISP1763_DC_TESTMODE 0x84 #endif diff --git a/drivers/usb/isp1760/isp1760-udc.c b/drivers/usb/isp1760/isp1760-udc.c index 1714b2258b54..a78da59d6417 100644 --- a/drivers/usb/isp1760/isp1760-udc.c +++ b/drivers/usb/isp1760/isp1760-udc.c @@ -2,10 +2,12 @@ /* * Driver for the NXP ISP1761 device controller * + * Copyright 2021 Linaro, Rui Miguel Silva * Copyright 2014 Ideas on Board Oy * * Contacts: * Laurent Pinchart <laurent.pinchart@ideasonboard.com> + * Rui Miguel Silva <rui.silva@linaro.org> */ #include <linux/interrupt.h> @@ -45,16 +47,62 @@ static inline struct isp1760_request *req_to_udc_req(struct usb_request *req) return container_of(req, struct isp1760_request, req); } -static inline u32 isp1760_udc_read(struct isp1760_udc *udc, u16 reg) +static u32 isp1760_udc_read(struct isp1760_udc *udc, u16 field) { - return isp1760_read32(udc->regs, reg); + return isp1760_field_read(udc->fields, field); } -static inline void isp1760_udc_write(struct isp1760_udc *udc, u16 reg, u32 val) +static void isp1760_udc_write(struct isp1760_udc *udc, u16 field, u32 val) { - isp1760_write32(udc->regs, reg, val); + isp1760_field_write(udc->fields, field, val); } +static u32 isp1760_udc_read_raw(struct isp1760_udc *udc, u16 reg) +{ + __le32 val; + + regmap_raw_read(udc->regs, reg, &val, 4); + + return le32_to_cpu(val); +} + +static u16 isp1760_udc_read_raw16(struct isp1760_udc *udc, u16 reg) +{ + __le16 val; + + regmap_raw_read(udc->regs, reg, &val, 2); + + return le16_to_cpu(val); +} + +static void isp1760_udc_write_raw(struct isp1760_udc *udc, u16 reg, u32 val) +{ + __le32 val_le = cpu_to_le32(val); + + regmap_raw_write(udc->regs, reg, &val_le, 4); +} + +static void isp1760_udc_write_raw16(struct isp1760_udc *udc, u16 reg, u16 val) +{ + __le16 val_le = cpu_to_le16(val); + + regmap_raw_write(udc->regs, reg, &val_le, 2); +} + +static void isp1760_udc_set(struct isp1760_udc *udc, u32 field) +{ + isp1760_udc_write(udc, field, 0xFFFFFFFF); +} + +static void isp1760_udc_clear(struct isp1760_udc *udc, u32 field) +{ + isp1760_udc_write(udc, field, 0); +} + +static bool isp1760_udc_is_set(struct isp1760_udc *udc, u32 field) +{ + return !!isp1760_udc_read(udc, field); +} /* ----------------------------------------------------------------------------- * Endpoint Management */ @@ -75,16 +123,21 @@ static struct isp1760_ep *isp1760_udc_find_ep(struct isp1760_udc *udc, return NULL; } -static void __isp1760_udc_select_ep(struct isp1760_ep *ep, int dir) +static void __isp1760_udc_select_ep(struct isp1760_udc *udc, + struct isp1760_ep *ep, int dir) { - isp1760_udc_write(ep->udc, DC_EPINDEX, - DC_ENDPIDX(ep->addr & USB_ENDPOINT_NUMBER_MASK) | - (dir == USB_DIR_IN ? DC_EPDIR : 0)); + isp1760_udc_write(udc, DC_ENDPIDX, ep->addr & USB_ENDPOINT_NUMBER_MASK); + + if (dir == USB_DIR_IN) + isp1760_udc_set(udc, DC_EPDIR); + else + isp1760_udc_clear(udc, DC_EPDIR); } /** * isp1760_udc_select_ep - Select an endpoint for register access * @ep: The endpoint + * @udc: Reference to the device controller * * The ISP1761 endpoint registers are banked. This function selects the target * endpoint for banked register access. The selection remains valid until the @@ -93,9 +146,10 @@ static void __isp1760_udc_select_ep(struct isp1760_ep *ep, int dir) * * Called with the UDC spinlock held. */ -static void isp1760_udc_select_ep(struct isp1760_ep *ep) +static void isp1760_udc_select_ep(struct isp1760_udc *udc, + struct isp1760_ep *ep) { - __isp1760_udc_select_ep(ep, ep->addr & USB_ENDPOINT_DIR_MASK); + __isp1760_udc_select_ep(udc, ep, ep->addr & USB_ENDPOINT_DIR_MASK); } /* Called with the UDC spinlock held. */ @@ -108,9 +162,13 @@ static void isp1760_udc_ctrl_send_status(struct isp1760_ep *ep, int dir) * the direction opposite to the data stage data packets, we thus need * to select the OUT/IN endpoint for IN/OUT transfers. */ - isp1760_udc_write(udc, DC_EPINDEX, DC_ENDPIDX(0) | - (dir == USB_DIR_IN ? 0 : DC_EPDIR)); - isp1760_udc_write(udc, DC_CTRLFUNC, DC_STATUS); + if (dir == USB_DIR_IN) + isp1760_udc_clear(udc, DC_EPDIR); + else + isp1760_udc_set(udc, DC_EPDIR); + + isp1760_udc_write(udc, DC_ENDPIDX, 1); + isp1760_udc_set(udc, DC_STATUS); /* * The hardware will terminate the request automatically and go back to @@ -157,10 +215,10 @@ static void isp1760_udc_ctrl_send_stall(struct isp1760_ep *ep) spin_lock_irqsave(&udc->lock, flags); /* Stall both the IN and OUT endpoints. */ - __isp1760_udc_select_ep(ep, USB_DIR_OUT); - isp1760_udc_write(udc, DC_CTRLFUNC, DC_STALL); - __isp1760_udc_select_ep(ep, USB_DIR_IN); - isp1760_udc_write(udc, DC_CTRLFUNC, DC_STALL); + __isp1760_udc_select_ep(udc, ep, USB_DIR_OUT); + isp1760_udc_set(udc, DC_STALL); + __isp1760_udc_select_ep(udc, ep, USB_DIR_IN); + isp1760_udc_set(udc, DC_STALL); /* A protocol stall completes the control transaction. */ udc->ep0_state = ISP1760_CTRL_SETUP; @@ -181,8 +239,8 @@ static bool isp1760_udc_receive(struct isp1760_ep *ep, u32 *buf; int i; - isp1760_udc_select_ep(ep); - len = isp1760_udc_read(udc, DC_BUFLEN) & DC_DATACOUNT_MASK; + isp1760_udc_select_ep(udc, ep); + len = isp1760_udc_read(udc, DC_BUFLEN); dev_dbg(udc->isp->dev, "%s: received %u bytes (%u/%u done)\n", __func__, len, req->req.actual, req->req.length); @@ -198,7 +256,7 @@ static bool isp1760_udc_receive(struct isp1760_ep *ep, * datasheet doesn't clearly document how this should be * handled. */ - isp1760_udc_write(udc, DC_CTRLFUNC, DC_CLBUF); + isp1760_udc_set(udc, DC_CLBUF); return false; } @@ -209,9 +267,9 @@ static bool isp1760_udc_receive(struct isp1760_ep *ep, * the next packet might be removed from the FIFO. */ for (i = len; i > 2; i -= 4, ++buf) - *buf = le32_to_cpu(isp1760_udc_read(udc, DC_DATAPORT)); + *buf = isp1760_udc_read_raw(udc, ISP176x_DC_DATAPORT); if (i > 0) - *(u16 *)buf = le16_to_cpu(readw(udc->regs + DC_DATAPORT)); + *(u16 *)buf = isp1760_udc_read_raw16(udc, ISP176x_DC_DATAPORT); req->req.actual += len; @@ -253,7 +311,7 @@ static void isp1760_udc_transmit(struct isp1760_ep *ep, __func__, req->packet_size, req->req.actual, req->req.length); - __isp1760_udc_select_ep(ep, USB_DIR_IN); + __isp1760_udc_select_ep(udc, ep, USB_DIR_IN); if (req->packet_size) isp1760_udc_write(udc, DC_BUFLEN, req->packet_size); @@ -265,14 +323,14 @@ static void isp1760_udc_transmit(struct isp1760_ep *ep, * the FIFO for this kind of conditions, but doesn't seem to work. */ for (i = req->packet_size; i > 2; i -= 4, ++buf) - isp1760_udc_write(udc, DC_DATAPORT, cpu_to_le32(*buf)); + isp1760_udc_write_raw(udc, ISP176x_DC_DATAPORT, *buf); if (i > 0) - writew(cpu_to_le16(*(u16 *)buf), udc->regs + DC_DATAPORT); + isp1760_udc_write_raw16(udc, ISP176x_DC_DATAPORT, *(u16 *)buf); if (ep->addr == 0) - isp1760_udc_write(udc, DC_CTRLFUNC, DC_DSEN); + isp1760_udc_set(udc, DC_DSEN); if (!req->packet_size) - isp1760_udc_write(udc, DC_CTRLFUNC, DC_VENDP); + isp1760_udc_set(udc, DC_VENDP); } static void isp1760_ep_rx_ready(struct isp1760_ep *ep) @@ -408,19 +466,24 @@ static int __isp1760_udc_set_halt(struct isp1760_ep *ep, bool halt) return -EINVAL; } - isp1760_udc_select_ep(ep); - isp1760_udc_write(udc, DC_CTRLFUNC, halt ? DC_STALL : 0); + isp1760_udc_select_ep(udc, ep); + + if (halt) + isp1760_udc_set(udc, DC_STALL); + else + isp1760_udc_clear(udc, DC_STALL); if (ep->addr == 0) { /* When halting the control endpoint, stall both IN and OUT. */ - __isp1760_udc_select_ep(ep, USB_DIR_IN); - isp1760_udc_write(udc, DC_CTRLFUNC, halt ? DC_STALL : 0); + __isp1760_udc_select_ep(udc, ep, USB_DIR_IN); + if (halt) + isp1760_udc_set(udc, DC_STALL); + else + isp1760_udc_clear(udc, DC_STALL); } else if (!halt) { /* Reset the data PID by cycling the endpoint enable bit. */ - u16 eptype = isp1760_udc_read(udc, DC_EPTYPE); - - isp1760_udc_write(udc, DC_EPTYPE, eptype & ~DC_EPENABLE); - isp1760_udc_write(udc, DC_EPTYPE, eptype); + isp1760_udc_clear(udc, DC_EPENABLE); + isp1760_udc_set(udc, DC_EPENABLE); /* * Disabling the endpoint emptied the transmit FIFO, fill it @@ -479,12 +542,14 @@ static int isp1760_udc_get_status(struct isp1760_udc *udc, return -EINVAL; } - isp1760_udc_write(udc, DC_EPINDEX, DC_ENDPIDX(0) | DC_EPDIR); + isp1760_udc_set(udc, DC_EPDIR); + isp1760_udc_write(udc, DC_ENDPIDX, 1); + isp1760_udc_write(udc, DC_BUFLEN, 2); - writew(cpu_to_le16(status), udc->regs + DC_DATAPORT); + isp1760_udc_write_raw16(udc, ISP176x_DC_DATAPORT, status); - isp1760_udc_write(udc, DC_CTRLFUNC, DC_DSEN); + isp1760_udc_set(udc, DC_DSEN); dev_dbg(udc->isp->dev, "%s: status 0x%04x\n", __func__, status); @@ -508,7 +573,8 @@ static int isp1760_udc_set_address(struct isp1760_udc *udc, u16 addr) usb_gadget_set_state(&udc->gadget, addr ? USB_STATE_ADDRESS : USB_STATE_DEFAULT); - isp1760_udc_write(udc, DC_ADDRESS, DC_DEVEN | addr); + isp1760_udc_write(udc, DC_DEVADDR, addr); + isp1760_udc_set(udc, DC_DEVEN); spin_lock(&udc->lock); isp1760_udc_ctrl_send_status(&udc->ep[0], USB_DIR_OUT); @@ -650,9 +716,9 @@ static void isp1760_ep0_setup(struct isp1760_udc *udc) spin_lock(&udc->lock); - isp1760_udc_write(udc, DC_EPINDEX, DC_EP0SETUP); + isp1760_udc_set(udc, DC_EP0SETUP); - count = isp1760_udc_read(udc, DC_BUFLEN) & DC_DATACOUNT_MASK; + count = isp1760_udc_read(udc, DC_BUFLEN); if (count != sizeof(req)) { spin_unlock(&udc->lock); @@ -663,8 +729,8 @@ static void isp1760_ep0_setup(struct isp1760_udc *udc) return; } - req.data[0] = isp1760_udc_read(udc, DC_DATAPORT); - req.data[1] = isp1760_udc_read(udc, DC_DATAPORT); + req.data[0] = isp1760_udc_read_raw(udc, ISP176x_DC_DATAPORT); + req.data[1] = isp1760_udc_read_raw(udc, ISP176x_DC_DATAPORT); if (udc->ep0_state != ISP1760_CTRL_SETUP) { spin_unlock(&udc->lock); @@ -732,13 +798,13 @@ static int isp1760_ep_enable(struct usb_ep *ep, switch (usb_endpoint_type(desc)) { case USB_ENDPOINT_XFER_ISOC: - type = DC_ENDPTYP_ISOC; + type = ISP176x_DC_ENDPTYP_ISOC; break; case USB_ENDPOINT_XFER_BULK: - type = DC_ENDPTYP_BULK; + type = ISP176x_DC_ENDPTYP_BULK; break; case USB_ENDPOINT_XFER_INT: - type = DC_ENDPTYP_INTERRUPT; + type = ISP176x_DC_ENDPTYP_INTERRUPT; break; case USB_ENDPOINT_XFER_CONTROL: default: @@ -755,10 +821,13 @@ static int isp1760_ep_enable(struct usb_ep *ep, uep->halted = false; uep->wedged = false; - isp1760_udc_select_ep(uep); - isp1760_udc_write(udc, DC_EPMAXPKTSZ, uep->maxpacket); + isp1760_udc_select_ep(udc, uep); + + isp1760_udc_write(udc, DC_FFOSZ, uep->maxpacket); isp1760_udc_write(udc, DC_BUFLEN, uep->maxpacket); - isp1760_udc_write(udc, DC_EPTYPE, DC_EPENABLE | type); + + isp1760_udc_write(udc, DC_ENDPTYP, type); + isp1760_udc_set(udc, DC_EPENABLE); spin_unlock_irqrestore(&udc->lock, flags); @@ -786,8 +855,9 @@ static int isp1760_ep_disable(struct usb_ep *ep) uep->desc = NULL; uep->maxpacket = 0; - isp1760_udc_select_ep(uep); - isp1760_udc_write(udc, DC_EPTYPE, 0); + isp1760_udc_select_ep(udc, uep); + isp1760_udc_clear(udc, DC_EPENABLE); + isp1760_udc_clear(udc, DC_ENDPTYP); /* TODO Synchronize with the IRQ handler */ @@ -864,8 +934,8 @@ static int isp1760_ep_queue(struct usb_ep *ep, struct usb_request *_req, case ISP1760_CTRL_DATA_OUT: list_add_tail(&req->queue, &uep->queue); - __isp1760_udc_select_ep(uep, USB_DIR_OUT); - isp1760_udc_write(udc, DC_CTRLFUNC, DC_DSEN); + __isp1760_udc_select_ep(udc, uep, USB_DIR_OUT); + isp1760_udc_set(udc, DC_DSEN); break; case ISP1760_CTRL_STATUS: @@ -1025,14 +1095,14 @@ static void isp1760_ep_fifo_flush(struct usb_ep *ep) spin_lock_irqsave(&udc->lock, flags); - isp1760_udc_select_ep(uep); + isp1760_udc_select_ep(udc, uep); /* * Set the CLBUF bit twice to flush both buffers in case double * buffering is enabled. */ - isp1760_udc_write(udc, DC_CTRLFUNC, DC_CLBUF); - isp1760_udc_write(udc, DC_CTRLFUNC, DC_CLBUF); + isp1760_udc_set(udc, DC_CLBUF); + isp1760_udc_set(udc, DC_CLBUF); spin_unlock_irqrestore(&udc->lock, flags); } @@ -1082,6 +1152,10 @@ static void isp1760_udc_disconnect(struct isp1760_udc *udc) static void isp1760_udc_init_hw(struct isp1760_udc *udc) { + u32 intconf = udc->is_isp1763 ? ISP1763_DC_INTCONF : ISP176x_DC_INTCONF; + u32 intena = udc->is_isp1763 ? ISP1763_DC_INTENABLE : + ISP176x_DC_INTENABLE; + /* * The device controller currently shares its interrupt with the host * controller, the DC_IRQ polarity and signaling mode are ignored. Set @@ -1091,19 +1165,22 @@ static void isp1760_udc_init_hw(struct isp1760_udc *udc) * ACK tokens only (and NYET for the out pipe). The default * configuration also generates an interrupt on the first NACK token. */ - isp1760_udc_write(udc, DC_INTCONF, DC_CDBGMOD_ACK | DC_DDBGMODIN_ACK | - DC_DDBGMODOUT_ACK_NYET); - - isp1760_udc_write(udc, DC_INTENABLE, DC_IEPRXTX(7) | DC_IEPRXTX(6) | - DC_IEPRXTX(5) | DC_IEPRXTX(4) | DC_IEPRXTX(3) | - DC_IEPRXTX(2) | DC_IEPRXTX(1) | DC_IEPRXTX(0) | - DC_IEP0SETUP | DC_IEVBUS | DC_IERESM | DC_IESUSP | - DC_IEHS_STA | DC_IEBRST); + isp1760_reg_write(udc->regs, intconf, + ISP176x_DC_CDBGMOD_ACK | ISP176x_DC_DDBGMODIN_ACK | + ISP176x_DC_DDBGMODOUT_ACK); + + isp1760_reg_write(udc->regs, intena, DC_IEPRXTX(7) | + DC_IEPRXTX(6) | DC_IEPRXTX(5) | DC_IEPRXTX(4) | + DC_IEPRXTX(3) | DC_IEPRXTX(2) | DC_IEPRXTX(1) | + DC_IEPRXTX(0) | ISP176x_DC_IEP0SETUP | + ISP176x_DC_IEVBUS | ISP176x_DC_IERESM | + ISP176x_DC_IESUSP | ISP176x_DC_IEHS_STA | + ISP176x_DC_IEBRST); if (udc->connected) isp1760_set_pullup(udc->isp, true); - isp1760_udc_write(udc, DC_ADDRESS, DC_DEVEN); + isp1760_udc_set(udc, DC_DEVEN); } static void isp1760_udc_reset(struct isp1760_udc *udc) @@ -1152,7 +1229,7 @@ static int isp1760_udc_get_frame(struct usb_gadget *gadget) { struct isp1760_udc *udc = gadget_to_udc(gadget); - return isp1760_udc_read(udc, DC_FRAMENUM) & ((1 << 11) - 1); + return isp1760_udc_read(udc, DC_FRAMENUM); } static int isp1760_udc_wakeup(struct usb_gadget *gadget) @@ -1219,7 +1296,7 @@ static int isp1760_udc_start(struct usb_gadget *gadget, usb_gadget_set_state(&udc->gadget, USB_STATE_ATTACHED); /* DMA isn't supported yet, don't enable the DMA clock. */ - isp1760_udc_write(udc, DC_MODE, DC_GLINTENA); + isp1760_udc_set(udc, DC_GLINTENA); isp1760_udc_init_hw(udc); @@ -1232,13 +1309,14 @@ static int isp1760_udc_start(struct usb_gadget *gadget, static int isp1760_udc_stop(struct usb_gadget *gadget) { struct isp1760_udc *udc = gadget_to_udc(gadget); + u32 mode_reg = udc->is_isp1763 ? ISP1763_DC_MODE : ISP176x_DC_MODE; unsigned long flags; dev_dbg(udc->isp->dev, "%s\n", __func__); del_timer_sync(&udc->vbus_timer); - isp1760_udc_write(udc, DC_MODE, 0); + isp1760_reg_write(udc->regs, mode_reg, 0); spin_lock_irqsave(&udc->lock, flags); udc->driver = NULL; @@ -1260,15 +1338,30 @@ static const struct usb_gadget_ops isp1760_udc_ops = { * Interrupt Handling */ +static u32 isp1760_udc_irq_get_status(struct isp1760_udc *udc) +{ + u32 status; + + if (udc->is_isp1763) { + status = isp1760_reg_read(udc->regs, ISP1763_DC_INTERRUPT) + & isp1760_reg_read(udc->regs, ISP1763_DC_INTENABLE); + isp1760_reg_write(udc->regs, ISP1763_DC_INTERRUPT, status); + } else { + status = isp1760_reg_read(udc->regs, ISP176x_DC_INTERRUPT) + & isp1760_reg_read(udc->regs, ISP176x_DC_INTENABLE); + isp1760_reg_write(udc->regs, ISP176x_DC_INTERRUPT, status); + } + + return status; +} + static irqreturn_t isp1760_udc_irq(int irq, void *dev) { struct isp1760_udc *udc = dev; unsigned int i; u32 status; - status = isp1760_udc_read(udc, DC_INTERRUPT) - & isp1760_udc_read(udc, DC_INTENABLE); - isp1760_udc_write(udc, DC_INTERRUPT, status); + status = isp1760_udc_irq_get_status(udc); if (status & DC_IEVBUS) { dev_dbg(udc->isp->dev, "%s(VBUS)\n", __func__); @@ -1313,7 +1406,7 @@ static irqreturn_t isp1760_udc_irq(int irq, void *dev) dev_dbg(udc->isp->dev, "%s(SUSP)\n", __func__); spin_lock(&udc->lock); - if (!(isp1760_udc_read(udc, DC_MODE) & DC_VBUSSTAT)) + if (!isp1760_udc_is_set(udc, DC_VBUSSTAT)) isp1760_udc_disconnect(udc); else isp1760_udc_suspend(udc); @@ -1335,7 +1428,7 @@ static void isp1760_udc_vbus_poll(struct timer_list *t) spin_lock_irqsave(&udc->lock, flags); - if (!(isp1760_udc_read(udc, DC_MODE) & DC_VBUSSTAT)) + if (!(isp1760_udc_is_set(udc, DC_VBUSSTAT))) isp1760_udc_disconnect(udc); else if (udc->gadget.state >= USB_STATE_POWERED) mod_timer(&udc->vbus_timer, @@ -1403,6 +1496,7 @@ static void isp1760_udc_init_eps(struct isp1760_udc *udc) static int isp1760_udc_init(struct isp1760_udc *udc) { + u32 mode_reg = udc->is_isp1763 ? ISP1763_DC_MODE : ISP176x_DC_MODE; u16 scratch; u32 chipid; @@ -1413,7 +1507,8 @@ static int isp1760_udc_init(struct isp1760_udc *udc) * and scratch register contents must match the expected values. */ isp1760_udc_write(udc, DC_SCRATCH, 0xbabe); - chipid = isp1760_udc_read(udc, DC_CHIPID); + chipid = isp1760_udc_read(udc, DC_CHIP_ID_HIGH) << 16; + chipid |= isp1760_udc_read(udc, DC_CHIP_ID_LOW); scratch = isp1760_udc_read(udc, DC_SCRATCH); if (scratch != 0xbabe) { @@ -1423,15 +1518,16 @@ static int isp1760_udc_init(struct isp1760_udc *udc) return -ENODEV; } - if (chipid != 0x00011582 && chipid != 0x00158210) { + if (chipid != 0x00011582 && chipid != 0x00158210 && + chipid != 0x00176320) { dev_err(udc->isp->dev, "udc: invalid chip ID 0x%08x\n", chipid); return -ENODEV; } /* Reset the device controller. */ - isp1760_udc_write(udc, DC_MODE, DC_SFRESET); + isp1760_udc_set(udc, DC_SFRESET); usleep_range(10000, 11000); - isp1760_udc_write(udc, DC_MODE, 0); + isp1760_reg_write(udc->regs, mode_reg, 0); usleep_range(10000, 11000); return 0; @@ -1445,7 +1541,6 @@ int isp1760_udc_register(struct isp1760_device *isp, int irq, udc->irq = -1; udc->isp = isp; - udc->regs = isp->regs; spin_lock_init(&udc->lock); timer_setup(&udc->vbus_timer, isp1760_udc_vbus_poll, 0); diff --git a/drivers/usb/isp1760/isp1760-udc.h b/drivers/usb/isp1760/isp1760-udc.h index d2df650d54e9..22044e86bc0e 100644 --- a/drivers/usb/isp1760/isp1760-udc.h +++ b/drivers/usb/isp1760/isp1760-udc.h @@ -2,10 +2,12 @@ /* * Driver for the NXP ISP1761 device controller * + * Copyright 2021 Linaro, Rui Miguel Silva * Copyright 2014 Ideas on Board Oy * * Contacts: * Laurent Pinchart <laurent.pinchart@ideasonboard.com> + * Rui Miguel Silva <rui.silva@linaro.org> */ #ifndef _ISP1760_UDC_H_ @@ -17,6 +19,8 @@ #include <linux/timer.h> #include <linux/usb/gadget.h> +#include "isp1760-regs.h" + struct isp1760_device; struct isp1760_udc; @@ -48,7 +52,7 @@ struct isp1760_ep { * struct isp1760_udc - UDC state information * irq: IRQ number * irqname: IRQ name (as passed to request_irq) - * regs: Base address of the UDC registers + * regs: regmap for UDC registers * driver: Gadget driver * gadget: Gadget device * lock: Protects driver, vbus_timer, ep, ep0_*, DC_EPINDEX register @@ -59,12 +63,13 @@ struct isp1760_ep { * connected: Tracks gadget driver bus connection state */ struct isp1760_udc { -#ifdef CONFIG_USB_ISP1761_UDC struct isp1760_device *isp; int irq; char *irqname; - void __iomem *regs; + + struct regmap *regs; + struct regmap_field *fields[DC_FIELD_MAX]; struct usb_gadget_driver *driver; struct usb_gadget gadget; @@ -79,9 +84,9 @@ struct isp1760_udc { u16 ep0_length; bool connected; + bool is_isp1763; unsigned int devstatus; -#endif }; #ifdef CONFIG_USB_ISP1761_UDC diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 8a3d9c0c8d8b..e5a8fcdbb78e 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -2098,7 +2098,6 @@ more:{ } else d += sprintf(d, " .."); bytes_read += 1; - continue; } goto more; } else if (packet_bytes > 1) { diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index aef0a0bba25a..5546b868b08b 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -10,6 +10,7 @@ #ifndef __MTU3_H__ #define __MTU3_H__ +#include <linux/clk.h> #include <linux/device.h> #include <linux/dmapool.h> #include <linux/extcon.h> @@ -21,6 +22,7 @@ #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> #include <linux/usb/otg.h> +#include <linux/usb/role.h> struct mtu3; struct mtu3_ep; @@ -88,6 +90,8 @@ struct mtu3_request; */ #define EP0_RESPONSE_BUF 6 +#define BULK_CLKS_CNT 4 + /* device operated link and speed got from DEVICE_CONF register */ enum mtu3_speed { MTU3_SPEED_INACTIVE = 0, @@ -192,13 +196,9 @@ struct mtu3_gpd_ring { /** * @vbus: vbus 5V used by host mode * @edev: external connector used to detect vbus and iddig changes -* @vbus_nb: notifier for vbus detection -* @vbus_work : work of vbus detection notifier, used to avoid sleep in -* notifier callback which is atomic context -* @vbus_event : event of vbus detecion notifier * @id_nb : notifier for iddig(idpin) detection -* @id_work : work of iddig detection notifier -* @id_event : event of iddig detecion notifier +* @dr_work : work for drd mode switch, used to avoid sleep in atomic context +* @desired_role : role desired to switch * @role_sw : use USB Role Switch to support dual-role switch, can't use * extcon at the same time, and extcon is deprecated. * @role_sw_used : true when the USB Role Switch is used. @@ -209,12 +209,9 @@ struct mtu3_gpd_ring { struct otg_switch_mtk { struct regulator *vbus; struct extcon_dev *edev; - struct notifier_block vbus_nb; - struct work_struct vbus_work; - unsigned long vbus_event; struct notifier_block id_nb; - struct work_struct id_work; - unsigned long id_event; + struct work_struct dr_work; + enum usb_role desired_role; struct usb_role_switch *role_sw; bool role_sw_used; bool is_u3_drd; @@ -225,10 +222,6 @@ struct otg_switch_mtk { * @mac_base: register base address of device MAC, exclude xHCI's * @ippc_base: register base address of IP Power and Clock interface (IPPC) * @vusb33: usb3.3V shared by device/host IP - * @sys_clk: system clock of mtu3, shared by device/host IP - * @ref_clk: reference clock - * @mcu_clk: mcu_bus_ck clock for AHB bus etc - * @dma_clk: dma_bus_ck clock for AXI bus etc * @dr_mode: works in which mode: * host only, device only or dual-role mode * @u2_ports: number of usb2.0 host ports @@ -250,10 +243,7 @@ struct ssusb_mtk { int num_phys; /* common power & clock */ struct regulator *vusb33; - struct clk *sys_clk; - struct clk *ref_clk; - struct clk *mcu_clk; - struct clk *dma_clk; + struct clk_bulk_data clks[BULK_CLKS_CNT]; /* otg */ struct otg_switch_mtk otg_switch; enum usb_dr_mode dr_mode; @@ -422,11 +412,9 @@ int mtu3_config_ep(struct mtu3 *mtu, struct mtu3_ep *mep, int interval, int burst, int mult); void mtu3_deconfig_ep(struct mtu3 *mtu, struct mtu3_ep *mep); void mtu3_ep_stall_set(struct mtu3_ep *mep, bool set); -void mtu3_ep0_setup(struct mtu3 *mtu); void mtu3_start(struct mtu3 *mtu); void mtu3_stop(struct mtu3 *mtu); void mtu3_dev_on_off(struct mtu3 *mtu, int is_on); -void mtu3_set_speed(struct mtu3 *mtu, enum usb_device_speed speed); int mtu3_gadget_setup(struct mtu3 *mtu); void mtu3_gadget_cleanup(struct mtu3 *mtu); diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c index b3b459937566..562f4357831e 100644 --- a/drivers/usb/mtu3/mtu3_core.c +++ b/drivers/usb/mtu3/mtu3_core.c @@ -207,7 +207,7 @@ static void mtu3_intr_enable(struct mtu3 *mtu) mtu3_writel(mbase, U3D_DEV_LINK_INTR_ENABLE, SSUSB_DEV_SPEED_CHG_INTR); } -void mtu3_set_speed(struct mtu3 *mtu, enum usb_device_speed speed) +static void mtu3_set_speed(struct mtu3 *mtu, enum usb_device_speed speed) { void __iomem *mbase = mtu->mac_base; @@ -334,6 +334,10 @@ void mtu3_start(struct mtu3 *mtu) mtu3_readl(mbase, U3D_DEVICE_CONTROL)); mtu3_clrbits(mtu->ippc_base, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN); + if (mtu->is_u3_ip) + mtu3_clrbits(mtu->ippc_base, SSUSB_U3_CTRL(0), SSUSB_U3_PORT_PDN); + + mtu3_clrbits(mtu->ippc_base, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_PDN); mtu3_csr_init(mtu); mtu3_set_speed(mtu, mtu->speed); @@ -356,6 +360,11 @@ void mtu3_stop(struct mtu3 *mtu) mtu3_dev_on_off(mtu, 0); mtu->is_active = 0; + + if (mtu->is_u3_ip) + mtu3_setbits(mtu->ippc_base, SSUSB_U3_CTRL(0), SSUSB_U3_PORT_PDN); + + mtu3_setbits(mtu->ippc_base, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_PDN); mtu3_setbits(mtu->ippc_base, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN); } @@ -536,7 +545,7 @@ static void get_ep_fifo_config(struct mtu3 *mtu) rx_fifo->base, rx_fifo->limit); } -void mtu3_ep0_setup(struct mtu3 *mtu) +static void mtu3_ep0_setup(struct mtu3 *mtu) { u32 maxpacket = mtu->g.ep0->maxpacket; u32 csr; @@ -921,16 +930,15 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb) device_init_wakeup(dev, true); + /* power down device IP for power saving by default */ + mtu3_stop(mtu); + ret = mtu3_gadget_setup(mtu); if (ret) { dev_err(dev, "mtu3 gadget init failed:%d\n", ret); goto gadget_err; } - /* init as host mode, power down device IP for power saving */ - if (mtu->ssusb->dr_mode == USB_DR_MODE_OTG) - mtu3_stop(mtu); - ssusb_dev_debugfs_init(ssusb); dev_dbg(dev, " %s() done...\n", __func__); diff --git a/drivers/usb/mtu3/mtu3_debugfs.c b/drivers/usb/mtu3/mtu3_debugfs.c index 7537bfd651af..d27de647c86a 100644 --- a/drivers/usb/mtu3/mtu3_debugfs.c +++ b/drivers/usb/mtu3/mtu3_debugfs.c @@ -30,6 +30,7 @@ static const struct debugfs_reg32 mtu3_ippc_regs[] = { dump_register(SSUSB_IP_PW_CTRL1), dump_register(SSUSB_IP_PW_CTRL2), dump_register(SSUSB_IP_PW_CTRL3), + dump_register(SSUSB_IP_PW_STS1), dump_register(SSUSB_OTG_STS), dump_register(SSUSB_IP_XHCI_CAP), dump_register(SSUSB_IP_DEV_CAP), diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c index 04f666e85731..318fbc618137 100644 --- a/drivers/usb/mtu3/mtu3_dr.c +++ b/drivers/usb/mtu3/mtu3_dr.c @@ -7,8 +7,6 @@ * Author: Chunfeng Yun <chunfeng.yun@mediatek.com> */ -#include <linux/usb/role.h> - #include "mtu3.h" #include "mtu3_dr.h" #include "mtu3_debug.h" @@ -16,27 +14,9 @@ #define USB2_PORT 2 #define USB3_PORT 3 -enum mtu3_vbus_id_state { - MTU3_ID_FLOAT = 1, - MTU3_ID_GROUND, - MTU3_VBUS_OFF, - MTU3_VBUS_VALID, -}; - -static char *mailbox_state_string(enum mtu3_vbus_id_state state) +static inline struct ssusb_mtk *otg_sx_to_ssusb(struct otg_switch_mtk *otg_sx) { - switch (state) { - case MTU3_ID_FLOAT: - return "ID_FLOAT"; - case MTU3_ID_GROUND: - return "ID_GROUND"; - case MTU3_VBUS_OFF: - return "VBUS_OFF"; - case MTU3_VBUS_VALID: - return "VBUS_VALID"; - default: - return "UNKNOWN"; - } + return container_of(otg_sx, struct ssusb_mtk, otg_switch); } static void toggle_opstate(struct ssusb_mtk *ssusb) @@ -123,8 +103,7 @@ static void switch_port_to_device(struct ssusb_mtk *ssusb) int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on) { - struct ssusb_mtk *ssusb = - container_of(otg_sx, struct ssusb_mtk, otg_switch); + struct ssusb_mtk *ssusb = otg_sx_to_ssusb(otg_sx); struct regulator *vbus = otg_sx->vbus; int ret; @@ -147,99 +126,72 @@ int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on) return 0; } -/* - * switch to host: -> MTU3_VBUS_OFF --> MTU3_ID_GROUND - * switch to device: -> MTU3_ID_FLOAT --> MTU3_VBUS_VALID - */ -static void ssusb_set_mailbox(struct otg_switch_mtk *otg_sx, - enum mtu3_vbus_id_state status) +static void ssusb_mode_sw_work(struct work_struct *work) { - struct ssusb_mtk *ssusb = - container_of(otg_sx, struct ssusb_mtk, otg_switch); + struct otg_switch_mtk *otg_sx = + container_of(work, struct otg_switch_mtk, dr_work); + struct ssusb_mtk *ssusb = otg_sx_to_ssusb(otg_sx); struct mtu3 *mtu = ssusb->u3d; + enum usb_role desired_role = otg_sx->desired_role; + enum usb_role current_role; + + current_role = ssusb->is_host ? USB_ROLE_HOST : USB_ROLE_DEVICE; + + if (desired_role == USB_ROLE_NONE) + desired_role = USB_ROLE_HOST; - dev_dbg(ssusb->dev, "mailbox %s\n", mailbox_state_string(status)); - mtu3_dbg_trace(ssusb->dev, "mailbox %s", mailbox_state_string(status)); + if (current_role == desired_role) + return; + + dev_dbg(ssusb->dev, "set role : %s\n", usb_role_string(desired_role)); + mtu3_dbg_trace(ssusb->dev, "set role : %s", usb_role_string(desired_role)); - switch (status) { - case MTU3_ID_GROUND: + switch (desired_role) { + case USB_ROLE_HOST: + ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_HOST); + mtu3_stop(mtu); switch_port_to_host(ssusb); ssusb_set_vbus(otg_sx, 1); ssusb->is_host = true; break; - case MTU3_ID_FLOAT: + case USB_ROLE_DEVICE: + ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_DEVICE); ssusb->is_host = false; ssusb_set_vbus(otg_sx, 0); switch_port_to_device(ssusb); - break; - case MTU3_VBUS_OFF: - mtu3_stop(mtu); - pm_relax(ssusb->dev); - break; - case MTU3_VBUS_VALID: - /* avoid suspend when works as device */ - pm_stay_awake(ssusb->dev); mtu3_start(mtu); break; + case USB_ROLE_NONE: default: - dev_err(ssusb->dev, "invalid state\n"); + dev_err(ssusb->dev, "invalid role\n"); } } -static void ssusb_id_work(struct work_struct *work) +static void ssusb_set_mode(struct otg_switch_mtk *otg_sx, enum usb_role role) { - struct otg_switch_mtk *otg_sx = - container_of(work, struct otg_switch_mtk, id_work); + struct ssusb_mtk *ssusb = otg_sx_to_ssusb(otg_sx); - if (otg_sx->id_event) - ssusb_set_mailbox(otg_sx, MTU3_ID_GROUND); - else - ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT); -} - -static void ssusb_vbus_work(struct work_struct *work) -{ - struct otg_switch_mtk *otg_sx = - container_of(work, struct otg_switch_mtk, vbus_work); + if (ssusb->dr_mode != USB_DR_MODE_OTG) + return; - if (otg_sx->vbus_event) - ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID); - else - ssusb_set_mailbox(otg_sx, MTU3_VBUS_OFF); + otg_sx->desired_role = role; + queue_work(system_freezable_wq, &otg_sx->dr_work); } -/* - * @ssusb_id_notifier is called in atomic context, but @ssusb_set_mailbox - * may sleep, so use work queue here - */ static int ssusb_id_notifier(struct notifier_block *nb, unsigned long event, void *ptr) { struct otg_switch_mtk *otg_sx = container_of(nb, struct otg_switch_mtk, id_nb); - otg_sx->id_event = event; - schedule_work(&otg_sx->id_work); - - return NOTIFY_DONE; -} - -static int ssusb_vbus_notifier(struct notifier_block *nb, - unsigned long event, void *ptr) -{ - struct otg_switch_mtk *otg_sx = - container_of(nb, struct otg_switch_mtk, vbus_nb); - - otg_sx->vbus_event = event; - schedule_work(&otg_sx->vbus_work); + ssusb_set_mode(otg_sx, event ? USB_ROLE_HOST : USB_ROLE_DEVICE); return NOTIFY_DONE; } static int ssusb_extcon_register(struct otg_switch_mtk *otg_sx) { - struct ssusb_mtk *ssusb = - container_of(otg_sx, struct ssusb_mtk, otg_switch); + struct ssusb_mtk *ssusb = otg_sx_to_ssusb(otg_sx); struct extcon_dev *edev = otg_sx->edev; int ret; @@ -247,14 +199,6 @@ static int ssusb_extcon_register(struct otg_switch_mtk *otg_sx) if (!edev) return 0; - otg_sx->vbus_nb.notifier_call = ssusb_vbus_notifier; - ret = devm_extcon_register_notifier(ssusb->dev, edev, EXTCON_USB, - &otg_sx->vbus_nb); - if (ret < 0) { - dev_err(ssusb->dev, "failed to register notifier for USB\n"); - return ret; - } - otg_sx->id_nb.notifier_call = ssusb_id_notifier; ret = devm_extcon_register_notifier(ssusb->dev, edev, EXTCON_USB_HOST, &otg_sx->id_nb); @@ -263,15 +207,12 @@ static int ssusb_extcon_register(struct otg_switch_mtk *otg_sx) return ret; } - dev_dbg(ssusb->dev, "EXTCON_USB: %d, EXTCON_USB_HOST: %d\n", - extcon_get_state(edev, EXTCON_USB), - extcon_get_state(edev, EXTCON_USB_HOST)); + ret = extcon_get_state(edev, EXTCON_USB_HOST); + dev_dbg(ssusb->dev, "EXTCON_USB_HOST: %d\n", ret); /* default as host, switch to device mode if needed */ - if (extcon_get_state(edev, EXTCON_USB_HOST) == false) - ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT); - if (extcon_get_state(edev, EXTCON_USB) == true) - ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID); + if (!ret) + ssusb_set_mode(otg_sx, USB_ROLE_DEVICE); return 0; } @@ -286,15 +227,7 @@ void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host) { struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; - if (to_host) { - ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_HOST); - ssusb_set_mailbox(otg_sx, MTU3_VBUS_OFF); - ssusb_set_mailbox(otg_sx, MTU3_ID_GROUND); - } else { - ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_DEVICE); - ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT); - ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID); - } + ssusb_set_mode(otg_sx, to_host ? USB_ROLE_HOST : USB_ROLE_DEVICE); } void ssusb_set_force_mode(struct ssusb_mtk *ssusb, @@ -323,13 +256,9 @@ void ssusb_set_force_mode(struct ssusb_mtk *ssusb, static int ssusb_role_sw_set(struct usb_role_switch *sw, enum usb_role role) { struct ssusb_mtk *ssusb = usb_role_switch_get_drvdata(sw); - bool to_host = false; - - if (role == USB_ROLE_HOST) - to_host = true; + struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; - if (to_host ^ ssusb->is_host) - ssusb_mode_switch(ssusb, to_host); + ssusb_set_mode(otg_sx, role); return 0; } @@ -337,18 +266,14 @@ static int ssusb_role_sw_set(struct usb_role_switch *sw, enum usb_role role) static enum usb_role ssusb_role_sw_get(struct usb_role_switch *sw) { struct ssusb_mtk *ssusb = usb_role_switch_get_drvdata(sw); - enum usb_role role; - - role = ssusb->is_host ? USB_ROLE_HOST : USB_ROLE_DEVICE; - return role; + return ssusb->is_host ? USB_ROLE_HOST : USB_ROLE_DEVICE; } static int ssusb_role_sw_register(struct otg_switch_mtk *otg_sx) { struct usb_role_switch_desc role_sx_desc = { 0 }; - struct ssusb_mtk *ssusb = - container_of(otg_sx, struct ssusb_mtk, otg_switch); + struct ssusb_mtk *ssusb = otg_sx_to_ssusb(otg_sx); if (!otg_sx->role_sw_used) return 0; @@ -367,8 +292,7 @@ int ssusb_otg_switch_init(struct ssusb_mtk *ssusb) struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; int ret = 0; - INIT_WORK(&otg_sx->id_work, ssusb_id_work); - INIT_WORK(&otg_sx->vbus_work, ssusb_vbus_work); + INIT_WORK(&otg_sx->dr_work, ssusb_mode_sw_work); if (otg_sx->manual_drd_enabled) ssusb_dr_debugfs_init(ssusb); @@ -384,7 +308,6 @@ void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb) { struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; - cancel_work_sync(&otg_sx->id_work); - cancel_work_sync(&otg_sx->vbus_work); + cancel_work_sync(&otg_sx->dr_work); usb_role_switch_unregister(otg_sx->role_sw); } diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c index 38f17d66d5bc..5e21ba05ebf0 100644 --- a/drivers/usb/mtu3/mtu3_gadget.c +++ b/drivers/usb/mtu3/mtu3_gadget.c @@ -577,7 +577,7 @@ mtu3_gadget_set_speed(struct usb_gadget *g, enum usb_device_speed speed) dev_dbg(mtu->dev, "%s %s\n", __func__, usb_speed_string(speed)); spin_lock_irqsave(&mtu->lock, flags); - mtu3_set_speed(mtu, speed); + mtu->speed = speed; spin_unlock_irqrestore(&mtu->lock, flags); } diff --git a/drivers/usb/mtu3/mtu3_host.c b/drivers/usb/mtu3/mtu3_host.c index 0a8cd446cf1b..93a1a4c11e1e 100644 --- a/drivers/usb/mtu3/mtu3_host.c +++ b/drivers/usb/mtu3/mtu3_host.c @@ -213,8 +213,6 @@ int ssusb_host_disable(struct ssusb_mtk *ssusb, bool suspend) static void ssusb_host_setup(struct ssusb_mtk *ssusb) { - struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; - host_ports_num_get(ssusb); /* @@ -222,9 +220,7 @@ static void ssusb_host_setup(struct ssusb_mtk *ssusb) * if support OTG, gadget driver will switch port0 to device mode */ ssusb_host_enable(ssusb); - - if (otg_sx->manual_drd_enabled) - ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_HOST); + ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_HOST); /* if port0 supports dual-role, works as host mode by default */ ssusb_set_vbus(&ssusb->otg_switch, 1); diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c index 7786a95a874e..c0615f6e5cce 100644 --- a/drivers/usb/mtu3/mtu3_plat.c +++ b/drivers/usb/mtu3/mtu3_plat.c @@ -5,7 +5,6 @@ * Author: Chunfeng Yun <chunfeng.yun@mediatek.com> */ -#include <linux/clk.h> #include <linux/dma-mapping.h> #include <linux/iopoll.h> #include <linux/kernel.h> @@ -101,54 +100,6 @@ static void ssusb_phy_power_off(struct ssusb_mtk *ssusb) phy_power_off(ssusb->phys[i]); } -static int ssusb_clks_enable(struct ssusb_mtk *ssusb) -{ - int ret; - - ret = clk_prepare_enable(ssusb->sys_clk); - if (ret) { - dev_err(ssusb->dev, "failed to enable sys_clk\n"); - goto sys_clk_err; - } - - ret = clk_prepare_enable(ssusb->ref_clk); - if (ret) { - dev_err(ssusb->dev, "failed to enable ref_clk\n"); - goto ref_clk_err; - } - - ret = clk_prepare_enable(ssusb->mcu_clk); - if (ret) { - dev_err(ssusb->dev, "failed to enable mcu_clk\n"); - goto mcu_clk_err; - } - - ret = clk_prepare_enable(ssusb->dma_clk); - if (ret) { - dev_err(ssusb->dev, "failed to enable dma_clk\n"); - goto dma_clk_err; - } - - return 0; - -dma_clk_err: - clk_disable_unprepare(ssusb->mcu_clk); -mcu_clk_err: - clk_disable_unprepare(ssusb->ref_clk); -ref_clk_err: - clk_disable_unprepare(ssusb->sys_clk); -sys_clk_err: - return ret; -} - -static void ssusb_clks_disable(struct ssusb_mtk *ssusb) -{ - clk_disable_unprepare(ssusb->dma_clk); - clk_disable_unprepare(ssusb->mcu_clk); - clk_disable_unprepare(ssusb->ref_clk); - clk_disable_unprepare(ssusb->sys_clk); -} - static int ssusb_rscs_init(struct ssusb_mtk *ssusb) { int ret = 0; @@ -159,7 +110,7 @@ static int ssusb_rscs_init(struct ssusb_mtk *ssusb) goto vusb33_err; } - ret = ssusb_clks_enable(ssusb); + ret = clk_bulk_prepare_enable(BULK_CLKS_CNT, ssusb->clks); if (ret) goto clks_err; @@ -180,7 +131,7 @@ static int ssusb_rscs_init(struct ssusb_mtk *ssusb) phy_err: ssusb_phy_exit(ssusb); phy_init_err: - ssusb_clks_disable(ssusb); + clk_bulk_disable_unprepare(BULK_CLKS_CNT, ssusb->clks); clks_err: regulator_disable(ssusb->vusb33); vusb33_err: @@ -189,7 +140,7 @@ vusb33_err: static void ssusb_rscs_exit(struct ssusb_mtk *ssusb) { - ssusb_clks_disable(ssusb); + clk_bulk_disable_unprepare(BULK_CLKS_CNT, ssusb->clks); regulator_disable(ssusb->vusb33); ssusb_phy_power_off(ssusb); ssusb_phy_exit(ssusb); @@ -215,6 +166,7 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) { struct device_node *node = pdev->dev.of_node; struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; + struct clk_bulk_data *clks = ssusb->clks; struct device *dev = &pdev->dev; int i; int ret; @@ -225,23 +177,13 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) return PTR_ERR(ssusb->vusb33); } - ssusb->sys_clk = devm_clk_get(dev, "sys_ck"); - if (IS_ERR(ssusb->sys_clk)) { - dev_err(dev, "failed to get sys clock\n"); - return PTR_ERR(ssusb->sys_clk); - } - - ssusb->ref_clk = devm_clk_get_optional(dev, "ref_ck"); - if (IS_ERR(ssusb->ref_clk)) - return PTR_ERR(ssusb->ref_clk); - - ssusb->mcu_clk = devm_clk_get_optional(dev, "mcu_ck"); - if (IS_ERR(ssusb->mcu_clk)) - return PTR_ERR(ssusb->mcu_clk); - - ssusb->dma_clk = devm_clk_get_optional(dev, "dma_ck"); - if (IS_ERR(ssusb->dma_clk)) - return PTR_ERR(ssusb->dma_clk); + clks[0].id = "sys_ck"; + clks[1].id = "ref_ck"; + clks[2].id = "mcu_ck"; + clks[3].id = "dma_ck"; + ret = devm_clk_bulk_get_optional(dev, BULK_CLKS_CNT, clks); + if (ret) + return ret; ssusb->num_phys = of_count_phandle_with_args(node, "phys", "#phy-cells"); @@ -299,11 +241,14 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) of_property_read_bool(node, "enable-manual-drd"); otg_sx->role_sw_used = of_property_read_bool(node, "usb-role-switch"); - if (!otg_sx->role_sw_used && of_property_read_bool(node, "extcon")) { + if (otg_sx->role_sw_used || otg_sx->manual_drd_enabled) + goto out; + + if (of_property_read_bool(node, "extcon")) { otg_sx->edev = extcon_get_edev_by_phandle(ssusb->dev, 0); if (IS_ERR(otg_sx->edev)) { - dev_err(ssusb->dev, "couldn't get extcon device\n"); - return PTR_ERR(otg_sx->edev); + return dev_err_probe(dev, PTR_ERR(otg_sx->edev), + "couldn't get extcon device\n"); } } @@ -461,7 +406,7 @@ static int __maybe_unused mtu3_suspend(struct device *dev) ssusb_host_disable(ssusb, true); ssusb_phy_power_off(ssusb); - ssusb_clks_disable(ssusb); + clk_bulk_disable_unprepare(BULK_CLKS_CNT, ssusb->clks); ssusb_wakeup_set(ssusb, true); return 0; @@ -478,7 +423,7 @@ static int __maybe_unused mtu3_resume(struct device *dev) return 0; ssusb_wakeup_set(ssusb, false); - ret = ssusb_clks_enable(ssusb); + ret = clk_bulk_prepare_enable(BULK_CLKS_CNT, ssusb->clks); if (ret) goto clks_err; @@ -491,7 +436,7 @@ static int __maybe_unused mtu3_resume(struct device *dev) return 0; phy_err: - ssusb_clks_disable(ssusb); + clk_bulk_disable_unprepare(BULK_CLKS_CNT, ssusb->clks); clks_err: return ret; } diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 4c8f0112481f..f7b1d5993f8c 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -480,9 +480,7 @@ int musb_set_host(struct musb *musb) devctl = musb_read_devctl(musb); if (!(devctl & MUSB_DEVCTL_BDEVICE)) { - dev_info(musb->controller, - "%s: already in host mode: %02x\n", - __func__, devctl); + trace_musb_state(musb, devctl, "Already in host mode"); goto init_data; } @@ -499,6 +497,9 @@ int musb_set_host(struct musb *musb) return error; } + devctl = musb_read_devctl(musb); + trace_musb_state(musb, devctl, "Host mode set"); + init_data: musb->is_active = 1; musb->xceiv->otg->state = OTG_STATE_A_IDLE; @@ -526,10 +527,7 @@ int musb_set_peripheral(struct musb *musb) devctl = musb_read_devctl(musb); if (devctl & MUSB_DEVCTL_BDEVICE) { - dev_info(musb->controller, - "%s: already in peripheral mode: %02x\n", - __func__, devctl); - + trace_musb_state(musb, devctl, "Already in peripheral mode"); goto init_data; } @@ -546,6 +544,9 @@ int musb_set_peripheral(struct musb *musb) return error; } + devctl = musb_read_devctl(musb); + trace_musb_state(musb, devctl, "Peripheral mode set"); + init_data: musb->is_active = 0; musb->xceiv->otg->state = OTG_STATE_B_IDLE; @@ -1984,6 +1985,21 @@ ATTRIBUTE_GROUPS(musb); #define MUSB_QUIRK_A_DISCONNECT_19 ((3 << MUSB_DEVCTL_VBUS_SHIFT) | \ MUSB_DEVCTL_SESSION) +static bool musb_state_needs_recheck(struct musb *musb, u8 devctl, + const char *desc) +{ + if (musb->quirk_retries && !musb->flush_irq_work) { + trace_musb_state(musb, devctl, desc); + schedule_delayed_work(&musb->irq_work, + msecs_to_jiffies(1000)); + musb->quirk_retries--; + + return true; + } + + return false; +} + /* * Check the musb devctl session bit to determine if we want to * allow PM runtime for the device. In general, we want to keep things @@ -2004,35 +2020,21 @@ static void musb_pm_runtime_check_session(struct musb *musb) MUSB_DEVCTL_HR; switch (devctl & ~s) { case MUSB_QUIRK_B_DISCONNECT_99: - if (musb->quirk_retries && !musb->flush_irq_work) { - musb_dbg(musb, "Poll devctl in case of suspend after disconnect\n"); - schedule_delayed_work(&musb->irq_work, - msecs_to_jiffies(1000)); - musb->quirk_retries--; - } + musb_state_needs_recheck(musb, devctl, + "Poll devctl in case of suspend after disconnect"); break; case MUSB_QUIRK_B_INVALID_VBUS_91: - if (musb->quirk_retries && !musb->flush_irq_work) { - musb_dbg(musb, - "Poll devctl on invalid vbus, assume no session"); - schedule_delayed_work(&musb->irq_work, - msecs_to_jiffies(1000)); - musb->quirk_retries--; + if (musb_state_needs_recheck(musb, devctl, + "Poll devctl on invalid vbus, assume no session")) return; - } fallthrough; case MUSB_QUIRK_A_DISCONNECT_19: - if (musb->quirk_retries && !musb->flush_irq_work) { - musb_dbg(musb, - "Poll devctl on possible host mode disconnect"); - schedule_delayed_work(&musb->irq_work, - msecs_to_jiffies(1000)); - musb->quirk_retries--; + if (musb_state_needs_recheck(musb, devctl, + "Poll devctl on possible host mode disconnect")) return; - } if (!musb->session) break; - musb_dbg(musb, "Allow PM on possible host mode disconnect"); + trace_musb_state(musb, devctl, "Allow PM on possible host mode disconnect"); pm_runtime_mark_last_busy(musb->controller); pm_runtime_put_autosuspend(musb->controller); musb->session = false; @@ -2048,14 +2050,23 @@ static void musb_pm_runtime_check_session(struct musb *musb) /* Block PM or allow PM? */ if (s) { - musb_dbg(musb, "Block PM on active session: %02x", devctl); + trace_musb_state(musb, devctl, "Block PM on active session"); error = pm_runtime_get_sync(musb->controller); if (error < 0) dev_err(musb->controller, "Could not enable: %i\n", error); musb->quirk_retries = 3; + + /* + * We can get a spurious MUSB_INTR_SESSREQ interrupt on start-up + * in B-peripheral mode with nothing connected and the session + * bit clears silently. Check status again in 3 seconds. + */ + if (devctl & MUSB_DEVCTL_BDEVICE) + schedule_delayed_work(&musb->irq_work, + msecs_to_jiffies(3000)); } else { - musb_dbg(musb, "Allow PM with no session: %02x", devctl); + trace_musb_state(musb, devctl, "Allow PM with no session"); pm_runtime_mark_last_busy(musb->controller); pm_runtime_put_autosuspend(musb->controller); } diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index ef374d4dd94a..98c0f4c1bffd 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -611,7 +611,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) * mode 0 only. So we do not get endpoint interrupts due to DMA * completion. We only get interrupts from DMA controller. * - * We could operate in DMA mode 1 if we knew the size of the tranfer + * We could operate in DMA mode 1 if we knew the size of the transfer * in advance. For mass storage class, request->length = what the host * sends, so that'd work. But for pretty much everything else, * request->length is routinely more than what the host sends. For diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 30c5e7de0761..9ff7d891b4b7 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -563,10 +563,9 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, u8 epnum) ep->rx_reinit = 0; } -static void musb_tx_dma_set_mode_mentor(struct dma_controller *dma, - struct musb_hw_ep *hw_ep, struct musb_qh *qh, - struct urb *urb, u32 offset, - u32 *length, u8 *mode) +static void musb_tx_dma_set_mode_mentor(struct musb_hw_ep *hw_ep, + struct musb_qh *qh, + u32 *length, u8 *mode) { struct dma_channel *channel = hw_ep->tx_channel; void __iomem *epio = hw_ep->regs; @@ -602,12 +601,8 @@ static void musb_tx_dma_set_mode_mentor(struct dma_controller *dma, musb_writew(epio, MUSB_TXCSR, csr); } -static void musb_tx_dma_set_mode_cppi_tusb(struct dma_controller *dma, - struct musb_hw_ep *hw_ep, - struct musb_qh *qh, +static void musb_tx_dma_set_mode_cppi_tusb(struct musb_hw_ep *hw_ep, struct urb *urb, - u32 offset, - u32 *length, u8 *mode) { struct dma_channel *channel = hw_ep->tx_channel; @@ -630,11 +625,10 @@ static bool musb_tx_dma_program(struct dma_controller *dma, u8 mode; if (musb_dma_inventra(hw_ep->musb) || musb_dma_ux500(hw_ep->musb)) - musb_tx_dma_set_mode_mentor(dma, hw_ep, qh, urb, offset, + musb_tx_dma_set_mode_mentor(hw_ep, qh, &length, &mode); else if (is_cppi_enabled(hw_ep->musb) || tusb_dma_omap(hw_ep->musb)) - musb_tx_dma_set_mode_cppi_tusb(dma, hw_ep, qh, urb, offset, - &length, &mode); + musb_tx_dma_set_mode_cppi_tusb(hw_ep, urb, &mode); else return false; diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h index 4804d4d85c15..63298bd233e0 100644 --- a/drivers/usb/musb/musb_host.h +++ b/drivers/usb/musb/musb_host.h @@ -61,10 +61,6 @@ extern void musb_host_tx(struct musb *, u8); extern void musb_host_rx(struct musb *, u8); extern void musb_root_disconnect(struct musb *musb); extern void musb_host_free(struct musb *); -extern void musb_host_cleanup(struct musb *); -extern void musb_host_tx(struct musb *, u8); -extern void musb_host_rx(struct musb *, u8); -extern void musb_root_disconnect(struct musb *musb); extern void musb_host_resume_root_hub(struct musb *musb); extern void musb_host_poke_root_hub(struct musb *musb); extern int musb_port_suspend(struct musb *musb, bool do_suspend); diff --git a/drivers/usb/musb/musb_trace.h b/drivers/usb/musb/musb_trace.h index 380ebc77eab1..ec28b5716796 100644 --- a/drivers/usb/musb/musb_trace.h +++ b/drivers/usb/musb/musb_trace.h @@ -37,6 +37,23 @@ TRACE_EVENT(musb_log, TP_printk("%s: %s", __get_str(name), __get_str(msg)) ); +TRACE_EVENT(musb_state, + TP_PROTO(struct musb *musb, u8 devctl, const char *desc), + TP_ARGS(musb, devctl, desc), + TP_STRUCT__entry( + __string(name, dev_name(musb->controller)) + __field(u8, devctl) + __string(desc, desc) + ), + TP_fast_assign( + __assign_str(name, dev_name(musb->controller)); + __entry->devctl = devctl; + __assign_str(desc, desc); + ), + TP_printk("%s: devctl: %02x %s", __get_str(name), __entry->devctl, + __get_str(desc)) +); + DECLARE_EVENT_CLASS(musb_regb, TP_PROTO(void *caller, const void __iomem *addr, unsigned int offset, u8 data), diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 4232f1ce3fbf..640a46f0d118 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -33,6 +33,8 @@ struct omap2430_glue { enum musb_vbus_id_status status; struct work_struct omap_musb_mailbox_work; struct device *control_otghs; + unsigned int is_runtime_suspended:1; + unsigned int needs_resume:1; }; #define glue_to_musb(g) platform_get_drvdata(g->musb) @@ -459,6 +461,8 @@ static int omap2430_runtime_suspend(struct device *dev) phy_power_off(musb->phy); phy_exit(musb->phy); + glue->is_runtime_suspended = 1; + return 0; } @@ -480,12 +484,40 @@ static int omap2430_runtime_resume(struct device *dev) /* Wait for musb to get oriented. Otherwise we can get babble */ usleep_range(200000, 250000); + glue->is_runtime_suspended = 0; + return 0; } +static int omap2430_suspend(struct device *dev) +{ + struct omap2430_glue *glue = dev_get_drvdata(dev); + + if (glue->is_runtime_suspended) + return 0; + + glue->needs_resume = 1; + + return omap2430_runtime_suspend(dev); +} + +static int omap2430_resume(struct device *dev) +{ + struct omap2430_glue *glue = dev_get_drvdata(dev); + + if (!glue->needs_resume) + return 0; + + glue->needs_resume = 0; + + return omap2430_runtime_resume(dev); +} + static const struct dev_pm_ops omap2430_pm_ops = { .runtime_suspend = omap2430_runtime_suspend, .runtime_resume = omap2430_runtime_resume, + .suspend = omap2430_suspend, + .resume = omap2430_resume, }; #define DEV_PM_OPS (&omap2430_pm_ops) diff --git a/drivers/usb/phy/phy-isp1301-omap.c b/drivers/usb/phy/phy-isp1301-omap.c index 02bb7ddd4bd6..f3e9b3b6ac3e 100644 --- a/drivers/usb/phy/phy-isp1301-omap.c +++ b/drivers/usb/phy/phy-isp1301-omap.c @@ -555,7 +555,7 @@ pullup: case OTG_STATE_A_PERIPHERAL: if (otg_ctrl & OTG_PULLUP) goto pullup; - /* FALLTHROUGH */ + fallthrough; // case OTG_STATE_B_WAIT_ACON: default: pulldown: diff --git a/drivers/usb/phy/phy-isp1301.c b/drivers/usb/phy/phy-isp1301.c index 6cf6fbd39237..ad3d57f1c273 100644 --- a/drivers/usb/phy/phy-isp1301.c +++ b/drivers/usb/phy/phy-isp1301.c @@ -142,24 +142,17 @@ static struct i2c_driver isp1301_driver = { module_i2c_driver(isp1301_driver); -static int match(struct device *dev, const void *data) -{ - const struct device_node *node = (const struct device_node *)data; - return (dev->of_node == node) && - (dev->driver == &isp1301_driver.driver); -} - struct i2c_client *isp1301_get_client(struct device_node *node) { - if (node) { /* reference of ISP1301 I2C node via DT */ - struct device *dev = bus_find_device(&i2c_bus_type, NULL, - node, match); - if (!dev) - return NULL; - return to_i2c_client(dev); - } else { /* non-DT: only one ISP1301 chip supported */ - return isp1301_i2c_client; - } + struct i2c_client *client; + + /* reference of ISP1301 I2C node via DT */ + client = of_find_i2c_device_by_node(node); + if (client) + return client; + + /* non-DT: only one ISP1301 chip supported */ + return isp1301_i2c_client; } EXPORT_SYMBOL_GPL(isp1301_get_client); diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c index a48452a6172b..c0f432d509aa 100644 --- a/drivers/usb/phy/phy-tegra-usb.c +++ b/drivers/usb/phy/phy-tegra-usb.c @@ -58,12 +58,12 @@ #define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16) #define USB_PHY_VBUS_SENSORS 0x404 -#define B_SESS_VLD_WAKEUP_EN BIT(6) -#define B_VBUS_VLD_WAKEUP_EN BIT(14) +#define B_SESS_VLD_WAKEUP_EN BIT(14) #define A_SESS_VLD_WAKEUP_EN BIT(22) #define A_VBUS_VLD_WAKEUP_EN BIT(30) #define USB_PHY_VBUS_WAKEUP_ID 0x408 +#define VBUS_WAKEUP_STS BIT(10) #define VBUS_WAKEUP_WAKEUP_EN BIT(30) #define USB1_LEGACY_CTRL 0x410 @@ -544,7 +544,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy) val = readl_relaxed(base + USB_PHY_VBUS_SENSORS); val &= ~(A_VBUS_VLD_WAKEUP_EN | A_SESS_VLD_WAKEUP_EN); - val &= ~(B_VBUS_VLD_WAKEUP_EN | B_SESS_VLD_WAKEUP_EN); + val &= ~(B_SESS_VLD_WAKEUP_EN); writel_relaxed(val, base + USB_PHY_VBUS_SENSORS); val = readl_relaxed(base + UTMIP_BAT_CHRG_CFG0); @@ -642,6 +642,15 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy) void __iomem *base = phy->regs; u32 val; + /* + * Give hardware time to settle down after VBUS disconnection, + * otherwise PHY will immediately wake up from suspend. + */ + if (phy->wakeup_enabled && phy->mode != USB_DR_MODE_HOST) + readl_relaxed_poll_timeout(base + USB_PHY_VBUS_WAKEUP_ID, + val, !(val & VBUS_WAKEUP_STS), + 5000, 100000); + utmi_phy_clk_disable(phy); /* PHY won't resume if reset is asserted */ diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c index b47285f023cf..83ed5089475a 100644 --- a/drivers/usb/phy/phy.c +++ b/drivers/usb/phy/phy.c @@ -42,6 +42,12 @@ static const char *const usb_chger_type[] = { [ACA_TYPE] = "USB_CHARGER_ACA_TYPE", }; +static const char *const usb_chger_state[] = { + [USB_CHARGER_DEFAULT] = "USB_CHARGER_DEFAULT", + [USB_CHARGER_PRESENT] = "USB_CHARGER_PRESENT", + [USB_CHARGER_ABSENT] = "USB_CHARGER_ABSENT", +}; + static struct usb_phy *__usb_find_phy(struct list_head *list, enum usb_phy_type type) { @@ -74,6 +80,18 @@ static struct usb_phy *__of_usb_find_phy(struct device_node *node) return ERR_PTR(-EPROBE_DEFER); } +static struct usb_phy *__device_to_usb_phy(struct device *dev) +{ + struct usb_phy *usb_phy; + + list_for_each_entry(usb_phy, &phy_list, head) { + if (usb_phy->dev == dev) + break; + } + + return usb_phy; +} + static void usb_phy_set_default_current(struct usb_phy *usb_phy) { usb_phy->chg_cur.sdp_min = DEFAULT_SDP_CUR_MIN; @@ -105,9 +123,6 @@ static void usb_phy_set_default_current(struct usb_phy *usb_phy) static void usb_phy_notify_charger_work(struct work_struct *work) { struct usb_phy *usb_phy = container_of(work, struct usb_phy, chg_work); - char uchger_state[50] = { 0 }; - char uchger_type[50] = { 0 }; - char *envp[] = { uchger_state, uchger_type, NULL }; unsigned int min, max; switch (usb_phy->chg_state) { @@ -115,15 +130,11 @@ static void usb_phy_notify_charger_work(struct work_struct *work) usb_phy_get_charger_current(usb_phy, &min, &max); atomic_notifier_call_chain(&usb_phy->notifier, max, usb_phy); - snprintf(uchger_state, ARRAY_SIZE(uchger_state), - "USB_CHARGER_STATE=%s", "USB_CHARGER_PRESENT"); break; case USB_CHARGER_ABSENT: usb_phy_set_default_current(usb_phy); atomic_notifier_call_chain(&usb_phy->notifier, 0, usb_phy); - snprintf(uchger_state, ARRAY_SIZE(uchger_state), - "USB_CHARGER_STATE=%s", "USB_CHARGER_ABSENT"); break; default: dev_warn(usb_phy->dev, "Unknown USB charger state: %d\n", @@ -131,9 +142,30 @@ static void usb_phy_notify_charger_work(struct work_struct *work) return; } + kobject_uevent(&usb_phy->dev->kobj, KOBJ_CHANGE); +} + +static int usb_phy_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + struct usb_phy *usb_phy; + char uchger_state[50] = { 0 }; + char uchger_type[50] = { 0 }; + + usb_phy = __device_to_usb_phy(dev); + + snprintf(uchger_state, ARRAY_SIZE(uchger_state), + "USB_CHARGER_STATE=%s", usb_chger_state[usb_phy->chg_state]); + snprintf(uchger_type, ARRAY_SIZE(uchger_type), "USB_CHARGER_TYPE=%s", usb_chger_type[usb_phy->chg_type]); - kobject_uevent_env(&usb_phy->dev->kobj, KOBJ_CHANGE, envp); + + if (add_uevent_var(env, uchger_state)) + return -ENOMEM; + + if (add_uevent_var(env, uchger_type)) + return -ENOMEM; + + return 0; } static void __usb_phy_get_charger_type(struct usb_phy *usb_phy) @@ -661,6 +693,11 @@ out: } EXPORT_SYMBOL_GPL(usb_add_phy); +static struct device_type usb_phy_dev_type = { + .name = "usb_phy", + .uevent = usb_phy_uevent, +}; + /** * usb_add_phy_dev - declare the USB PHY * @x: the USB phy to be used; or NULL @@ -684,6 +721,8 @@ int usb_add_phy_dev(struct usb_phy *x) if (ret) return ret; + x->dev->type = &usb_phy_dev_type; + ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier); spin_lock_irqsave(&phy_lock, flags); diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index 33b637d0d8d9..dfaed7eee94f 100644 --- a/drivers/usb/roles/class.c +++ b/drivers/usb/roles/class.c @@ -214,6 +214,15 @@ static const char * const usb_roles[] = { [USB_ROLE_DEVICE] = "device", }; +const char *usb_role_string(enum usb_role role) +{ + if (role < 0 || role >= ARRAY_SIZE(usb_roles)) + return "unknown"; + + return usb_roles[role]; +} +EXPORT_SYMBOL_GPL(usb_role_string); + static ssize_t role_show(struct device *dev, struct device_attribute *attr, char *buf) { diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index ed9193f3bb1a..8107e4b5b03b 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -356,25 +356,7 @@ static void belkin_sa_set_termios(struct tty_struct *tty, /* set the number of data bits */ if ((cflag & CSIZE) != (old_cflag & CSIZE)) { - switch (cflag & CSIZE) { - case CS5: - urb_value = BELKIN_SA_DATA_BITS(5); - break; - case CS6: - urb_value = BELKIN_SA_DATA_BITS(6); - break; - case CS7: - urb_value = BELKIN_SA_DATA_BITS(7); - break; - case CS8: - urb_value = BELKIN_SA_DATA_BITS(8); - break; - default: - dev_dbg(&port->dev, - "CSIZE was not CS5-CS8, using default of 8\n"); - urb_value = BELKIN_SA_DATA_BITS(8); - break; - } + urb_value = BELKIN_SA_DATA_BITS(tty_get_char_size(cflag)); if (BSA_USB_CMD(BELKIN_SA_SET_DATA_BITS_REQUEST, urb_value) < 0) dev_err(&port->dev, "Set data bits error\n"); } diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index fcb812bc832c..09b845d0da41 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -247,9 +247,9 @@ struct cp210x_serial_private { #ifdef CONFIG_GPIOLIB struct gpio_chip gc; bool gpio_registered; - u8 gpio_pushpull; - u8 gpio_altfunc; - u8 gpio_input; + u16 gpio_pushpull; + u16 gpio_altfunc; + u16 gpio_input; #endif u8 partnum; u32 fw_version; @@ -534,6 +534,48 @@ struct cp210x_single_port_config { #define CP2104_GPIO1_RXLED_MODE BIT(1) #define CP2104_GPIO2_RS485_MODE BIT(2) +struct cp210x_quad_port_state { + __le16 gpio_mode_pb0; + __le16 gpio_mode_pb1; + __le16 gpio_mode_pb2; + __le16 gpio_mode_pb3; + __le16 gpio_mode_pb4; + + __le16 gpio_lowpower_pb0; + __le16 gpio_lowpower_pb1; + __le16 gpio_lowpower_pb2; + __le16 gpio_lowpower_pb3; + __le16 gpio_lowpower_pb4; + + __le16 gpio_latch_pb0; + __le16 gpio_latch_pb1; + __le16 gpio_latch_pb2; + __le16 gpio_latch_pb3; + __le16 gpio_latch_pb4; +}; + +/* + * CP210X_VENDOR_SPECIFIC, CP210X_GET_PORTCONFIG call reads these 0x49 bytes + * on a CP2108 chip. + * + * See https://www.silabs.com/documents/public/application-notes/an978-cp210x-usb-to-uart-api-specification.pdf + */ +struct cp210x_quad_port_config { + struct cp210x_quad_port_state reset_state; + struct cp210x_quad_port_state suspend_state; + u8 ipdelay_ifc[4]; + u8 enhancedfxn_ifc[4]; + u8 enhancedfxn_device; + u8 extclkfreq[4]; +} __packed; + +#define CP2108_EF_IFC_GPIO_TXLED 0x01 +#define CP2108_EF_IFC_GPIO_RXLED 0x02 +#define CP2108_EF_IFC_GPIO_RS485 0x04 +#define CP2108_EF_IFC_GPIO_RS485_LOGIC 0x08 +#define CP2108_EF_IFC_GPIO_CLOCK 0x10 +#define CP2108_EF_IFC_DYNAMIC_SUSPEND 0x40 + /* CP2102N configuration array indices */ #define CP210X_2NCONFIG_CONFIG_VERSION_IDX 2 #define CP210X_2NCONFIG_GPIO_MODE_IDX 581 @@ -546,13 +588,25 @@ struct cp210x_single_port_config { #define CP2102N_QFN20_GPIO1_RS485_MODE BIT(4) #define CP2102N_QFN20_GPIO0_CLK_MODE BIT(6) -/* CP210X_VENDOR_SPECIFIC, CP210X_WRITE_LATCH call writes these 0x2 bytes. */ +/* + * CP210X_VENDOR_SPECIFIC, CP210X_WRITE_LATCH call writes these 0x02 bytes + * for CP2102N, CP2103, CP2104 and CP2105. + */ struct cp210x_gpio_write { u8 mask; u8 state; }; /* + * CP210X_VENDOR_SPECIFIC, CP210X_WRITE_LATCH call writes these 0x04 bytes + * for CP2108. + */ +struct cp210x_gpio_write16 { + __le16 mask; + __le16 state; +}; + +/* * Helper to get interface number when we only have struct usb_serial. */ static u8 cp210x_interface_num(struct usb_serial *serial) @@ -1434,52 +1488,84 @@ static int cp210x_gpio_get(struct gpio_chip *gc, unsigned int gpio) { struct usb_serial *serial = gpiochip_get_data(gc); struct cp210x_serial_private *priv = usb_get_serial_data(serial); - u8 req_type = REQTYPE_DEVICE_TO_HOST; + u8 req_type; + u16 mask; int result; - u8 buf; - - if (priv->partnum == CP210X_PARTNUM_CP2105) - req_type = REQTYPE_INTERFACE_TO_HOST; + int len; result = usb_autopm_get_interface(serial->interface); if (result) return result; - result = cp210x_read_vendor_block(serial, req_type, - CP210X_READ_LATCH, &buf, sizeof(buf)); + switch (priv->partnum) { + case CP210X_PARTNUM_CP2105: + req_type = REQTYPE_INTERFACE_TO_HOST; + len = 1; + break; + case CP210X_PARTNUM_CP2108: + req_type = REQTYPE_INTERFACE_TO_HOST; + len = 2; + break; + default: + req_type = REQTYPE_DEVICE_TO_HOST; + len = 1; + break; + } + + mask = 0; + result = cp210x_read_vendor_block(serial, req_type, CP210X_READ_LATCH, + &mask, len); + usb_autopm_put_interface(serial->interface); + if (result < 0) return result; - return !!(buf & BIT(gpio)); + le16_to_cpus(&mask); + + return !!(mask & BIT(gpio)); } static void cp210x_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value) { struct usb_serial *serial = gpiochip_get_data(gc); struct cp210x_serial_private *priv = usb_get_serial_data(serial); + struct cp210x_gpio_write16 buf16; struct cp210x_gpio_write buf; + u16 mask, state; + u16 wIndex; int result; if (value == 1) - buf.state = BIT(gpio); + state = BIT(gpio); else - buf.state = 0; + state = 0; - buf.mask = BIT(gpio); + mask = BIT(gpio); result = usb_autopm_get_interface(serial->interface); if (result) goto out; - if (priv->partnum == CP210X_PARTNUM_CP2105) { + switch (priv->partnum) { + case CP210X_PARTNUM_CP2105: + buf.mask = (u8)mask; + buf.state = (u8)state; result = cp210x_write_vendor_block(serial, REQTYPE_HOST_TO_INTERFACE, CP210X_WRITE_LATCH, &buf, sizeof(buf)); - } else { - u16 wIndex = buf.state << 8 | buf.mask; - + break; + case CP210X_PARTNUM_CP2108: + buf16.mask = cpu_to_le16(mask); + buf16.state = cpu_to_le16(state); + result = cp210x_write_vendor_block(serial, + REQTYPE_HOST_TO_INTERFACE, + CP210X_WRITE_LATCH, &buf16, + sizeof(buf16)); + break; + default: + wIndex = state << 8 | mask; result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), CP210X_VENDOR_SPECIFIC, @@ -1487,6 +1573,7 @@ static void cp210x_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value) CP210X_WRITE_LATCH, wIndex, NULL, 0, USB_CTRL_SET_TIMEOUT); + break; } usb_autopm_put_interface(serial->interface); @@ -1696,6 +1783,61 @@ static int cp2104_gpioconf_init(struct usb_serial *serial) return 0; } +static int cp2108_gpio_init(struct usb_serial *serial) +{ + struct cp210x_serial_private *priv = usb_get_serial_data(serial); + struct cp210x_quad_port_config config; + u16 gpio_latch; + int result; + u8 i; + + result = cp210x_read_vendor_block(serial, REQTYPE_DEVICE_TO_HOST, + CP210X_GET_PORTCONFIG, &config, + sizeof(config)); + if (result < 0) + return result; + + priv->gc.ngpio = 16; + priv->gpio_pushpull = le16_to_cpu(config.reset_state.gpio_mode_pb1); + gpio_latch = le16_to_cpu(config.reset_state.gpio_latch_pb1); + + /* + * Mark all pins which are not in GPIO mode. + * + * Refer to table 9.1 "GPIO Mode alternate Functions" in the datasheet: + * https://www.silabs.com/documents/public/data-sheets/cp2108-datasheet.pdf + * + * Alternate functions of GPIO0 to GPIO3 are determine by enhancedfxn_ifc[0] + * and the similarly for the other pins; enhancedfxn_ifc[1]: GPIO4 to GPIO7, + * enhancedfxn_ifc[2]: GPIO8 to GPIO11, enhancedfxn_ifc[3]: GPIO12 to GPIO15. + */ + for (i = 0; i < 4; i++) { + if (config.enhancedfxn_ifc[i] & CP2108_EF_IFC_GPIO_TXLED) + priv->gpio_altfunc |= BIT(i * 4); + if (config.enhancedfxn_ifc[i] & CP2108_EF_IFC_GPIO_RXLED) + priv->gpio_altfunc |= BIT((i * 4) + 1); + if (config.enhancedfxn_ifc[i] & CP2108_EF_IFC_GPIO_RS485) + priv->gpio_altfunc |= BIT((i * 4) + 2); + if (config.enhancedfxn_ifc[i] & CP2108_EF_IFC_GPIO_CLOCK) + priv->gpio_altfunc |= BIT((i * 4) + 3); + } + + /* + * Like CP2102N, CP2108 has also no strict input and output pin + * modes. Do the same input mode emulation as CP2102N. + */ + for (i = 0; i < priv->gc.ngpio; ++i) { + /* + * Set direction to "input" iff pin is open-drain and reset + * value is 1. + */ + if (!(priv->gpio_pushpull & BIT(i)) && (gpio_latch & BIT(i))) + priv->gpio_input |= BIT(i); + } + + return 0; +} + static int cp2102n_gpioconf_init(struct usb_serial *serial) { struct cp210x_serial_private *priv = usb_get_serial_data(serial); @@ -1812,6 +1954,15 @@ static int cp210x_gpio_init(struct usb_serial *serial) case CP210X_PARTNUM_CP2105: result = cp2105_gpioconf_init(serial); break; + case CP210X_PARTNUM_CP2108: + /* + * The GPIOs are not tied to any specific port so only register + * once for interface 0. + */ + if (cp210x_interface_num(serial) != 0) + return 0; + result = cp2108_gpio_init(serial); + break; case CP210X_PARTNUM_CP2102N_QFN28: case CP210X_PARTNUM_CP2102N_QFN24: case CP210X_PARTNUM_CP2102N_QFN20: diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index cf389224d528..51e5aac3bf4c 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -53,7 +53,7 @@ static int cyberjack_open(struct tty_struct *tty, static void cyberjack_close(struct usb_serial_port *port); static int cyberjack_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); -static int cyberjack_write_room(struct tty_struct *tty); +static unsigned int cyberjack_write_room(struct tty_struct *tty); static void cyberjack_read_int_callback(struct urb *urb); static void cyberjack_read_bulk_callback(struct urb *urb); static void cyberjack_write_bulk_callback(struct urb *urb); @@ -240,7 +240,7 @@ static int cyberjack_write(struct tty_struct *tty, return count; } -static int cyberjack_write_room(struct tty_struct *tty) +static unsigned int cyberjack_write_room(struct tty_struct *tty) { /* FIXME: .... */ return CYBERJACK_LOCAL_BUF_SIZE; diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 166ee2286fda..6b18990258c3 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -122,14 +122,14 @@ static void cypress_dtr_rts(struct usb_serial_port *port, int on); static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); static void cypress_send(struct usb_serial_port *port); -static int cypress_write_room(struct tty_struct *tty); +static unsigned int cypress_write_room(struct tty_struct *tty); static void cypress_earthmate_init_termios(struct tty_struct *tty); static void cypress_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old); static int cypress_tiocmget(struct tty_struct *tty); static int cypress_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); -static int cypress_chars_in_buffer(struct tty_struct *tty); +static unsigned int cypress_chars_in_buffer(struct tty_struct *tty); static void cypress_throttle(struct tty_struct *tty); static void cypress_unthrottle(struct tty_struct *tty); static void cypress_set_dead(struct usb_serial_port *port); @@ -326,7 +326,7 @@ static int cypress_serial_control(struct tty_struct *tty, /* fill the feature_buffer with new configuration */ put_unaligned_le32(new_baudrate, feature_buffer); - feature_buffer[4] |= data_bits; /* assign data bits in 2 bit space ( max 3 ) */ + feature_buffer[4] |= data_bits - 5; /* assign data bits in 2 bit space ( max 3 ) */ /* 1 bit gap */ feature_buffer[4] |= (stop_bits << 3); /* assign stop bits in 1 bit space */ feature_buffer[4] |= (parity_enable << 4); /* assign parity flag in 1 bit space */ @@ -789,18 +789,18 @@ send: /* returns how much space is available in the soft buffer */ -static int cypress_write_room(struct tty_struct *tty) +static unsigned int cypress_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); - int room = 0; + unsigned int room; unsigned long flags; spin_lock_irqsave(&priv->lock, flags); room = kfifo_avail(&priv->write_fifo); spin_unlock_irqrestore(&priv->lock, flags); - dev_dbg(&port->dev, "%s - returns %d\n", __func__, room); + dev_dbg(&port->dev, "%s - returns %u\n", __func__, room); return room; } @@ -887,23 +887,8 @@ static void cypress_set_termios(struct tty_struct *tty, } else parity_enable = parity_type = 0; - switch (cflag & CSIZE) { - case CS5: - data_bits = 0; - break; - case CS6: - data_bits = 1; - break; - case CS7: - data_bits = 2; - break; - case CS8: - data_bits = 3; - break; - default: - dev_err(dev, "%s - CSIZE was set, but not CS5-CS8\n", __func__); - data_bits = 3; - } + data_bits = tty_get_char_size(cflag); + spin_lock_irqsave(&priv->lock, flags); oldlines = priv->line_control; if ((cflag & CBAUD) == B0) { @@ -970,18 +955,18 @@ static void cypress_set_termios(struct tty_struct *tty, /* returns amount of data still left in soft buffer */ -static int cypress_chars_in_buffer(struct tty_struct *tty) +static unsigned int cypress_chars_in_buffer(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); - int chars = 0; + unsigned int chars; unsigned long flags; spin_lock_irqsave(&priv->lock, flags); chars = kfifo_len(&priv->write_fifo); spin_unlock_irqrestore(&priv->lock, flags); - dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars); + dev_dbg(&port->dev, "%s - returns %u\n", __func__, chars); return chars; } diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 8b2f06539f2c..af65eb863d70 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -223,8 +223,8 @@ static int digi_tiocmset(struct tty_struct *tty, unsigned int set, static int digi_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); static void digi_write_bulk_callback(struct urb *urb); -static int digi_write_room(struct tty_struct *tty); -static int digi_chars_in_buffer(struct tty_struct *tty); +static unsigned int digi_write_room(struct tty_struct *tty); +static unsigned int digi_chars_in_buffer(struct tty_struct *tty); static int digi_open(struct tty_struct *tty, struct usb_serial_port *port); static void digi_close(struct usb_serial_port *port); static void digi_dtr_rts(struct usb_serial_port *port, int on); @@ -372,7 +372,7 @@ static int digi_write_oob_command(struct usb_serial_port *port, int len; struct usb_serial_port *oob_port = (struct usb_serial_port *)((struct digi_serial *)(usb_get_serial_data(port->serial)))->ds_oob_port; struct digi_port *oob_priv = usb_get_serial_port_data(oob_port); - unsigned long flags = 0; + unsigned long flags; dev_dbg(&port->dev, "digi_write_oob_command: TOP: port=%d, count=%d\n", @@ -430,7 +430,7 @@ static int digi_write_inb_command(struct usb_serial_port *port, int len; struct digi_port *priv = usb_get_serial_port_data(port); unsigned char *data = port->write_urb->transfer_buffer; - unsigned long flags = 0; + unsigned long flags; dev_dbg(&port->dev, "digi_write_inb_command: TOP: port=%d, count=%d\n", priv->dp_port_num, count); @@ -511,8 +511,7 @@ static int digi_set_modem_signals(struct usb_serial_port *port, struct usb_serial_port *oob_port = (struct usb_serial_port *) ((struct digi_serial *)(usb_get_serial_data(port->serial)))->ds_oob_port; struct digi_port *oob_priv = usb_get_serial_port_data(oob_port); unsigned char *data = oob_port->write_urb->transfer_buffer; - unsigned long flags = 0; - + unsigned long flags; dev_dbg(&port->dev, "digi_set_modem_signals: TOP: port=%d, modem_signals=0x%x\n", @@ -577,7 +576,7 @@ static int digi_transmit_idle(struct usb_serial_port *port, int ret; unsigned char buf[2]; struct digi_port *priv = usb_get_serial_port_data(port); - unsigned long flags = 0; + unsigned long flags; spin_lock_irqsave(&priv->dp_port_lock, flags); priv->dp_transmit_idle = 0; @@ -887,7 +886,7 @@ static int digi_write(struct tty_struct *tty, struct usb_serial_port *port, int ret, data_len, new_len; struct digi_port *priv = usb_get_serial_port_data(port); unsigned char *data = port->write_urb->transfer_buffer; - unsigned long flags = 0; + unsigned long flags; dev_dbg(&port->dev, "digi_write: TOP: port=%d, count=%d\n", priv->dp_port_num, count); @@ -1020,12 +1019,12 @@ static void digi_write_bulk_callback(struct urb *urb) tty_port_tty_wakeup(&port->port); } -static int digi_write_room(struct tty_struct *tty) +static unsigned int digi_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct digi_port *priv = usb_get_serial_port_data(port); - int room; - unsigned long flags = 0; + unsigned long flags; + unsigned int room; spin_lock_irqsave(&priv->dp_port_lock, flags); @@ -1035,27 +1034,28 @@ static int digi_write_room(struct tty_struct *tty) room = port->bulk_out_size - 2 - priv->dp_out_buf_len; spin_unlock_irqrestore(&priv->dp_port_lock, flags); - dev_dbg(&port->dev, "digi_write_room: port=%d, room=%d\n", priv->dp_port_num, room); + dev_dbg(&port->dev, "digi_write_room: port=%d, room=%u\n", priv->dp_port_num, room); return room; } -static int digi_chars_in_buffer(struct tty_struct *tty) +static unsigned int digi_chars_in_buffer(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct digi_port *priv = usb_get_serial_port_data(port); + unsigned long flags; + unsigned int chars; - if (priv->dp_write_urb_in_use) { - dev_dbg(&port->dev, "digi_chars_in_buffer: port=%d, chars=%d\n", - priv->dp_port_num, port->bulk_out_size - 2); - /* return(port->bulk_out_size - 2); */ - return 256; - } else { - dev_dbg(&port->dev, "digi_chars_in_buffer: port=%d, chars=%d\n", - priv->dp_port_num, priv->dp_out_buf_len); - return priv->dp_out_buf_len; - } + spin_lock_irqsave(&priv->dp_port_lock, flags); + if (priv->dp_write_urb_in_use) + chars = port->bulk_out_size - 2; + else + chars = priv->dp_out_buf_len; + spin_unlock_irqrestore(&priv->dp_port_lock, flags); + dev_dbg(&port->dev, "%s: port=%d, chars=%d\n", __func__, + priv->dp_port_num, chars); + return chars; } static void digi_dtr_rts(struct usb_serial_port *port, int on) diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 50e8bdc77e71..756d1ac7e96f 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -1113,7 +1113,7 @@ static int garmin_write(struct tty_struct *tty, struct usb_serial_port *port, } -static int garmin_write_room(struct tty_struct *tty) +static unsigned int garmin_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; /* diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index d10aa3d2ee49..15b6dee3a8e5 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -230,11 +230,11 @@ int usb_serial_generic_write(struct tty_struct *tty, } EXPORT_SYMBOL_GPL(usb_serial_generic_write); -int usb_serial_generic_write_room(struct tty_struct *tty) +unsigned int usb_serial_generic_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; unsigned long flags; - int room; + unsigned int room; if (!port->bulk_out_size) return 0; @@ -243,15 +243,15 @@ int usb_serial_generic_write_room(struct tty_struct *tty) room = kfifo_avail(&port->write_fifo); spin_unlock_irqrestore(&port->lock, flags); - dev_dbg(&port->dev, "%s - returns %d\n", __func__, room); + dev_dbg(&port->dev, "%s - returns %u\n", __func__, room); return room; } -int usb_serial_generic_chars_in_buffer(struct tty_struct *tty) +unsigned int usb_serial_generic_chars_in_buffer(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; unsigned long flags; - int chars; + unsigned int chars; if (!port->bulk_out_size) return 0; @@ -260,7 +260,7 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty) chars = kfifo_len(&port->write_fifo) + port->tx_bytes; spin_unlock_irqrestore(&port->lock, flags); - dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars); + dev_dbg(&port->dev, "%s - returns %u\n", __func__, chars); return chars; } EXPORT_SYMBOL_GPL(usb_serial_generic_chars_in_buffer); diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index e6fe3882bf69..ea4edf5eed27 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -1351,33 +1351,21 @@ exit_send: /***************************************************************************** * edge_write_room * this function is called by the tty driver when it wants to know how - * many bytes of data we can accept for a specific port. If successful, - * we return the amount of room that we have for this port (the txCredits) - * otherwise we return a negative error number. + * many bytes of data we can accept for a specific port. *****************************************************************************/ -static int edge_write_room(struct tty_struct *tty) +static unsigned int edge_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); - int room; + unsigned int room; unsigned long flags; - if (edge_port == NULL) - return 0; - if (edge_port->closePending) - return 0; - - if (!edge_port->open) { - dev_dbg(&port->dev, "%s - port not opened\n", __func__); - return 0; - } - /* total of both buffers is still txCredit */ spin_lock_irqsave(&edge_port->ep_lock, flags); room = edge_port->txCredits - edge_port->txfifo.count; spin_unlock_irqrestore(&edge_port->ep_lock, flags); - dev_dbg(&port->dev, "%s - returns %d\n", __func__, room); + dev_dbg(&port->dev, "%s - returns %u\n", __func__, room); return room; } @@ -1387,33 +1375,20 @@ static int edge_write_room(struct tty_struct *tty) * this function is called by the tty driver when it wants to know how * many bytes of data we currently have outstanding in the port (data that * has been written, but hasn't made it out the port yet) - * If successful, we return the number of bytes left to be written in the - * system, - * Otherwise we return a negative error number. *****************************************************************************/ -static int edge_chars_in_buffer(struct tty_struct *tty) +static unsigned int edge_chars_in_buffer(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); - int num_chars; + unsigned int num_chars; unsigned long flags; - if (edge_port == NULL) - return 0; - if (edge_port->closePending) - return 0; - - if (!edge_port->open) { - dev_dbg(&port->dev, "%s - port not opened\n", __func__); - return 0; - } - spin_lock_irqsave(&edge_port->ep_lock, flags); num_chars = edge_port->maxTxCredits - edge_port->txCredits + edge_port->txfifo.count; spin_unlock_irqrestore(&edge_port->ep_lock, flags); if (num_chars) { - dev_dbg(&port->dev, "%s - returns %d\n", __func__, num_chars); + dev_dbg(&port->dev, "%s - returns %u\n", __func__, num_chars); } return num_chars; diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 39503fdccebf..84b848d2794e 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2067,11 +2067,11 @@ static void edge_send(struct usb_serial_port *port, struct tty_struct *tty) tty_wakeup(tty); } -static int edge_write_room(struct tty_struct *tty) +static unsigned int edge_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); - int room = 0; + unsigned int room; unsigned long flags; if (edge_port == NULL) @@ -2083,15 +2083,15 @@ static int edge_write_room(struct tty_struct *tty) room = kfifo_avail(&port->write_fifo); spin_unlock_irqrestore(&edge_port->ep_lock, flags); - dev_dbg(&port->dev, "%s - returns %d\n", __func__, room); + dev_dbg(&port->dev, "%s - returns %u\n", __func__, room); return room; } -static int edge_chars_in_buffer(struct tty_struct *tty) +static unsigned int edge_chars_in_buffer(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); - int chars = 0; + unsigned int chars; unsigned long flags; if (edge_port == NULL) return 0; @@ -2100,7 +2100,7 @@ static int edge_chars_in_buffer(struct tty_struct *tty) chars = kfifo_len(&port->write_fifo); spin_unlock_irqrestore(&edge_port->ep_lock, flags); - dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars); + dev_dbg(&port->dev, "%s - returns %u\n", __func__, chars); return chars; } diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 172261a908d8..7b44dbea95cd 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -47,7 +47,7 @@ static int xbof = -1; static int ir_startup (struct usb_serial *serial); static int ir_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); -static int ir_write_room(struct tty_struct *tty); +static unsigned int ir_write_room(struct tty_struct *tty); static void ir_write_bulk_callback(struct urb *urb); static void ir_process_read_urb(struct urb *urb); static void ir_set_termios(struct tty_struct *tty, @@ -339,10 +339,10 @@ static void ir_write_bulk_callback(struct urb *urb) usb_serial_port_softint(port); } -static int ir_write_room(struct tty_struct *tty) +static unsigned int ir_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - int count = 0; + unsigned int count = 0; if (port->bulk_out_size == 0) return 0; diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index b04a029e3657..87b89c99d517 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -1453,13 +1453,13 @@ static void usa67_glocont_callback(struct urb *urb) } } -static int keyspan_write_room(struct tty_struct *tty) +static unsigned int keyspan_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct keyspan_port_private *p_priv; const struct keyspan_device_details *d_details; int flip; - int data_len; + unsigned int data_len; struct urb *this_urb; p_priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index a9bc546626ab..4ed8b8b0a361 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -53,7 +53,7 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port); static void kobil_close(struct usb_serial_port *port); static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); -static int kobil_write_room(struct tty_struct *tty); +static unsigned int kobil_write_room(struct tty_struct *tty); static int kobil_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); static int kobil_tiocmget(struct tty_struct *tty); @@ -358,7 +358,7 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, } -static int kobil_write_room(struct tty_struct *tty) +static unsigned int kobil_write_room(struct tty_struct *tty) { /* FIXME */ return 8; diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index f9ce9e7b9b80..30ab565e0738 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -109,9 +109,9 @@ static void metrousb_read_int_callback(struct urb *urb) struct usb_serial_port *port = urb->context; struct metrousb_private *metro_priv = usb_get_serial_port_data(port); unsigned char *data = urb->transfer_buffer; + unsigned long flags; int throttled = 0; int result = 0; - unsigned long flags = 0; dev_dbg(&port->dev, "%s\n", __func__); @@ -171,7 +171,7 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) { struct usb_serial *serial = port->serial; struct metrousb_private *metro_priv = usb_get_serial_port_data(port); - unsigned long flags = 0; + unsigned long flags; int result = 0; /* Set the private data information for the port. */ @@ -268,7 +268,7 @@ static void metrousb_throttle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct metrousb_private *metro_priv = usb_get_serial_port_data(port); - unsigned long flags = 0; + unsigned long flags; /* Set the private information for the port to stop reading data. */ spin_lock_irqsave(&metro_priv->lock, flags); @@ -281,7 +281,7 @@ static int metrousb_tiocmget(struct tty_struct *tty) unsigned long control_state = 0; struct usb_serial_port *port = tty->driver_data; struct metrousb_private *metro_priv = usb_get_serial_port_data(port); - unsigned long flags = 0; + unsigned long flags; spin_lock_irqsave(&metro_priv->lock, flags); control_state = metro_priv->control_state; @@ -296,7 +296,7 @@ static int metrousb_tiocmset(struct tty_struct *tty, struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; struct metrousb_private *metro_priv = usb_get_serial_port_data(port); - unsigned long flags = 0; + unsigned long flags; unsigned long control_state = 0; dev_dbg(&port->dev, "%s - set=%d, clear=%d\n", __func__, set, clear); @@ -323,7 +323,7 @@ static void metrousb_unthrottle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct metrousb_private *metro_priv = usb_get_serial_port_data(port); - unsigned long flags = 0; + unsigned long flags; int result = 0; /* Set the private information for the port to resume reading data. */ diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 6ee83886e2c9..227f43d2bd56 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -945,27 +945,20 @@ static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port) * this function is called by the tty driver when it wants to know how many * bytes of data we currently have outstanding in the port (data that has * been written, but hasn't made it out the port yet) - * If successful, we return the number of bytes left to be written in the - * system, - * Otherwise we return a negative error number. */ -static int mos7720_chars_in_buffer(struct tty_struct *tty) +static unsigned int mos7720_chars_in_buffer(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; + struct moschip_port *mos7720_port = usb_get_serial_port_data(port); int i; - int chars = 0; - struct moschip_port *mos7720_port; - - mos7720_port = usb_get_serial_port_data(port); - if (mos7720_port == NULL) - return 0; + unsigned int chars = 0; for (i = 0; i < NUM_URBS; ++i) { if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status == -EINPROGRESS) chars += URB_TRANSFER_BUFFER_SIZE; } - dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars); + dev_dbg(&port->dev, "%s - returns %u\n", __func__, chars); return chars; } @@ -1030,20 +1023,14 @@ static void mos7720_break(struct tty_struct *tty, int break_state) * mos7720_write_room * this function is called by the tty driver when it wants to know how many * bytes of data we can accept for a specific port. - * If successful, we return the amount of room that we have for this port - * Otherwise we return a negative error number. */ -static int mos7720_write_room(struct tty_struct *tty) +static unsigned int mos7720_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - struct moschip_port *mos7720_port; - int room = 0; + struct moschip_port *mos7720_port = usb_get_serial_port_data(port); + unsigned int room = 0; int i; - mos7720_port = usb_get_serial_port_data(port); - if (mos7720_port == NULL) - return 0; - /* FIXME: Locking */ for (i = 0; i < NUM_URBS; ++i) { if (mos7720_port->write_urb_pool[i] && @@ -1051,7 +1038,7 @@ static int mos7720_write_room(struct tty_struct *tty) room += URB_TRANSFER_BUFFER_SIZE; } - dev_dbg(&port->dev, "%s - returns %d\n", __func__, room); + dev_dbg(&port->dev, "%s - returns %u\n", __func__, room); return room; } diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 28e4093794e0..d7fe33ca73e4 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -730,17 +730,14 @@ err: * this function is called by the tty driver when it wants to know how many * bytes of data we currently have outstanding in the port (data that has * been written, but hasn't made it out the port yet) - * If successful, we return the number of bytes left to be written in the - * system, - * Otherwise we return zero. *****************************************************************************/ -static int mos7840_chars_in_buffer(struct tty_struct *tty) +static unsigned int mos7840_chars_in_buffer(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct moschip_port *mos7840_port = usb_get_serial_port_data(port); int i; - int chars = 0; + unsigned int chars = 0; unsigned long flags; spin_lock_irqsave(&mos7840_port->pool_lock, flags); @@ -751,7 +748,7 @@ static int mos7840_chars_in_buffer(struct tty_struct *tty) } } spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); - dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars); + dev_dbg(&port->dev, "%s - returns %u\n", __func__, chars); return chars; } @@ -814,16 +811,14 @@ static void mos7840_break(struct tty_struct *tty, int break_state) * mos7840_write_room * this function is called by the tty driver when it wants to know how many * bytes of data we can accept for a specific port. - * If successful, we return the amount of room that we have for this port - * Otherwise we return a negative error number. *****************************************************************************/ -static int mos7840_write_room(struct tty_struct *tty) +static unsigned int mos7840_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct moschip_port *mos7840_port = usb_get_serial_port_data(port); int i; - int room = 0; + unsigned int room = 0; unsigned long flags; spin_lock_irqsave(&mos7840_port->pool_lock, flags); @@ -834,7 +829,7 @@ static int mos7840_write_room(struct tty_struct *tty) spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); room = (room == 0) ? 0 : room - URB_TRANSFER_BUFFER_SIZE + 1; - dev_dbg(&mos7840_port->port->dev, "%s - returns %d\n", __func__, room); + dev_dbg(&mos7840_port->port->dev, "%s - returns %u\n", __func__, room); return room; } diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 40c713fae0c3..aed28c35caff 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -267,7 +267,7 @@ error_no_buffer: return ret; } -static int opticon_write_room(struct tty_struct *tty) +static unsigned int opticon_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct opticon_private *priv = usb_get_serial_port_data(port); @@ -289,12 +289,12 @@ static int opticon_write_room(struct tty_struct *tty) return 2048; } -static int opticon_chars_in_buffer(struct tty_struct *tty) +static unsigned int opticon_chars_in_buffer(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct opticon_private *priv = usb_get_serial_port_data(port); unsigned long flags; - int count; + unsigned int count; spin_lock_irqsave(&priv->lock, flags); count = priv->outstanding_bytes; diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 65cd0341fa78..a5caedbe72e2 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -126,8 +126,8 @@ static void oti6858_read_bulk_callback(struct urb *urb); static void oti6858_write_bulk_callback(struct urb *urb); static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); -static int oti6858_write_room(struct tty_struct *tty); -static int oti6858_chars_in_buffer(struct tty_struct *tty); +static unsigned int oti6858_write_room(struct tty_struct *tty); +static unsigned int oti6858_chars_in_buffer(struct tty_struct *tty); static int oti6858_tiocmget(struct tty_struct *tty); static int oti6858_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); @@ -363,10 +363,10 @@ static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port, return count; } -static int oti6858_write_room(struct tty_struct *tty) +static unsigned int oti6858_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - int room = 0; + unsigned int room; unsigned long flags; spin_lock_irqsave(&port->lock, flags); @@ -376,10 +376,10 @@ static int oti6858_write_room(struct tty_struct *tty) return room; } -static int oti6858_chars_in_buffer(struct tty_struct *tty) +static unsigned int oti6858_chars_in_buffer(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - int chars = 0; + unsigned int chars; unsigned long flags; spin_lock_irqsave(&port->lock, flags); diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 940050c31482..2f2f5047452b 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -789,20 +789,7 @@ static void pl2303_set_termios(struct tty_struct *tty, pl2303_get_line_request(port, buf); - switch (C_CSIZE(tty)) { - case CS5: - buf[6] = 5; - break; - case CS6: - buf[6] = 6; - break; - case CS7: - buf[6] = 7; - break; - default: - case CS8: - buf[6] = 8; - } + buf[6] = tty_get_char_size(tty->termios.c_cflag); dev_dbg(&port->dev, "data bits = %d\n", buf[6]); /* For reference buf[0]:buf[3] baud rate value */ diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 067690dac24c..971907f083a3 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -870,12 +870,12 @@ static void qt2_update_lsr(struct usb_serial_port *port, unsigned char *ch) } -static int qt2_write_room(struct tty_struct *tty) +static unsigned int qt2_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct qt2_port_private *port_priv; - unsigned long flags = 0; - int r; + unsigned long flags; + unsigned int r; port_priv = usb_get_serial_port_data(port); diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 54e16ffc30a0..4b49b7c33364 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -613,7 +613,7 @@ static void sierra_instat_callback(struct urb *urb) } } -static int sierra_write_room(struct tty_struct *tty) +static unsigned int sierra_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct sierra_port_private *portdata = usb_get_serial_port_data(port); @@ -632,19 +632,19 @@ static int sierra_write_room(struct tty_struct *tty) return 2048; } -static int sierra_chars_in_buffer(struct tty_struct *tty) +static unsigned int sierra_chars_in_buffer(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct sierra_port_private *portdata = usb_get_serial_port_data(port); unsigned long flags; - int chars; + unsigned int chars; /* NOTE: This overcounts somewhat. */ spin_lock_irqsave(&portdata->lock, flags); chars = portdata->outstanding_urbs * MAX_TRANSFER; spin_unlock_irqrestore(&portdata->lock, flags); - dev_dbg(&port->dev, "%s - %d\n", __func__, chars); + dev_dbg(&port->dev, "%s - %u\n", __func__, chars); return chars; } diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 310db5abea9d..18c0bd853392 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -308,8 +308,8 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port); static void ti_close(struct usb_serial_port *port); static int ti_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *data, int count); -static int ti_write_room(struct tty_struct *tty); -static int ti_chars_in_buffer(struct tty_struct *tty); +static unsigned int ti_write_room(struct tty_struct *tty); +static unsigned int ti_chars_in_buffer(struct tty_struct *tty); static bool ti_tx_empty(struct usb_serial_port *port); static void ti_throttle(struct tty_struct *tty); static void ti_unthrottle(struct tty_struct *tty); @@ -813,34 +813,34 @@ static int ti_write(struct tty_struct *tty, struct usb_serial_port *port, } -static int ti_write_room(struct tty_struct *tty) +static unsigned int ti_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct ti_port *tport = usb_get_serial_port_data(port); - int room = 0; + unsigned int room; unsigned long flags; spin_lock_irqsave(&tport->tp_lock, flags); room = kfifo_avail(&port->write_fifo); spin_unlock_irqrestore(&tport->tp_lock, flags); - dev_dbg(&port->dev, "%s - returns %d\n", __func__, room); + dev_dbg(&port->dev, "%s - returns %u\n", __func__, room); return room; } -static int ti_chars_in_buffer(struct tty_struct *tty) +static unsigned int ti_chars_in_buffer(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct ti_port *tport = usb_get_serial_port_data(port); - int chars = 0; + unsigned int chars; unsigned long flags; spin_lock_irqsave(&tport->tp_lock, flags); chars = kfifo_len(&port->write_fifo); spin_unlock_irqrestore(&tport->tp_lock, flags); - dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars); + dev_dbg(&port->dev, "%s - returns %u\n", __func__, chars); return chars; } diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 98b33b1b5357..eeb441c77207 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -376,7 +376,7 @@ exit: return retval; } -static int serial_write_room(struct tty_struct *tty) +static unsigned int serial_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; @@ -385,7 +385,7 @@ static int serial_write_room(struct tty_struct *tty) return port->serial->type->write_room(tty); } -static int serial_chars_in_buffer(struct tty_struct *tty) +static unsigned int serial_chars_in_buffer(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h index b5331d03092f..519101945769 100644 --- a/drivers/usb/serial/usb-wwan.h +++ b/drivers/usb/serial/usb-wwan.h @@ -11,13 +11,13 @@ extern int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port); extern void usb_wwan_close(struct usb_serial_port *port); extern int usb_wwan_port_probe(struct usb_serial_port *port); extern void usb_wwan_port_remove(struct usb_serial_port *port); -extern int usb_wwan_write_room(struct tty_struct *tty); +extern unsigned int usb_wwan_write_room(struct tty_struct *tty); extern int usb_wwan_tiocmget(struct tty_struct *tty); extern int usb_wwan_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); extern int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); -extern int usb_wwan_chars_in_buffer(struct tty_struct *tty); +extern unsigned int usb_wwan_chars_in_buffer(struct tty_struct *tty); #ifdef CONFIG_PM extern int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message); extern int usb_wwan_resume(struct usb_serial *serial); diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 3eb72c59ede6..cb01283d4d15 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -278,12 +278,12 @@ static void usb_wwan_outdat_callback(struct urb *urb) } } -int usb_wwan_write_room(struct tty_struct *tty) +unsigned int usb_wwan_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct usb_wwan_port_private *portdata; int i; - int data_len = 0; + unsigned int data_len = 0; struct urb *this_urb; portdata = usb_get_serial_port_data(port); @@ -294,17 +294,17 @@ int usb_wwan_write_room(struct tty_struct *tty) data_len += OUT_BUFLEN; } - dev_dbg(&port->dev, "%s: %d\n", __func__, data_len); + dev_dbg(&port->dev, "%s: %u\n", __func__, data_len); return data_len; } EXPORT_SYMBOL(usb_wwan_write_room); -int usb_wwan_chars_in_buffer(struct tty_struct *tty) +unsigned int usb_wwan_chars_in_buffer(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct usb_wwan_port_private *portdata; int i; - int data_len = 0; + unsigned int data_len = 0; struct urb *this_urb; portdata = usb_get_serial_port_data(port); @@ -316,7 +316,7 @@ int usb_wwan_chars_in_buffer(struct tty_struct *tty) if (this_urb && test_bit(i, &portdata->out_busy)) data_len += this_urb->transfer_buffer_length; } - dev_dbg(&port->dev, "%s: %d\n", __func__, data_len); + dev_dbg(&port->dev, "%s: %u\n", __func__, data_len); return data_len; } EXPORT_SYMBOL(usb_wwan_chars_in_buffer); diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 5116ed9db3eb..da65d14c9ed5 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -625,14 +625,7 @@ static void firm_setup_port(struct tty_struct *tty) port_settings.port = port->port_number + 1; - /* get the byte size */ - switch (cflag & CSIZE) { - case CS5: port_settings.bits = 5; break; - case CS6: port_settings.bits = 6; break; - case CS7: port_settings.bits = 7; break; - default: - case CS8: port_settings.bits = 8; break; - } + port_settings.bits = tty_get_char_size(cflag); dev_dbg(dev, "%s - data bits = %d\n", __func__, port_settings.bits); /* determine the parity */ diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c index b9429c9f65f6..aeef453aa658 100644 --- a/drivers/usb/typec/class.c +++ b/drivers/usb/typec/class.c @@ -517,8 +517,10 @@ typec_register_altmode(struct device *parent, int ret; alt = kzalloc(sizeof(*alt), GFP_KERNEL); - if (!alt) + if (!alt) { + altmode_id_remove(parent, id); return ERR_PTR(-ENOMEM); + } alt->adev.svid = desc->svid; alt->adev.mode = desc->mode; diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c index 77dabd306ba8..c8340de0ed49 100644 --- a/drivers/usb/typec/mux.c +++ b/drivers/usb/typec/mux.c @@ -17,21 +17,12 @@ #include "class.h" #include "mux.h" -static bool dev_name_ends_with(struct device *dev, const char *suffix) -{ - const char *name = dev_name(dev); - const int name_len = strlen(name); - const int suffix_len = strlen(suffix); - - if (suffix_len > name_len) - return false; - - return strcmp(name + (name_len - suffix_len), suffix) == 0; -} - static int switch_fwnode_match(struct device *dev, const void *fwnode) { - return dev_fwnode(dev) == fwnode && dev_name_ends_with(dev, "-switch"); + if (!is_typec_switch(dev)) + return 0; + + return dev_fwnode(dev) == fwnode; } static void *typec_switch_match(struct fwnode_handle *fwnode, const char *id, @@ -39,9 +30,22 @@ static void *typec_switch_match(struct fwnode_handle *fwnode, const char *id, { struct device *dev; + /* + * Device graph (OF graph) does not give any means to identify the + * device type or the device class of the remote port parent that @fwnode + * represents, so in order to identify the type or the class of @fwnode + * an additional device property is needed. With typec switches the + * property is named "orientation-switch" (@id). The value of the device + * property is ignored. + */ if (id && !fwnode_property_present(fwnode, id)) return NULL; + /* + * At this point we are sure that @fwnode is a typec switch in all + * cases. If the switch hasn't yet been registered for some reason, the + * function "defers probe" for now. + */ dev = class_find_device(&typec_mux_class, NULL, fwnode, switch_fwnode_match); @@ -90,7 +94,7 @@ static void typec_switch_release(struct device *dev) kfree(to_typec_switch(dev)); } -static const struct device_type typec_switch_dev_type = { +const struct device_type typec_switch_dev_type = { .name = "orientation_switch", .release = typec_switch_release, }; @@ -180,7 +184,10 @@ EXPORT_SYMBOL_GPL(typec_switch_get_drvdata); static int mux_fwnode_match(struct device *dev, const void *fwnode) { - return dev_fwnode(dev) == fwnode && dev_name_ends_with(dev, "-mux"); + if (!is_typec_mux(dev)) + return 0; + + return dev_fwnode(dev) == fwnode; } static void *typec_mux_match(struct fwnode_handle *fwnode, const char *id, @@ -295,7 +302,7 @@ static void typec_mux_release(struct device *dev) kfree(to_typec_mux(dev)); } -static const struct device_type typec_mux_dev_type = { +const struct device_type typec_mux_dev_type = { .name = "mode_switch", .release = typec_mux_release, }; diff --git a/drivers/usb/typec/mux.h b/drivers/usb/typec/mux.h index 4fd9426ee44f..b1d6e837cb74 100644 --- a/drivers/usb/typec/mux.h +++ b/drivers/usb/typec/mux.h @@ -18,4 +18,10 @@ struct typec_mux { #define to_typec_switch(_dev_) container_of(_dev_, struct typec_switch, dev) #define to_typec_mux(_dev_) container_of(_dev_, struct typec_mux, dev) +extern const struct device_type typec_switch_dev_type; +extern const struct device_type typec_mux_dev_type; + +#define is_typec_switch(dev) ((dev)->type == &typec_switch_dev_type) +#define is_typec_mux(dev) ((dev)->type == &typec_mux_dev_type) + #endif /* __USB_TYPEC_MUX__ */ diff --git a/drivers/usb/typec/mux/intel_pmc_mux.c b/drivers/usb/typec/mux/intel_pmc_mux.c index ffa8aa12d5f1..2cdd22130834 100644 --- a/drivers/usb/typec/mux/intel_pmc_mux.c +++ b/drivers/usb/typec/mux/intel_pmc_mux.c @@ -83,8 +83,6 @@ enum { /* * Input Output Manager (IOM) PORT STATUS */ -#define IOM_PORT_STATUS_OFFSET 0x560 - #define IOM_PORT_STATUS_ACTIVITY_TYPE_MASK GENMASK(9, 6) #define IOM_PORT_STATUS_ACTIVITY_TYPE_SHIFT 6 #define IOM_PORT_STATUS_ACTIVITY_TYPE_USB 0x03 @@ -144,6 +142,7 @@ struct pmc_usb { struct pmc_usb_port *port; struct acpi_device *iom_adev; void __iomem *iom_base; + u32 iom_port_status_offset; }; static void update_port_status(struct pmc_usb_port *port) @@ -153,7 +152,8 @@ static void update_port_status(struct pmc_usb_port *port) /* SoC expects the USB Type-C port numbers to start with 0 */ port_num = port->usb3_port - 1; - port->iom_status = readl(port->pmc->iom_base + IOM_PORT_STATUS_OFFSET + + port->iom_status = readl(port->pmc->iom_base + + port->pmc->iom_port_status_offset + port_num * sizeof(u32)); } @@ -559,14 +559,32 @@ static int is_memory(struct acpi_resource *res, void *data) return !acpi_dev_resource_memory(res, &r); } +/* IOM ACPI IDs and IOM_PORT_STATUS_OFFSET */ +static const struct acpi_device_id iom_acpi_ids[] = { + /* TigerLake */ + { "INTC1072", 0x560, }, + + /* AlderLake */ + { "INTC1079", 0x160, }, + {} +}; + static int pmc_usb_probe_iom(struct pmc_usb *pmc) { struct list_head resource_list; struct resource_entry *rentry; - struct acpi_device *adev; + static const struct acpi_device_id *dev_id; + struct acpi_device *adev = NULL; int ret; - adev = acpi_dev_get_first_match_dev("INTC1072", NULL, -1); + for (dev_id = &iom_acpi_ids[0]; dev_id->id[0]; dev_id++) { + if (acpi_dev_present(dev_id->id, NULL, -1)) { + pmc->iom_port_status_offset = (u32)dev_id->driver_data; + adev = acpi_dev_get_first_match_dev(dev_id->id, NULL, -1); + break; + } + } + if (!adev) return -ENODEV; diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c index 25b480752266..9858716698df 100644 --- a/drivers/usb/typec/tcpm/tcpci.c +++ b/drivers/usb/typec/tcpm/tcpci.c @@ -21,8 +21,12 @@ #define PD_RETRY_COUNT_DEFAULT 3 #define PD_RETRY_COUNT_3_0_OR_HIGHER 2 #define AUTO_DISCHARGE_DEFAULT_THRESHOLD_MV 3500 -#define AUTO_DISCHARGE_PD_HEADROOM_MV 850 -#define AUTO_DISCHARGE_PPS_HEADROOM_MV 1250 +#define VSINKPD_MIN_IR_DROP_MV 750 +#define VSRC_NEW_MIN_PERCENT 95 +#define VSRC_VALID_MIN_MV 500 +#define VPPS_NEW_MIN_PERCENT 95 +#define VPPS_VALID_MIN_MV 100 +#define VSINKDISCONNECT_PD_MIN_PERCENT 90 #define tcpc_presenting_rd(reg, cc) \ (!(TCPC_ROLE_CTRL_DRP & (reg)) && \ @@ -115,6 +119,33 @@ static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc) return 0; } +static int tcpci_apply_rc(struct tcpc_dev *tcpc, enum typec_cc_status cc, + enum typec_cc_polarity polarity) +{ + struct tcpci *tcpci = tcpc_to_tcpci(tcpc); + unsigned int reg; + int ret; + + ret = regmap_read(tcpci->regmap, TCPC_ROLE_CTRL, ®); + if (ret < 0) + return ret; + + /* + * APPLY_RC state is when ROLE_CONTROL.CC1 != ROLE_CONTROL.CC2 and vbus autodischarge on + * disconnect is disabled. Bail out when ROLE_CONTROL.CC1 != ROLE_CONTROL.CC2. + */ + if (((reg & (TCPC_ROLE_CTRL_CC2_MASK << TCPC_ROLE_CTRL_CC2_SHIFT)) >> + TCPC_ROLE_CTRL_CC2_SHIFT) != + ((reg & (TCPC_ROLE_CTRL_CC1_MASK << TCPC_ROLE_CTRL_CC1_SHIFT)) >> + TCPC_ROLE_CTRL_CC1_SHIFT)) + return 0; + + return regmap_update_bits(tcpci->regmap, TCPC_ROLE_CTRL, polarity == TYPEC_POLARITY_CC1 ? + TCPC_ROLE_CTRL_CC2_MASK << TCPC_ROLE_CTRL_CC2_SHIFT : + TCPC_ROLE_CTRL_CC1_MASK << TCPC_ROLE_CTRL_CC1_SHIFT, + TCPC_ROLE_CTRL_CC_OPEN); +} + static int tcpci_start_toggling(struct tcpc_dev *tcpc, enum typec_port_type port_type, enum typec_cc_status cc) @@ -324,11 +355,13 @@ static int tcpci_set_auto_vbus_discharge_threshold(struct tcpc_dev *dev, enum ty threshold = AUTO_DISCHARGE_DEFAULT_THRESHOLD_MV; } else if (mode == TYPEC_PWR_MODE_PD) { if (pps_active) - threshold = (95 * requested_vbus_voltage_mv / 100) - - AUTO_DISCHARGE_PD_HEADROOM_MV; + threshold = ((VPPS_NEW_MIN_PERCENT * requested_vbus_voltage_mv / 100) - + VSINKPD_MIN_IR_DROP_MV - VPPS_VALID_MIN_MV) * + VSINKDISCONNECT_PD_MIN_PERCENT / 100; else - threshold = (95 * requested_vbus_voltage_mv / 100) - - AUTO_DISCHARGE_PPS_HEADROOM_MV; + threshold = ((VSRC_NEW_MIN_PERCENT * requested_vbus_voltage_mv / 100) - + VSINKPD_MIN_IR_DROP_MV - VSRC_VALID_MIN_MV) * + VSINKDISCONNECT_PD_MIN_PERCENT / 100; } else { /* 3.5V for non-pd sink */ threshold = AUTO_DISCHARGE_DEFAULT_THRESHOLD_MV; @@ -728,6 +761,7 @@ struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data) tcpci->tcpc.get_vbus = tcpci_get_vbus; tcpci->tcpc.set_vbus = tcpci_set_vbus; tcpci->tcpc.set_cc = tcpci_set_cc; + tcpci->tcpc.apply_rc = tcpci_apply_rc; tcpci->tcpc.get_cc = tcpci_get_cc; tcpci->tcpc.set_polarity = tcpci_set_polarity; tcpci->tcpc.set_vconn = tcpci_set_vconn; diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 63470cf7f4cd..5b22a1c931a9 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -776,6 +776,34 @@ static void tcpm_set_cc(struct tcpm_port *port, enum typec_cc_status cc) port->tcpc->set_cc(port->tcpc, cc); } +static int tcpm_enable_auto_vbus_discharge(struct tcpm_port *port, bool enable) +{ + int ret = 0; + + if (port->tcpc->enable_auto_vbus_discharge) { + ret = port->tcpc->enable_auto_vbus_discharge(port->tcpc, enable); + tcpm_log_force(port, "%s vbus discharge ret:%d", enable ? "enable" : "disable", + ret); + if (!ret) + port->auto_vbus_discharge_enabled = enable; + } + + return ret; +} + +static void tcpm_apply_rc(struct tcpm_port *port) +{ + /* + * TCPCI: Move to APPLY_RC state to prevent disconnect during PR_SWAP + * when Vbus auto discharge on disconnect is enabled. + */ + if (port->tcpc->enable_auto_vbus_discharge && port->tcpc->apply_rc) { + tcpm_log(port, "Apply_RC"); + port->tcpc->apply_rc(port->tcpc, port->cc_req, port->polarity); + tcpm_enable_auto_vbus_discharge(port, false); + } +} + /* * Determine RP value to set based on maximum current supported * by a port if configured as source. @@ -2576,6 +2604,11 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, } else { next_state = SNK_WAIT_CAPABILITIES; } + + /* Threshold was relaxed before sending Request. Restore it back. */ + tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_PD, + port->pps_data.active, + port->supply_voltage); tcpm_set_state(port, next_state, 0); break; case SNK_NEGOTIATE_PPS_CAPABILITIES: @@ -2589,6 +2622,11 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, port->send_discover) port->vdm_sm_running = true; + /* Threshold was relaxed before sending Request. Restore it back. */ + tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_PD, + port->pps_data.active, + port->supply_voltage); + tcpm_set_state(port, SNK_READY, 0); break; case DR_SWAP_SEND: @@ -3308,6 +3346,12 @@ static int tcpm_pd_send_request(struct tcpm_port *port) if (ret < 0) return ret; + /* + * Relax the threshold as voltage will be adjusted after Accept Message plus tSrcTransition. + * It is safer to modify the threshold here. + */ + tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_USB, false, 0); + memset(&msg, 0, sizeof(msg)); msg.header = PD_HEADER_LE(PD_DATA_REQUEST, port->pwr_role, @@ -3405,6 +3449,9 @@ static int tcpm_pd_send_pps_request(struct tcpm_port *port) if (ret < 0) return ret; + /* Relax the threshold as voltage will be adjusted right after Accept Message. */ + tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_USB, false, 0); + memset(&msg, 0, sizeof(msg)); msg.header = PD_HEADER_LE(PD_DATA_REQUEST, port->pwr_role, @@ -3515,12 +3562,7 @@ static int tcpm_src_attach(struct tcpm_port *port) if (ret < 0) return ret; - if (port->tcpc->enable_auto_vbus_discharge) { - ret = port->tcpc->enable_auto_vbus_discharge(port->tcpc, true); - tcpm_log_force(port, "enable vbus discharge ret:%d", ret); - if (!ret) - port->auto_vbus_discharge_enabled = true; - } + tcpm_enable_auto_vbus_discharge(port, true); ret = tcpm_set_roles(port, true, TYPEC_SOURCE, tcpm_data_role_for_source(port)); if (ret < 0) @@ -3597,14 +3639,7 @@ static void tcpm_set_partner_usb_comm_capable(struct tcpm_port *port, bool capab static void tcpm_reset_port(struct tcpm_port *port) { - int ret; - - if (port->tcpc->enable_auto_vbus_discharge) { - ret = port->tcpc->enable_auto_vbus_discharge(port->tcpc, false); - tcpm_log_force(port, "Disable vbus discharge ret:%d", ret); - if (!ret) - port->auto_vbus_discharge_enabled = false; - } + tcpm_enable_auto_vbus_discharge(port, false); port->in_ams = false; port->ams = NONE_AMS; port->vdm_sm_running = false; @@ -3672,13 +3707,7 @@ static int tcpm_snk_attach(struct tcpm_port *port) if (ret < 0) return ret; - if (port->tcpc->enable_auto_vbus_discharge) { - tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_USB, false, VSAFE5V); - ret = port->tcpc->enable_auto_vbus_discharge(port->tcpc, true); - tcpm_log_force(port, "enable vbus discharge ret:%d", ret); - if (!ret) - port->auto_vbus_discharge_enabled = true; - } + tcpm_enable_auto_vbus_discharge(port, true); ret = tcpm_set_roles(port, true, TYPEC_SINK, tcpm_data_role_for_sink(port)); if (ret < 0) @@ -4186,6 +4215,10 @@ static void run_state_machine(struct tcpm_port *port) port->hard_reset_count = 0; ret = tcpm_pd_send_request(port); if (ret < 0) { + /* Restore back to the original state */ + tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_PD, + port->pps_data.active, + port->supply_voltage); /* Let the Source send capabilities again. */ tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0); } else { @@ -4196,6 +4229,10 @@ static void run_state_machine(struct tcpm_port *port) case SNK_NEGOTIATE_PPS_CAPABILITIES: ret = tcpm_pd_send_pps_request(port); if (ret < 0) { + /* Restore back to the original state */ + tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_PD, + port->pps_data.active, + port->supply_voltage); port->pps_status = ret; /* * If this was called due to updates to sink @@ -4515,6 +4552,7 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, ready_state(port), 0); break; case PR_SWAP_START: + tcpm_apply_rc(port); if (port->pwr_role == TYPEC_SOURCE) tcpm_set_state(port, PR_SWAP_SRC_SNK_TRANSITION_OFF, PD_T_SRC_TRANSITION); @@ -4554,6 +4592,7 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, ERROR_RECOVERY, PD_T_PS_SOURCE_ON_PRS); break; case PR_SWAP_SRC_SNK_SINK_ON: + tcpm_enable_auto_vbus_discharge(port, true); /* Set the vbus disconnect threshold for implicit contract */ tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_USB, false, VSAFE5V); tcpm_set_state(port, SNK_STARTUP, 0); @@ -4570,6 +4609,7 @@ static void run_state_machine(struct tcpm_port *port) PD_T_PS_SOURCE_OFF); break; case PR_SWAP_SNK_SRC_SOURCE_ON: + tcpm_enable_auto_vbus_discharge(port, true); tcpm_set_cc(port, tcpm_rp_cc(port)); tcpm_set_vbus(port, true); /* @@ -5198,6 +5238,10 @@ static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port) tcpm_set_state(port, SNK_UNATTACHED, 0); } break; + case PR_SWAP_SNK_SRC_SINK_OFF: + case PR_SWAP_SNK_SRC_SOURCE_ON: + /* Do nothing, vsafe0v is expected during transition */ + break; default: if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled) tcpm_set_state(port, SNK_UNATTACHED, 0); diff --git a/drivers/usb/typec/tcpm/wcove.c b/drivers/usb/typec/tcpm/wcove.c index 5d125339687a..20917d85d6f4 100644 --- a/drivers/usb/typec/tcpm/wcove.c +++ b/drivers/usb/typec/tcpm/wcove.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/** +/* * typec_wcove.c - WhiskeyCove PMIC USB Type-C PHY driver * * Copyright (C) 2017 Intel Corporation diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index b7d104c80d85..5ef5bd0e87cf 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -1219,7 +1219,7 @@ static int ucsi_init(struct ucsi *ucsi) goto err_reset; } - /* Allocate the connectors. Released in ucsi_unregister_ppm() */ + /* Allocate the connectors. Released in ucsi_unregister() */ ucsi->connector = kcalloc(ucsi->cap.num_connectors + 1, sizeof(*ucsi->connector), GFP_KERNEL); if (!ucsi->connector) { @@ -1280,7 +1280,7 @@ void *ucsi_get_drvdata(struct ucsi *ucsi) EXPORT_SYMBOL_GPL(ucsi_get_drvdata); /** - * ucsi_get_drvdata - Assign private driver data pointer + * ucsi_set_drvdata - Assign private driver data pointer * @ucsi: UCSI interface * @data: Private data pointer */ diff --git a/drivers/vdpa/ifcvf/ifcvf_base.c b/drivers/vdpa/ifcvf/ifcvf_base.c index 1a661ab45af5..6e197fe0fcf9 100644 --- a/drivers/vdpa/ifcvf/ifcvf_base.c +++ b/drivers/vdpa/ifcvf/ifcvf_base.c @@ -133,6 +133,8 @@ int ifcvf_init_hw(struct ifcvf_hw *hw, struct pci_dev *pdev) &hw->notify_off_multiplier); hw->notify_bar = cap.bar; hw->notify_base = get_cap_addr(hw, &cap); + hw->notify_base_pa = pci_resource_start(pdev, cap.bar) + + le32_to_cpu(cap.offset); IFCVF_DBG(pdev, "hw->notify_base = %p\n", hw->notify_base); break; @@ -161,6 +163,8 @@ next: notify_off = ifc_ioread16(&hw->common_cfg->queue_notify_off); hw->vring[i].notify_addr = hw->notify_base + notify_off * hw->notify_off_multiplier; + hw->vring[i].notify_pa = hw->notify_base_pa + + notify_off * hw->notify_off_multiplier; } hw->lm_cfg = hw->base[IFCVF_LM_BAR]; diff --git a/drivers/vdpa/ifcvf/ifcvf_base.h b/drivers/vdpa/ifcvf/ifcvf_base.h index 0111bfdeb342..2996db0da490 100644 --- a/drivers/vdpa/ifcvf/ifcvf_base.h +++ b/drivers/vdpa/ifcvf/ifcvf_base.h @@ -19,21 +19,9 @@ #include <uapi/linux/virtio_config.h> #include <uapi/linux/virtio_pci.h> -#define N3000_VENDOR_ID 0x1AF4 #define N3000_DEVICE_ID 0x1041 -#define N3000_SUBSYS_VENDOR_ID 0x8086 #define N3000_SUBSYS_DEVICE_ID 0x001A -#define C5000X_PL_VENDOR_ID 0x1AF4 -#define C5000X_PL_DEVICE_ID 0x1000 -#define C5000X_PL_SUBSYS_VENDOR_ID 0x8086 -#define C5000X_PL_SUBSYS_DEVICE_ID 0x0001 - -#define C5000X_PL_BLK_VENDOR_ID 0x1AF4 -#define C5000X_PL_BLK_DEVICE_ID 0x1001 -#define C5000X_PL_BLK_SUBSYS_VENDOR_ID 0x8086 -#define C5000X_PL_BLK_SUBSYS_DEVICE_ID 0x0002 - #define IFCVF_NET_SUPPORTED_FEATURES \ ((1ULL << VIRTIO_NET_F_MAC) | \ (1ULL << VIRTIO_F_ANY_LAYOUT) | \ @@ -73,6 +61,7 @@ struct vring_info { u16 last_avail_idx; bool ready; void __iomem *notify_addr; + phys_addr_t notify_pa; u32 irq; struct vdpa_callback cb; char msix_name[256]; @@ -87,6 +76,7 @@ struct ifcvf_hw { u8 notify_bar; /* Notificaiton bar address */ void __iomem *notify_base; + phys_addr_t notify_base_pa; u32 notify_off_multiplier; u64 req_features; u64 hw_features; diff --git a/drivers/vdpa/ifcvf/ifcvf_main.c b/drivers/vdpa/ifcvf/ifcvf_main.c index ab0ab5cf0f6e..21b78f1cd521 100644 --- a/drivers/vdpa/ifcvf/ifcvf_main.c +++ b/drivers/vdpa/ifcvf/ifcvf_main.c @@ -264,7 +264,7 @@ static int ifcvf_vdpa_get_vq_state(struct vdpa_device *vdpa_dev, u16 qid, { struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev); - state->avail_index = ifcvf_get_vq_state(vf, qid); + state->split.avail_index = ifcvf_get_vq_state(vf, qid); return 0; } @@ -273,7 +273,7 @@ static int ifcvf_vdpa_set_vq_state(struct vdpa_device *vdpa_dev, u16 qid, { struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev); - return ifcvf_set_vq_state(vf, qid, state->avail_index); + return ifcvf_set_vq_state(vf, qid, state->split.avail_index); } static void ifcvf_vdpa_set_vq_cb(struct vdpa_device *vdpa_dev, u16 qid, @@ -413,6 +413,21 @@ static int ifcvf_vdpa_get_vq_irq(struct vdpa_device *vdpa_dev, return vf->vring[qid].irq; } +static struct vdpa_notification_area ifcvf_get_vq_notification(struct vdpa_device *vdpa_dev, + u16 idx) +{ + struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev); + struct vdpa_notification_area area; + + area.addr = vf->vring[idx].notify_pa; + if (!vf->notify_off_multiplier) + area.size = PAGE_SIZE; + else + area.size = vf->notify_off_multiplier; + + return area; +} + /* * IFCVF currently does't have on-chip IOMMU, so not * implemented set_map()/dma_map()/dma_unmap() @@ -440,6 +455,7 @@ static const struct vdpa_config_ops ifc_vdpa_ops = { .get_config = ifcvf_vdpa_get_config, .set_config = ifcvf_vdpa_set_config, .set_config_cb = ifcvf_vdpa_set_config_cb, + .get_vq_notification = ifcvf_get_vq_notification, }; static int ifcvf_probe(struct pci_dev *pdev, const struct pci_device_id *id) @@ -536,18 +552,21 @@ static void ifcvf_remove(struct pci_dev *pdev) } static struct pci_device_id ifcvf_pci_ids[] = { - { PCI_DEVICE_SUB(N3000_VENDOR_ID, + /* N3000 network device */ + { PCI_DEVICE_SUB(PCI_VENDOR_ID_REDHAT_QUMRANET, N3000_DEVICE_ID, - N3000_SUBSYS_VENDOR_ID, + PCI_VENDOR_ID_INTEL, N3000_SUBSYS_DEVICE_ID) }, - { PCI_DEVICE_SUB(C5000X_PL_VENDOR_ID, - C5000X_PL_DEVICE_ID, - C5000X_PL_SUBSYS_VENDOR_ID, - C5000X_PL_SUBSYS_DEVICE_ID) }, - { PCI_DEVICE_SUB(C5000X_PL_BLK_VENDOR_ID, - C5000X_PL_BLK_DEVICE_ID, - C5000X_PL_BLK_SUBSYS_VENDOR_ID, - C5000X_PL_BLK_SUBSYS_DEVICE_ID) }, + /* C5000X-PL network device */ + { PCI_DEVICE_SUB(PCI_VENDOR_ID_REDHAT_QUMRANET, + VIRTIO_TRANS_ID_NET, + PCI_VENDOR_ID_INTEL, + VIRTIO_ID_NET) }, + /* C5000X-PL block device */ + { PCI_DEVICE_SUB(PCI_VENDOR_ID_REDHAT_QUMRANET, + VIRTIO_TRANS_ID_BLOCK, + PCI_VENDOR_ID_INTEL, + VIRTIO_ID_BLOCK) }, { 0 }, }; diff --git a/drivers/vdpa/mlx5/core/mlx5_vdpa.h b/drivers/vdpa/mlx5/core/mlx5_vdpa.h index b6cc53ba980c..0002b2136b48 100644 --- a/drivers/vdpa/mlx5/core/mlx5_vdpa.h +++ b/drivers/vdpa/mlx5/core/mlx5_vdpa.h @@ -35,12 +35,14 @@ struct mlx5_vdpa_mr { /* serialize mkey creation and destruction */ struct mutex mkey_mtx; + bool user_mr; }; struct mlx5_vdpa_resources { u32 pdn; struct mlx5_uars_page *uar; void __iomem *kick_addr; + u64 phys_kick_addr; u16 uid; u32 null_mkey; bool valid; diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c index 800cfd1967ad..dcee6039e966 100644 --- a/drivers/vdpa/mlx5/core/mr.c +++ b/drivers/vdpa/mlx5/core/mr.c @@ -219,11 +219,6 @@ static void destroy_indirect_key(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_m mlx5_vdpa_destroy_mkey(mvdev, &mkey->mkey); } -static struct device *get_dma_device(struct mlx5_vdpa_dev *mvdev) -{ - return &mvdev->mdev->pdev->dev; -} - static int map_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr *mr, struct vhost_iotlb *iotlb) { @@ -239,7 +234,7 @@ static int map_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr u64 pa; u64 paend; struct scatterlist *sg; - struct device *dma = get_dma_device(mvdev); + struct device *dma = mvdev->vdev.dma_dev; for (map = vhost_iotlb_itree_first(iotlb, mr->start, mr->end - 1); map; map = vhost_iotlb_itree_next(map, start, mr->end - 1)) { @@ -298,7 +293,7 @@ err_map: static void unmap_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr *mr) { - struct device *dma = get_dma_device(mvdev); + struct device *dma = mvdev->vdev.dma_dev; destroy_direct_mr(mvdev, mr); dma_unmap_sg_attrs(dma, mr->sg_head.sgl, mr->nsg, DMA_BIDIRECTIONAL, 0); @@ -360,7 +355,7 @@ err_alloc: * indirect memory key that provides access to the enitre address space given * by iotlb. */ -static int _mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb) +static int create_user_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb) { struct mlx5_vdpa_mr *mr = &mvdev->mr; struct mlx5_vdpa_direct_mr *dmr; @@ -374,9 +369,6 @@ static int _mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb int err = 0; int nnuls; - if (mr->initialized) - return 0; - INIT_LIST_HEAD(&mr->head); for (map = vhost_iotlb_itree_first(iotlb, start, last); map; map = vhost_iotlb_itree_next(map, start, last)) { @@ -414,7 +406,7 @@ static int _mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb if (err) goto err_chain; - mr->initialized = true; + mr->user_mr = true; return 0; err_chain: @@ -426,33 +418,94 @@ err_chain: return err; } -int mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb) +static int create_dma_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr) +{ + int inlen = MLX5_ST_SZ_BYTES(create_mkey_in); + void *mkc; + u32 *in; + int err; + + in = kzalloc(inlen, GFP_KERNEL); + if (!in) + return -ENOMEM; + + mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry); + + MLX5_SET(mkc, mkc, access_mode_1_0, MLX5_MKC_ACCESS_MODE_PA); + MLX5_SET(mkc, mkc, length64, 1); + MLX5_SET(mkc, mkc, lw, 1); + MLX5_SET(mkc, mkc, lr, 1); + MLX5_SET(mkc, mkc, pd, mvdev->res.pdn); + MLX5_SET(mkc, mkc, qpn, 0xffffff); + + err = mlx5_vdpa_create_mkey(mvdev, &mr->mkey, in, inlen); + if (!err) + mr->user_mr = false; + + kfree(in); + return err; +} + +static void destroy_dma_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr) +{ + mlx5_vdpa_destroy_mkey(mvdev, &mr->mkey); +} + +static int _mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb) { struct mlx5_vdpa_mr *mr = &mvdev->mr; int err; - mutex_lock(&mr->mkey_mtx); + if (mr->initialized) + return 0; + + if (iotlb) + err = create_user_mr(mvdev, iotlb); + else + err = create_dma_mr(mvdev, mr); + + if (!err) + mr->initialized = true; + + return err; +} + +int mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb) +{ + int err; + + mutex_lock(&mvdev->mr.mkey_mtx); err = _mlx5_vdpa_create_mr(mvdev, iotlb); - mutex_unlock(&mr->mkey_mtx); + mutex_unlock(&mvdev->mr.mkey_mtx); return err; } -void mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev) +static void destroy_user_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr) { - struct mlx5_vdpa_mr *mr = &mvdev->mr; struct mlx5_vdpa_direct_mr *dmr; struct mlx5_vdpa_direct_mr *n; - mutex_lock(&mr->mkey_mtx); - if (!mr->initialized) - goto out; - destroy_indirect_key(mvdev, mr); list_for_each_entry_safe_reverse(dmr, n, &mr->head, list) { list_del_init(&dmr->list); unmap_direct_mr(mvdev, dmr); kfree(dmr); } +} + +void mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev) +{ + struct mlx5_vdpa_mr *mr = &mvdev->mr; + + mutex_lock(&mr->mkey_mtx); + if (!mr->initialized) + goto out; + + if (mr->user_mr) + destroy_user_mr(mvdev, mr); + else + destroy_dma_mr(mvdev, mr); + memset(mr, 0, sizeof(*mr)); mr->initialized = false; out: diff --git a/drivers/vdpa/mlx5/core/resources.c b/drivers/vdpa/mlx5/core/resources.c index 6521cbd0f5c2..d4606213f88a 100644 --- a/drivers/vdpa/mlx5/core/resources.c +++ b/drivers/vdpa/mlx5/core/resources.c @@ -54,6 +54,9 @@ static int create_uctx(struct mlx5_vdpa_dev *mvdev, u16 *uid) void *in; int err; + if (MLX5_CAP_GEN(mvdev->mdev, umem_uid_0)) + return 0; + /* 0 means not supported */ if (!MLX5_CAP_GEN(mvdev->mdev, log_max_uctx)) return -EOPNOTSUPP; @@ -79,6 +82,9 @@ static void destroy_uctx(struct mlx5_vdpa_dev *mvdev, u32 uid) u32 out[MLX5_ST_SZ_DW(destroy_uctx_out)] = {}; u32 in[MLX5_ST_SZ_DW(destroy_uctx_in)] = {}; + if (!uid) + return; + MLX5_SET(destroy_uctx_in, in, opcode, MLX5_CMD_OP_DESTROY_UCTX); MLX5_SET(destroy_uctx_in, in, uid, uid); @@ -247,6 +253,7 @@ int mlx5_vdpa_alloc_resources(struct mlx5_vdpa_dev *mvdev) goto err_key; kick_addr = mdev->bar_addr + offset; + res->phys_kick_addr = kick_addr; res->kick_addr = ioremap(kick_addr, PAGE_SIZE); if (!res->kick_addr) { diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c index dda5dc6f7737..2a31467f7ac5 100644 --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c @@ -611,8 +611,8 @@ static void cq_destroy(struct mlx5_vdpa_net *ndev, u16 idx) mlx5_db_free(ndev->mvdev.mdev, &vcq->db); } -static int umem_size(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq, int num, - struct mlx5_vdpa_umem **umemp) +static void set_umem_size(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq, int num, + struct mlx5_vdpa_umem **umemp) { struct mlx5_core_dev *mdev = ndev->mvdev.mdev; int p_a; @@ -635,7 +635,7 @@ static int umem_size(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq *umemp = &mvq->umem3; break; } - return p_a * mvq->num_ent + p_b; + (*umemp)->size = p_a * mvq->num_ent + p_b; } static void umem_frag_buf_free(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_umem *umem) @@ -651,15 +651,10 @@ static int create_umem(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *m void *in; int err; __be64 *pas; - int size; struct mlx5_vdpa_umem *umem; - size = umem_size(ndev, mvq, num, &umem); - if (size < 0) - return size; - - umem->size = size; - err = umem_frag_buf_alloc(ndev, umem, size); + set_umem_size(ndev, mvq, num, &umem); + err = umem_frag_buf_alloc(ndev, umem, umem->size); if (err) return err; @@ -829,9 +824,9 @@ static int create_virtqueue(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtque MLX5_SET(virtio_q, vq_ctx, umem_1_id, mvq->umem1.id); MLX5_SET(virtio_q, vq_ctx, umem_1_size, mvq->umem1.size); MLX5_SET(virtio_q, vq_ctx, umem_2_id, mvq->umem2.id); - MLX5_SET(virtio_q, vq_ctx, umem_2_size, mvq->umem1.size); + MLX5_SET(virtio_q, vq_ctx, umem_2_size, mvq->umem2.size); MLX5_SET(virtio_q, vq_ctx, umem_3_id, mvq->umem3.id); - MLX5_SET(virtio_q, vq_ctx, umem_3_size, mvq->umem1.size); + MLX5_SET(virtio_q, vq_ctx, umem_3_size, mvq->umem3.size); MLX5_SET(virtio_q, vq_ctx, pd, ndev->mvdev.res.pdn); if (MLX5_CAP_DEV_VDPA_EMULATION(ndev->mvdev.mdev, eth_frame_offload_type)) MLX5_SET(virtio_q, vq_ctx, virtio_version_1_0, 1); @@ -1428,8 +1423,8 @@ static int mlx5_vdpa_set_vq_state(struct vdpa_device *vdev, u16 idx, return -EINVAL; } - mvq->used_idx = state->avail_index; - mvq->avail_idx = state->avail_index; + mvq->used_idx = state->split.avail_index; + mvq->avail_idx = state->split.avail_index; return 0; } @@ -1450,7 +1445,7 @@ static int mlx5_vdpa_get_vq_state(struct vdpa_device *vdev, u16 idx, struct vdpa * Since both values should be identical, we take the value of * used_idx which is reported correctly. */ - state->avail_index = mvq->used_idx; + state->split.avail_index = mvq->used_idx; return 0; } @@ -1459,7 +1454,7 @@ static int mlx5_vdpa_get_vq_state(struct vdpa_device *vdev, u16 idx, struct vdpa mlx5_vdpa_warn(mvdev, "failed to query virtqueue\n"); return err; } - state->avail_index = attr.used_index; + state->split.avail_index = attr.used_index; return 0; } @@ -1772,6 +1767,14 @@ out: mutex_unlock(&ndev->reslock); } +static void clear_vqs_ready(struct mlx5_vdpa_net *ndev) +{ + int i; + + for (i = 0; i < ndev->mvdev.max_vqs; i++) + ndev->vqs[i].ready = false; +} + static void mlx5_vdpa_set_status(struct vdpa_device *vdev, u8 status) { struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); @@ -1782,10 +1785,15 @@ static void mlx5_vdpa_set_status(struct vdpa_device *vdev, u8 status) if (!status) { mlx5_vdpa_info(mvdev, "performing device reset\n"); teardown_driver(ndev); + clear_vqs_ready(ndev); mlx5_vdpa_destroy_mr(&ndev->mvdev); ndev->mvdev.status = 0; ndev->mvdev.mlx_features = 0; ++mvdev->generation; + if (MLX5_CAP_GEN(mvdev->mdev, umem_uid_0)) { + if (mlx5_vdpa_create_mr(mvdev, NULL)) + mlx5_vdpa_warn(mvdev, "create MR failed\n"); + } return; } @@ -1866,6 +1874,7 @@ static void mlx5_vdpa_free(struct vdpa_device *vdev) ndev = to_mlx5_vdpa_ndev(mvdev); free_resources(ndev); + mlx5_vdpa_destroy_mr(mvdev); if (!is_zero_ether_addr(ndev->config.mac)) { pfmdev = pci_get_drvdata(pci_physfn(mvdev->mdev->pdev)); mlx5_mpfs_del_mac(pfmdev, ndev->config.mac); @@ -1876,8 +1885,22 @@ static void mlx5_vdpa_free(struct vdpa_device *vdev) static struct vdpa_notification_area mlx5_get_vq_notification(struct vdpa_device *vdev, u16 idx) { + struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); struct vdpa_notification_area ret = {}; + struct mlx5_vdpa_net *ndev; + phys_addr_t addr; + + /* If SF BAR size is smaller than PAGE_SIZE, do not use direct + * notification to avoid the risk of mapping pages that contain BAR of more + * than one SF + */ + if (MLX5_CAP_GEN(mvdev->mdev, log_min_sf_size) + 12 < PAGE_SHIFT) + return ret; + ndev = to_mlx5_vdpa_ndev(mvdev); + addr = (phys_addr_t)ndev->mvdev.res.phys_kick_addr; + ret.addr = addr; + ret.size = PAGE_SIZE; return ret; } @@ -2037,14 +2060,20 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name) goto err_mtu; } - mvdev->vdev.dma_dev = mdev->device; + mvdev->vdev.dma_dev = &mdev->pdev->dev; err = mlx5_vdpa_alloc_resources(&ndev->mvdev); if (err) goto err_mpfs; + if (MLX5_CAP_GEN(mvdev->mdev, umem_uid_0)) { + err = mlx5_vdpa_create_mr(mvdev, NULL); + if (err) + goto err_res; + } + err = alloc_resources(ndev); if (err) - goto err_res; + goto err_mr; mvdev->vdev.mdev = &mgtdev->mgtdev; err = _vdpa_register_device(&mvdev->vdev, 2 * mlx5_vdpa_max_qps(max_vqs)); @@ -2056,6 +2085,8 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name) err_reg: free_resources(ndev); +err_mr: + mlx5_vdpa_destroy_mr(mvdev); err_res: mlx5_vdpa_free_resources(&ndev->mvdev); err_mpfs: diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c index 98f793bc9376..14e024de5cbf 100644 --- a/drivers/vdpa/vdpa_sim/vdpa_sim.c +++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c @@ -374,7 +374,7 @@ static int vdpasim_set_vq_state(struct vdpa_device *vdpa, u16 idx, struct vringh *vrh = &vq->vring; spin_lock(&vdpasim->lock); - vrh->last_avail_idx = state->avail_index; + vrh->last_avail_idx = state->split.avail_index; spin_unlock(&vdpasim->lock); return 0; @@ -387,7 +387,7 @@ static int vdpasim_get_vq_state(struct vdpa_device *vdpa, u16 idx, struct vdpasim_virtqueue *vq = &vdpasim->vqs[idx]; struct vringh *vrh = &vq->vring; - state->avail_index = vrh->last_avail_idx; + state->split.avail_index = vrh->last_avail_idx; return 0; } diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c index 5bfe1c281645..a790903f243e 100644 --- a/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c +++ b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c @@ -15,7 +15,6 @@ #include <linux/blkdev.h> #include <linux/vringh.h> #include <linux/vdpa.h> -#include <linux/blkdev.h> #include <uapi/linux/virtio_blk.h> #include "vdpa_sim.h" diff --git a/drivers/vdpa/virtio_pci/vp_vdpa.c b/drivers/vdpa/virtio_pci/vp_vdpa.c index c76ebb531212..7b4a6396c553 100644 --- a/drivers/vdpa/virtio_pci/vp_vdpa.c +++ b/drivers/vdpa/virtio_pci/vp_vdpa.c @@ -210,13 +210,49 @@ static int vp_vdpa_get_vq_state(struct vdpa_device *vdpa, u16 qid, return -EOPNOTSUPP; } +static int vp_vdpa_set_vq_state_split(struct vdpa_device *vdpa, + const struct vdpa_vq_state *state) +{ + const struct vdpa_vq_state_split *split = &state->split; + + if (split->avail_index == 0) + return 0; + + return -EOPNOTSUPP; +} + +static int vp_vdpa_set_vq_state_packed(struct vdpa_device *vdpa, + const struct vdpa_vq_state *state) +{ + const struct vdpa_vq_state_packed *packed = &state->packed; + + if (packed->last_avail_counter == 1 && + packed->last_avail_idx == 0 && + packed->last_used_counter == 1 && + packed->last_used_idx == 0) + return 0; + + return -EOPNOTSUPP; +} + static int vp_vdpa_set_vq_state(struct vdpa_device *vdpa, u16 qid, const struct vdpa_vq_state *state) { - /* Note that this is not supported by virtio specification, so - * we return -ENOPOTSUPP here. This means we can't support live - * migration, vhost device start/stop. + struct virtio_pci_modern_device *mdev = vdpa_to_mdev(vdpa); + + /* Note that this is not supported by virtio specification. + * But if the state is by chance equal to the device initial + * state, we can let it go. */ + if ((vp_modern_get_status(mdev) & VIRTIO_CONFIG_S_FEATURES_OK) && + !vp_modern_get_queue_enable(mdev, qid)) { + if (vp_modern_get_driver_features(mdev) & + BIT_ULL(VIRTIO_F_RING_PACKED)) + return vp_vdpa_set_vq_state_packed(vdpa, state); + else + return vp_vdpa_set_vq_state_split(vdpa, state); + } + return -EOPNOTSUPP; } @@ -442,6 +478,7 @@ static int vp_vdpa_probe(struct pci_dev *pdev, const struct pci_device_id *id) vp_modern_map_vq_notify(mdev, i, &vp_vdpa->vring[i].notify_pa); if (!vp_vdpa->vring[i].notify) { + ret = -EINVAL; dev_warn(&pdev->dev, "Fail to map vq notify %d\n", i); goto err; } diff --git a/drivers/vfio/fsl-mc/vfio_fsl_mc.c b/drivers/vfio/fsl-mc/vfio_fsl_mc.c index 980e59551301..90cad109583b 100644 --- a/drivers/vfio/fsl-mc/vfio_fsl_mc.c +++ b/drivers/vfio/fsl-mc/vfio_fsl_mc.c @@ -140,26 +140,18 @@ static int vfio_fsl_mc_open(struct vfio_device *core_vdev) { struct vfio_fsl_mc_device *vdev = container_of(core_vdev, struct vfio_fsl_mc_device, vdev); - int ret; - - if (!try_module_get(THIS_MODULE)) - return -ENODEV; + int ret = 0; mutex_lock(&vdev->reflck->lock); if (!vdev->refcnt) { ret = vfio_fsl_mc_regions_init(vdev); if (ret) - goto err_reg_init; + goto out; } vdev->refcnt++; - +out: mutex_unlock(&vdev->reflck->lock); - return 0; - -err_reg_init: - mutex_unlock(&vdev->reflck->lock); - module_put(THIS_MODULE); return ret; } @@ -196,8 +188,6 @@ static void vfio_fsl_mc_release(struct vfio_device *core_vdev) } mutex_unlock(&vdev->reflck->lock); - - module_put(THIS_MODULE); } static long vfio_fsl_mc_ioctl(struct vfio_device *core_vdev, diff --git a/drivers/vfio/mdev/Kconfig b/drivers/vfio/mdev/Kconfig index 5da27f2100f9..763c877a1318 100644 --- a/drivers/vfio/mdev/Kconfig +++ b/drivers/vfio/mdev/Kconfig @@ -9,10 +9,3 @@ config VFIO_MDEV See Documentation/driver-api/vfio-mediated-device.rst for more details. If you don't know what do here, say N. - -config VFIO_MDEV_DEVICE - tristate "VFIO driver for Mediated devices" - depends on VFIO && VFIO_MDEV - default n - help - VFIO based driver for Mediated devices. diff --git a/drivers/vfio/mdev/Makefile b/drivers/vfio/mdev/Makefile index 101516fdf375..ff9ecd802125 100644 --- a/drivers/vfio/mdev/Makefile +++ b/drivers/vfio/mdev/Makefile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -mdev-y := mdev_core.o mdev_sysfs.o mdev_driver.o +mdev-y := mdev_core.o mdev_sysfs.o mdev_driver.o vfio_mdev.o obj-$(CONFIG_VFIO_MDEV) += mdev.o -obj-$(CONFIG_VFIO_MDEV_DEVICE) += vfio_mdev.o diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c index 2a85d6fcb7dd..e4581ec093a6 100644 --- a/drivers/vfio/mdev/mdev_core.c +++ b/drivers/vfio/mdev/mdev_core.c @@ -94,9 +94,11 @@ static void mdev_device_remove_common(struct mdev_device *mdev) mdev_remove_sysfs_files(mdev); device_del(&mdev->dev); lockdep_assert_held(&parent->unreg_sem); - ret = parent->ops->remove(mdev); - if (ret) - dev_err(&mdev->dev, "Remove failed: err=%d\n", ret); + if (parent->ops->remove) { + ret = parent->ops->remove(mdev); + if (ret) + dev_err(&mdev->dev, "Remove failed: err=%d\n", ret); + } /* Balances with device_initialize() */ put_device(&mdev->dev); @@ -127,7 +129,9 @@ int mdev_register_device(struct device *dev, const struct mdev_parent_ops *ops) char *envp[] = { env_string, NULL }; /* check for mandatory ops */ - if (!ops || !ops->create || !ops->remove || !ops->supported_type_groups) + if (!ops || !ops->supported_type_groups) + return -EINVAL; + if (!ops->device_driver && (!ops->create || !ops->remove)) return -EINVAL; dev = get_device(dev); @@ -256,6 +260,7 @@ int mdev_device_create(struct mdev_type *type, const guid_t *uuid) int ret; struct mdev_device *mdev, *tmp; struct mdev_parent *parent = type->parent; + struct mdev_driver *drv = parent->ops->device_driver; mutex_lock(&mdev_list_lock); @@ -296,14 +301,22 @@ int mdev_device_create(struct mdev_type *type, const guid_t *uuid) goto out_put_device; } - ret = parent->ops->create(mdev); - if (ret) - goto out_unlock; + if (parent->ops->create) { + ret = parent->ops->create(mdev); + if (ret) + goto out_unlock; + } ret = device_add(&mdev->dev); if (ret) goto out_remove; + if (!drv) + drv = &vfio_mdev_driver; + ret = device_driver_attach(&drv->driver, &mdev->dev); + if (ret) + goto out_del; + ret = mdev_create_sysfs_files(mdev); if (ret) goto out_del; @@ -317,7 +330,8 @@ int mdev_device_create(struct mdev_type *type, const guid_t *uuid) out_del: device_del(&mdev->dev); out_remove: - parent->ops->remove(mdev); + if (parent->ops->remove) + parent->ops->remove(mdev); out_unlock: up_read(&parent->unreg_sem); out_put_device: @@ -360,11 +374,24 @@ int mdev_device_remove(struct mdev_device *mdev) static int __init mdev_init(void) { - return mdev_bus_register(); + int rc; + + rc = mdev_bus_register(); + if (rc) + return rc; + rc = mdev_register_driver(&vfio_mdev_driver); + if (rc) + goto err_bus; + return 0; +err_bus: + mdev_bus_unregister(); + return rc; } static void __exit mdev_exit(void) { + mdev_unregister_driver(&vfio_mdev_driver); + if (mdev_bus_compat_class) class_compat_unregister(mdev_bus_compat_class); @@ -378,4 +405,3 @@ MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_SOFTDEP("post: vfio_mdev"); diff --git a/drivers/vfio/mdev/mdev_driver.c b/drivers/vfio/mdev/mdev_driver.c index 041699571b7e..c368ec824e2b 100644 --- a/drivers/vfio/mdev/mdev_driver.c +++ b/drivers/vfio/mdev/mdev_driver.c @@ -71,10 +71,20 @@ static int mdev_remove(struct device *dev) return 0; } +static int mdev_match(struct device *dev, struct device_driver *drv) +{ + /* + * No drivers automatically match. Drivers are only bound by explicit + * device_driver_attach() + */ + return 0; +} + struct bus_type mdev_bus_type = { .name = "mdev", .probe = mdev_probe, .remove = mdev_remove, + .match = mdev_match, }; EXPORT_SYMBOL_GPL(mdev_bus_type); diff --git a/drivers/vfio/mdev/mdev_private.h b/drivers/vfio/mdev/mdev_private.h index 6999c89db7b1..afbad7b0a14a 100644 --- a/drivers/vfio/mdev/mdev_private.h +++ b/drivers/vfio/mdev/mdev_private.h @@ -37,6 +37,8 @@ struct mdev_type { #define to_mdev_type(_kobj) \ container_of(_kobj, struct mdev_type, kobj) +extern struct mdev_driver vfio_mdev_driver; + int parent_create_sysfs_files(struct mdev_parent *parent); void parent_remove_sysfs_files(struct mdev_parent *parent); diff --git a/drivers/vfio/mdev/vfio_mdev.c b/drivers/vfio/mdev/vfio_mdev.c index 922729071c5a..39ef7489fe47 100644 --- a/drivers/vfio/mdev/vfio_mdev.c +++ b/drivers/vfio/mdev/vfio_mdev.c @@ -17,28 +17,15 @@ #include "mdev_private.h" -#define DRIVER_VERSION "0.1" -#define DRIVER_AUTHOR "NVIDIA Corporation" -#define DRIVER_DESC "VFIO based driver for Mediated device" - static int vfio_mdev_open(struct vfio_device *core_vdev) { struct mdev_device *mdev = to_mdev_device(core_vdev->dev); struct mdev_parent *parent = mdev->type->parent; - int ret; - if (unlikely(!parent->ops->open)) return -EINVAL; - if (!try_module_get(THIS_MODULE)) - return -ENODEV; - - ret = parent->ops->open(mdev); - if (ret) - module_put(THIS_MODULE); - - return ret; + return parent->ops->open(mdev); } static void vfio_mdev_release(struct vfio_device *core_vdev) @@ -48,8 +35,6 @@ static void vfio_mdev_release(struct vfio_device *core_vdev) if (likely(parent->ops->release)) parent->ops->release(mdev); - - module_put(THIS_MODULE); } static long vfio_mdev_unlocked_ioctl(struct vfio_device *core_vdev, @@ -151,7 +136,7 @@ static void vfio_mdev_remove(struct mdev_device *mdev) kfree(vdev); } -static struct mdev_driver vfio_mdev_driver = { +struct mdev_driver vfio_mdev_driver = { .driver = { .name = "vfio_mdev", .owner = THIS_MODULE, @@ -160,21 +145,3 @@ static struct mdev_driver vfio_mdev_driver = { .probe = vfio_mdev_probe, .remove = vfio_mdev_remove, }; - -static int __init vfio_mdev_init(void) -{ - return mdev_register_driver(&vfio_mdev_driver); -} - -static void __exit vfio_mdev_exit(void) -{ - mdev_unregister_driver(&vfio_mdev_driver); -} - -module_init(vfio_mdev_init) -module_exit(vfio_mdev_exit) - -MODULE_VERSION(DRIVER_VERSION); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index bd7c482c948a..318864d52837 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -477,13 +477,10 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev) * We can not use the "try" reset interface here, which will * overwrite the previously restored configuration information. */ - if (vdev->reset_works && pci_cfg_access_trylock(pdev)) { - if (device_trylock(&pdev->dev)) { - if (!__pci_reset_function_locked(pdev)) - vdev->needs_reset = false; - device_unlock(&pdev->dev); - } - pci_cfg_access_unlock(pdev); + if (vdev->reset_works && pci_dev_trylock(pdev)) { + if (!__pci_reset_function_locked(pdev)) + vdev->needs_reset = false; + pci_dev_unlock(pdev); } pci_restore_state(pdev); @@ -558,8 +555,6 @@ static void vfio_pci_release(struct vfio_device *core_vdev) } mutex_unlock(&vdev->reflck->lock); - - module_put(THIS_MODULE); } static int vfio_pci_open(struct vfio_device *core_vdev) @@ -568,9 +563,6 @@ static int vfio_pci_open(struct vfio_device *core_vdev) container_of(core_vdev, struct vfio_pci_device, vdev); int ret = 0; - if (!try_module_get(THIS_MODULE)) - return -ENODEV; - mutex_lock(&vdev->reflck->lock); if (!vdev->refcnt) { @@ -584,8 +576,6 @@ static int vfio_pci_open(struct vfio_device *core_vdev) vdev->refcnt++; error: mutex_unlock(&vdev->reflck->lock); - if (ret) - module_put(THIS_MODULE); return ret; } @@ -1594,6 +1584,7 @@ static vm_fault_t vfio_pci_mmap_fault(struct vm_fault *vmf) { struct vm_area_struct *vma = vmf->vma; struct vfio_pci_device *vdev = vma->vm_private_data; + struct vfio_pci_mmap_vma *mmap_vma; vm_fault_t ret = VM_FAULT_NOPAGE; mutex_lock(&vdev->vma_lock); @@ -1601,24 +1592,36 @@ static vm_fault_t vfio_pci_mmap_fault(struct vm_fault *vmf) if (!__vfio_pci_memory_enabled(vdev)) { ret = VM_FAULT_SIGBUS; - mutex_unlock(&vdev->vma_lock); goto up_out; } - if (__vfio_pci_add_vma(vdev, vma)) { - ret = VM_FAULT_OOM; - mutex_unlock(&vdev->vma_lock); - goto up_out; + /* + * We populate the whole vma on fault, so we need to test whether + * the vma has already been mapped, such as for concurrent faults + * to the same vma. io_remap_pfn_range() will trigger a BUG_ON if + * we ask it to fill the same range again. + */ + list_for_each_entry(mmap_vma, &vdev->vma_list, vma_next) { + if (mmap_vma->vma == vma) + goto up_out; } - mutex_unlock(&vdev->vma_lock); - if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) + vma->vm_end - vma->vm_start, + vma->vm_page_prot)) { ret = VM_FAULT_SIGBUS; + zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start); + goto up_out; + } + + if (__vfio_pci_add_vma(vdev, vma)) { + ret = VM_FAULT_OOM; + zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start); + } up_out: up_read(&vdev->memory_lock); + mutex_unlock(&vdev->vma_lock); return ret; } diff --git a/drivers/vfio/platform/vfio_amba.c b/drivers/vfio/platform/vfio_amba.c index f970eb2a999f..badfffea14fb 100644 --- a/drivers/vfio/platform/vfio_amba.c +++ b/drivers/vfio/platform/vfio_amba.c @@ -59,7 +59,6 @@ static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id) vdev->flags = VFIO_DEVICE_FLAGS_AMBA; vdev->get_resource = get_amba_resource; vdev->get_irq = get_amba_irq; - vdev->parent_module = THIS_MODULE; vdev->reset_required = false; ret = vfio_platform_probe_common(vdev, &adev->dev); diff --git a/drivers/vfio/platform/vfio_platform.c b/drivers/vfio/platform/vfio_platform.c index e4027799a154..68a1c87066d7 100644 --- a/drivers/vfio/platform/vfio_platform.c +++ b/drivers/vfio/platform/vfio_platform.c @@ -50,7 +50,6 @@ static int vfio_platform_probe(struct platform_device *pdev) vdev->flags = VFIO_DEVICE_FLAGS_PLATFORM; vdev->get_resource = get_platform_resource; vdev->get_irq = get_platform_irq; - vdev->parent_module = THIS_MODULE; vdev->reset_required = reset_required; ret = vfio_platform_probe_common(vdev, &pdev->dev); diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c index 470fcf7dac56..703164df7637 100644 --- a/drivers/vfio/platform/vfio_platform_common.c +++ b/drivers/vfio/platform/vfio_platform_common.c @@ -241,8 +241,6 @@ static void vfio_platform_release(struct vfio_device *core_vdev) } mutex_unlock(&driver_lock); - - module_put(vdev->parent_module); } static int vfio_platform_open(struct vfio_device *core_vdev) @@ -251,9 +249,6 @@ static int vfio_platform_open(struct vfio_device *core_vdev) container_of(core_vdev, struct vfio_platform_device, vdev); int ret; - if (!try_module_get(vdev->parent_module)) - return -ENODEV; - mutex_lock(&driver_lock); if (!vdev->refcnt) { @@ -291,7 +286,6 @@ err_irq: vfio_platform_regions_cleanup(vdev); err_reg: mutex_unlock(&driver_lock); - module_put(vdev->parent_module); return ret; } diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h index a5ba82c8cbc3..dfb834c13659 100644 --- a/drivers/vfio/platform/vfio_platform_private.h +++ b/drivers/vfio/platform/vfio_platform_private.h @@ -50,7 +50,6 @@ struct vfio_platform_device { u32 num_irqs; int refcnt; struct mutex igate; - struct module *parent_module; const char *compat; const char *acpihid; struct module *reset_module; diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 5e631c359ef2..02cc51ce6891 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -1369,8 +1369,14 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf) if (IS_ERR(device)) return PTR_ERR(device); + if (!try_module_get(device->dev->driver->owner)) { + vfio_device_put(device); + return -ENODEV; + } + ret = device->ops->open(device); if (ret) { + module_put(device->dev->driver->owner); vfio_device_put(device); return ret; } @@ -1382,6 +1388,7 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf) ret = get_unused_fd_flags(O_CLOEXEC); if (ret < 0) { device->ops->release(device); + module_put(device->dev->driver->owner); vfio_device_put(device); return ret; } @@ -1392,6 +1399,7 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf) put_unused_fd(ret); ret = PTR_ERR(filep); device->ops->release(device); + module_put(device->dev->driver->owner); vfio_device_put(device); return ret; } @@ -1550,6 +1558,8 @@ static int vfio_device_fops_release(struct inode *inode, struct file *filep) device->ops->release(device); + module_put(device->dev->driver->owner); + vfio_group_try_dissolve_container(device->group); vfio_device_put(device); diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 4fce73a8a650..0b4f7c174c7a 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -110,7 +110,7 @@ struct vfio_batch { int offset; /* of next entry in pages */ }; -struct vfio_group { +struct vfio_iommu_group { struct iommu_group *iommu_group; struct list_head next; bool mdev_group; /* An mdev group */ @@ -160,8 +160,9 @@ struct vfio_regions { static int put_pfn(unsigned long pfn, int prot); -static struct vfio_group *vfio_iommu_find_iommu_group(struct vfio_iommu *iommu, - struct iommu_group *iommu_group); +static struct vfio_iommu_group* +vfio_iommu_find_iommu_group(struct vfio_iommu *iommu, + struct iommu_group *iommu_group); /* * This code handles mapping and unmapping of user data buffers @@ -836,7 +837,7 @@ static int vfio_iommu_type1_pin_pages(void *iommu_data, unsigned long *phys_pfn) { struct vfio_iommu *iommu = iommu_data; - struct vfio_group *group; + struct vfio_iommu_group *group; int i, j, ret; unsigned long remote_vaddr; struct vfio_dma *dma; @@ -1875,10 +1876,10 @@ static void vfio_test_domain_fgsp(struct vfio_domain *domain) __free_pages(pages, order); } -static struct vfio_group *find_iommu_group(struct vfio_domain *domain, - struct iommu_group *iommu_group) +static struct vfio_iommu_group *find_iommu_group(struct vfio_domain *domain, + struct iommu_group *iommu_group) { - struct vfio_group *g; + struct vfio_iommu_group *g; list_for_each_entry(g, &domain->group_list, next) { if (g->iommu_group == iommu_group) @@ -1888,11 +1889,12 @@ static struct vfio_group *find_iommu_group(struct vfio_domain *domain, return NULL; } -static struct vfio_group *vfio_iommu_find_iommu_group(struct vfio_iommu *iommu, - struct iommu_group *iommu_group) +static struct vfio_iommu_group* +vfio_iommu_find_iommu_group(struct vfio_iommu *iommu, + struct iommu_group *iommu_group) { struct vfio_domain *domain; - struct vfio_group *group = NULL; + struct vfio_iommu_group *group = NULL; list_for_each_entry(domain, &iommu->domain_list, next) { group = find_iommu_group(domain, iommu_group); @@ -1967,7 +1969,7 @@ static int vfio_mdev_detach_domain(struct device *dev, void *data) } static int vfio_iommu_attach_group(struct vfio_domain *domain, - struct vfio_group *group) + struct vfio_iommu_group *group) { if (group->mdev_group) return iommu_group_for_each_dev(group->iommu_group, @@ -1978,7 +1980,7 @@ static int vfio_iommu_attach_group(struct vfio_domain *domain, } static void vfio_iommu_detach_group(struct vfio_domain *domain, - struct vfio_group *group) + struct vfio_iommu_group *group) { if (group->mdev_group) iommu_group_for_each_dev(group->iommu_group, domain->domain, @@ -2242,7 +2244,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data, struct iommu_group *iommu_group) { struct vfio_iommu *iommu = iommu_data; - struct vfio_group *group; + struct vfio_iommu_group *group; struct vfio_domain *domain, *d; struct bus_type *bus = NULL; int ret; @@ -2518,7 +2520,7 @@ static int vfio_iommu_resv_refresh(struct vfio_iommu *iommu, struct list_head *iova_copy) { struct vfio_domain *d; - struct vfio_group *g; + struct vfio_iommu_group *g; struct vfio_iova *node; dma_addr_t start, end; LIST_HEAD(resv_regions); @@ -2560,7 +2562,7 @@ static void vfio_iommu_type1_detach_group(void *iommu_data, { struct vfio_iommu *iommu = iommu_data; struct vfio_domain *domain; - struct vfio_group *group; + struct vfio_iommu_group *group; bool update_dirty_scope = false; LIST_HEAD(iova_copy); @@ -2681,7 +2683,7 @@ static void *vfio_iommu_type1_open(unsigned long arg) static void vfio_release_domain(struct vfio_domain *domain, bool external) { - struct vfio_group *group, *group_tmp; + struct vfio_iommu_group *group, *group_tmp; list_for_each_entry_safe(group, group_tmp, &domain->group_list, next) { diff --git a/drivers/vhost/iotlb.c b/drivers/vhost/iotlb.c index 0fd3f87e913c..0582079e4bcc 100644 --- a/drivers/vhost/iotlb.c +++ b/drivers/vhost/iotlb.c @@ -83,7 +83,7 @@ int vhost_iotlb_add_range(struct vhost_iotlb *iotlb, EXPORT_SYMBOL_GPL(vhost_iotlb_add_range); /** - * vring_iotlb_del_range - delete overlapped ranges from vhost IOTLB + * vhost_iotlb_del_range - delete overlapped ranges from vhost IOTLB * @iotlb: the IOTLB * @start: start of the IOVA range * @last: last of IOVA range diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index d16c04dcc144..46f897e41217 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -1430,11 +1430,6 @@ static void vhost_scsi_handle_kick(struct vhost_work *work) vhost_scsi_handle_vq(vs, vq); } -static void vhost_scsi_flush_vq(struct vhost_scsi *vs, int index) -{ - vhost_poll_flush(&vs->vqs[index].vq.poll); -} - /* Callers must hold dev mutex */ static void vhost_scsi_flush(struct vhost_scsi *vs) { @@ -1453,10 +1448,7 @@ static void vhost_scsi_flush(struct vhost_scsi *vs) kref_put(&old_inflight[i]->kref, vhost_scsi_done_inflight); /* Flush both the vhost poll and vhost work */ - for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) - vhost_scsi_flush_vq(vs, i); - vhost_work_flush(&vs->dev, &vs->vs_completion_work); - vhost_work_flush(&vs->dev, &vs->vs_event_work); + vhost_work_dev_flush(&vs->dev); /* Wait for all reqs issued before the flush to be finished */ for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) @@ -1740,11 +1732,12 @@ vhost_scsi_clear_endpoint(struct vhost_scsi *vs, mutex_lock(&vq->mutex); vhost_vq_set_backend(vq, NULL); mutex_unlock(&vq->mutex); - /* - * Make sure cmds are not running before tearing them - * down. - */ - vhost_scsi_flush(vs); + } + /* Make sure cmds are not running before tearing them down. */ + vhost_scsi_flush(vs); + + for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) { + vq = &vs->vqs[i].vq; vhost_scsi_destroy_vq_cmds(vq); } } diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c index fb41db3da611..210ab35a7ebf 100644 --- a/drivers/vhost/vdpa.c +++ b/drivers/vhost/vdpa.c @@ -383,7 +383,7 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd, if (r) return r; - vq->last_avail_idx = vq_state.avail_index; + vq->last_avail_idx = vq_state.split.avail_index; break; } @@ -401,7 +401,7 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd, break; case VHOST_SET_VRING_BASE: - vq_state.avail_index = vq->last_avail_idx; + vq_state.split.avail_index = vq->last_avail_idx; if (ops->set_vq_state(vdpa, idx, &vq_state)) r = -EINVAL; break; diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 5ccb0705beae..b9e853e6094d 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -231,7 +231,7 @@ void vhost_poll_stop(struct vhost_poll *poll) } EXPORT_SYMBOL_GPL(vhost_poll_stop); -void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work) +void vhost_work_dev_flush(struct vhost_dev *dev) { struct vhost_flush_struct flush; @@ -243,13 +243,13 @@ void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work) wait_for_completion(&flush.wait_event); } } -EXPORT_SYMBOL_GPL(vhost_work_flush); +EXPORT_SYMBOL_GPL(vhost_work_dev_flush); /* Flush any work that has been scheduled. When calling this, don't hold any * locks that are also used by the callback. */ void vhost_poll_flush(struct vhost_poll *poll) { - vhost_work_flush(poll->dev, &poll->work); + vhost_work_dev_flush(poll->dev); } EXPORT_SYMBOL_GPL(vhost_poll_flush); @@ -538,7 +538,7 @@ static int vhost_attach_cgroups(struct vhost_dev *dev) attach.owner = current; vhost_work_init(&attach.work, vhost_attach_cgroups_work); vhost_work_queue(dev, &attach.work); - vhost_work_flush(dev, &attach.work); + vhost_work_dev_flush(dev); return attach.ret; } diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index b063324c7669..638bb640d6b4 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -20,20 +20,20 @@ typedef void (*vhost_work_fn_t)(struct vhost_work *work); #define VHOST_WORK_QUEUED 1 struct vhost_work { - struct llist_node node; - vhost_work_fn_t fn; - unsigned long flags; + struct llist_node node; + vhost_work_fn_t fn; + unsigned long flags; }; /* Poll a file (eventfd or socket) */ /* Note: there's nothing vhost specific about this structure. */ struct vhost_poll { - poll_table table; - wait_queue_head_t *wqh; - wait_queue_entry_t wait; - struct vhost_work work; - __poll_t mask; - struct vhost_dev *dev; + poll_table table; + wait_queue_head_t *wqh; + wait_queue_entry_t wait; + struct vhost_work work; + __poll_t mask; + struct vhost_dev *dev; }; void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn); @@ -46,8 +46,7 @@ int vhost_poll_start(struct vhost_poll *poll, struct file *file); void vhost_poll_stop(struct vhost_poll *poll); void vhost_poll_flush(struct vhost_poll *poll); void vhost_poll_queue(struct vhost_poll *poll); -void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work); -long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp); +void vhost_work_dev_flush(struct vhost_dev *dev); struct vhost_log { u64 addr; diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index d38c996b4f46..f249622ef11b 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -708,7 +708,7 @@ static void vhost_vsock_flush(struct vhost_vsock *vsock) for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++) if (vsock->vqs[i].handle_kick) vhost_poll_flush(&vsock->vqs[i].poll); - vhost_work_flush(&vsock->dev, &vsock->send_pkt_work); + vhost_work_dev_flush(&vsock->dev); } static void vhost_vsock_reset_orphans(struct sock *sk) diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index d83c87b902c1..e32694c13da5 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -128,12 +128,12 @@ config LCD_HX8357 If you have a HX-8357 LCD panel, say Y to enable its LCD control driver. - config LCD_OTM3225A - tristate "ORISE Technology OTM3225A support" - depends on SPI - help - If you have a panel based on the OTM3225A controller - chip then say y to include a driver for it. +config LCD_OTM3225A + tristate "ORISE Technology OTM3225A support" + depends on SPI + help + If you have a panel based on the OTM3225A controller + chip then say y to include a driver for it. endif # LCD_CLASS_DEVICE @@ -269,11 +269,11 @@ config BACKLIGHT_MAX8925 WLED output, say Y here to enable this driver. config BACKLIGHT_APPLE - tristate "Apple Backlight Driver" - depends on X86 && ACPI - help - If you have an Intel-based Apple say Y to enable a driver for its - backlight. + tristate "Apple Backlight Driver" + depends on X86 && ACPI + help + If you have an Intel-based Apple say Y to enable a driver for its + backlight. config BACKLIGHT_TOSA tristate "Sharp SL-6000 Backlight Driver" @@ -289,6 +289,14 @@ config BACKLIGHT_QCOM_WLED If you have the Qualcomm PMIC, say Y to enable a driver for the WLED block. Currently it supports PM8941 and PMI8998. +config BACKLIGHT_RT4831 + tristate "Richtek RT4831 Backlight Driver" + depends on MFD_RT4831 + help + This enables support for Richtek RT4831 Backlight driver. + It's commonly used to drive the display WLED. There're four channels + inisde, and each channel can provide up to 30mA current. + config BACKLIGHT_SAHARA tristate "Tabletkiosk Sahara Touch-iT Backlight Driver" depends on X86 diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 685f3f1ca4df..cae2c83422ae 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o obj-$(CONFIG_BACKLIGHT_QCOM_WLED) += qcom-wled.o +obj-$(CONFIG_BACKLIGHT_RT4831) += rt4831-backlight.o obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o obj-$(CONFIG_BACKLIGHT_SKY81452) += sky81452-backlight.o obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o diff --git a/drivers/video/backlight/lm3630a_bl.c b/drivers/video/backlight/lm3630a_bl.c index e88a2b0e5904..e8b185bb6f5e 100644 --- a/drivers/video/backlight/lm3630a_bl.c +++ b/drivers/video/backlight/lm3630a_bl.c @@ -52,6 +52,7 @@ struct lm3630a_chip { struct gpio_desc *enable_gpio; struct regmap *regmap; struct pwm_device *pwmd; + struct pwm_state pwmd_state; }; /* i2c access */ @@ -167,16 +168,19 @@ static int lm3630a_intr_config(struct lm3630a_chip *pchip) return rval; } -static void lm3630a_pwm_ctrl(struct lm3630a_chip *pchip, int br, int br_max) +static int lm3630a_pwm_ctrl(struct lm3630a_chip *pchip, int br, int br_max) { - unsigned int period = pchip->pdata->pwm_period; - unsigned int duty = br * period / br_max; + int err; - pwm_config(pchip->pwmd, duty, period); - if (duty) - pwm_enable(pchip->pwmd); - else - pwm_disable(pchip->pwmd); + pchip->pwmd_state.period = pchip->pdata->pwm_period; + + err = pwm_set_relative_duty_cycle(&pchip->pwmd_state, br, br_max); + if (err) + return err; + + pchip->pwmd_state.enabled = pchip->pwmd_state.duty_cycle ? true : false; + + return pwm_apply_state(pchip->pwmd, &pchip->pwmd_state); } /* update and get brightness */ @@ -187,11 +191,9 @@ static int lm3630a_bank_a_update_status(struct backlight_device *bl) enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; /* pwm control */ - if ((pwm_ctrl & LM3630A_PWM_BANK_A) != 0) { - lm3630a_pwm_ctrl(pchip, bl->props.brightness, - bl->props.max_brightness); - return bl->props.brightness; - } + if ((pwm_ctrl & LM3630A_PWM_BANK_A) != 0) + return lm3630a_pwm_ctrl(pchip, bl->props.brightness, + bl->props.max_brightness); /* disable sleep */ ret = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00); @@ -210,8 +212,8 @@ static int lm3630a_bank_a_update_status(struct backlight_device *bl) return 0; out_i2c_err: - dev_err(pchip->dev, "i2c failed to access\n"); - return bl->props.brightness; + dev_err(pchip->dev, "i2c failed to access (%pe)\n", ERR_PTR(ret)); + return ret; } static int lm3630a_bank_a_get_brightness(struct backlight_device *bl) @@ -264,11 +266,9 @@ static int lm3630a_bank_b_update_status(struct backlight_device *bl) enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; /* pwm control */ - if ((pwm_ctrl & LM3630A_PWM_BANK_B) != 0) { - lm3630a_pwm_ctrl(pchip, bl->props.brightness, - bl->props.max_brightness); - return bl->props.brightness; - } + if ((pwm_ctrl & LM3630A_PWM_BANK_B) != 0) + return lm3630a_pwm_ctrl(pchip, bl->props.brightness, + bl->props.max_brightness); /* disable sleep */ ret = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00); @@ -287,8 +287,8 @@ static int lm3630a_bank_b_update_status(struct backlight_device *bl) return 0; out_i2c_err: - dev_err(pchip->dev, "i2c failed to access REG_CTRL\n"); - return bl->props.brightness; + dev_err(pchip->dev, "i2c failed to access (%pe)\n", ERR_PTR(ret)); + return ret; } static int lm3630a_bank_b_get_brightness(struct backlight_device *bl) @@ -482,8 +482,10 @@ static int lm3630a_parse_node(struct lm3630a_chip *pchip, device_for_each_child_node(pchip->dev, node) { ret = lm3630a_parse_bank(pdata, node, &seen_led_sources); - if (ret) + if (ret) { + fwnode_handle_put(node); return ret; + } } return ret; @@ -563,11 +565,7 @@ static int lm3630a_probe(struct i2c_client *client, return PTR_ERR(pchip->pwmd); } - /* - * FIXME: pwm_apply_args() should be removed when switching to - * the atomic PWM API. - */ - pwm_apply_args(pchip->pwmd); + pwm_init_state(pchip->pwmd, &pchip->pwmd_state); } /* interrupt enable : irq 0 is not allowed */ diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c index 7c02f87c51c2..d094299c2a48 100644 --- a/drivers/video/backlight/qcom-wled.c +++ b/drivers/video/backlight/qcom-wled.c @@ -1717,6 +1717,7 @@ static int wled_remove(struct platform_device *pdev) static const struct of_device_id wled_match_table[] = { { .compatible = "qcom,pm8941-wled", .data = (void *)3 }, + { .compatible = "qcom,pmi8994-wled", .data = (void *)4 }, { .compatible = "qcom,pmi8998-wled", .data = (void *)4 }, { .compatible = "qcom,pm660l-wled", .data = (void *)4 }, { .compatible = "qcom,pm8150l-wled", .data = (void *)5 }, diff --git a/drivers/video/backlight/rt4831-backlight.c b/drivers/video/backlight/rt4831-backlight.c new file mode 100644 index 000000000000..42155c7d2db1 --- /dev/null +++ b/drivers/video/backlight/rt4831-backlight.c @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <dt-bindings/leds/rt4831-backlight.h> +#include <linux/backlight.h> +#include <linux/bitops.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/property.h> +#include <linux/regmap.h> + +#define RT4831_REG_BLCFG 0x02 +#define RT4831_REG_BLDIML 0x04 +#define RT4831_REG_ENABLE 0x08 + +#define RT4831_BLMAX_BRIGHTNESS 2048 + +#define RT4831_BLOVP_MASK GENMASK(7, 5) +#define RT4831_BLOVP_SHIFT 5 +#define RT4831_BLPWMEN_MASK BIT(0) +#define RT4831_BLEN_MASK BIT(4) +#define RT4831_BLCH_MASK GENMASK(3, 0) +#define RT4831_BLDIML_MASK GENMASK(2, 0) +#define RT4831_BLDIMH_MASK GENMASK(10, 3) +#define RT4831_BLDIMH_SHIFT 3 + +struct rt4831_priv { + struct device *dev; + struct regmap *regmap; + struct backlight_device *bl; +}; + +static int rt4831_bl_update_status(struct backlight_device *bl_dev) +{ + struct rt4831_priv *priv = bl_get_data(bl_dev); + int brightness = backlight_get_brightness(bl_dev); + unsigned int enable = brightness ? RT4831_BLEN_MASK : 0; + u8 v[2]; + int ret; + + if (brightness) { + v[0] = (brightness - 1) & RT4831_BLDIML_MASK; + v[1] = ((brightness - 1) & RT4831_BLDIMH_MASK) >> RT4831_BLDIMH_SHIFT; + + ret = regmap_raw_write(priv->regmap, RT4831_REG_BLDIML, v, sizeof(v)); + if (ret) + return ret; + } + + return regmap_update_bits(priv->regmap, RT4831_REG_ENABLE, RT4831_BLEN_MASK, enable); + +} + +static int rt4831_bl_get_brightness(struct backlight_device *bl_dev) +{ + struct rt4831_priv *priv = bl_get_data(bl_dev); + unsigned int val; + u8 v[2]; + int ret; + + ret = regmap_read(priv->regmap, RT4831_REG_ENABLE, &val); + if (ret) + return ret; + + if (!(val & RT4831_BLEN_MASK)) + return 0; + + ret = regmap_raw_read(priv->regmap, RT4831_REG_BLDIML, v, sizeof(v)); + if (ret) + return ret; + + ret = (v[1] << RT4831_BLDIMH_SHIFT) + (v[0] & RT4831_BLDIML_MASK) + 1; + + return ret; +} + +static const struct backlight_ops rt4831_bl_ops = { + .options = BL_CORE_SUSPENDRESUME, + .update_status = rt4831_bl_update_status, + .get_brightness = rt4831_bl_get_brightness, +}; + +static int rt4831_parse_backlight_properties(struct rt4831_priv *priv, + struct backlight_properties *bl_props) +{ + struct device *dev = priv->dev; + u8 propval; + u32 brightness; + unsigned int val = 0; + int ret; + + /* common properties */ + ret = device_property_read_u32(dev, "max-brightness", &brightness); + if (ret) + brightness = RT4831_BLMAX_BRIGHTNESS; + + bl_props->max_brightness = min_t(u32, brightness, RT4831_BLMAX_BRIGHTNESS); + + ret = device_property_read_u32(dev, "default-brightness", &brightness); + if (ret) + brightness = bl_props->max_brightness; + + bl_props->brightness = min_t(u32, brightness, bl_props->max_brightness); + + /* vendor properties */ + if (device_property_read_bool(dev, "richtek,pwm-enable")) + val = RT4831_BLPWMEN_MASK; + + ret = regmap_update_bits(priv->regmap, RT4831_REG_BLCFG, RT4831_BLPWMEN_MASK, val); + if (ret) + return ret; + + ret = device_property_read_u8(dev, "richtek,bled-ovp-sel", &propval); + if (ret) + propval = RT4831_BLOVPLVL_21V; + + propval = min_t(u8, propval, RT4831_BLOVPLVL_29V); + ret = regmap_update_bits(priv->regmap, RT4831_REG_BLCFG, RT4831_BLOVP_MASK, + propval << RT4831_BLOVP_SHIFT); + if (ret) + return ret; + + ret = device_property_read_u8(dev, "richtek,channel-use", &propval); + if (ret) { + dev_err(dev, "richtek,channel-use DT property missing\n"); + return ret; + } + + if (!(propval & RT4831_BLCH_MASK)) { + dev_err(dev, "No channel specified\n"); + return -EINVAL; + } + + return regmap_update_bits(priv->regmap, RT4831_REG_ENABLE, RT4831_BLCH_MASK, propval); +} + +static int rt4831_bl_probe(struct platform_device *pdev) +{ + struct rt4831_priv *priv; + struct backlight_properties bl_props = { .type = BACKLIGHT_RAW, + .scale = BACKLIGHT_SCALE_LINEAR }; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = &pdev->dev; + + priv->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!priv->regmap) { + dev_err(&pdev->dev, "Failed to init regmap\n"); + return -ENODEV; + } + + ret = rt4831_parse_backlight_properties(priv, &bl_props); + if (ret) { + dev_err(&pdev->dev, "Failed to parse backlight properties\n"); + return ret; + } + + priv->bl = devm_backlight_device_register(&pdev->dev, pdev->name, &pdev->dev, priv, + &rt4831_bl_ops, &bl_props); + if (IS_ERR(priv->bl)) { + dev_err(&pdev->dev, "Failed to register backlight\n"); + return PTR_ERR(priv->bl); + } + + backlight_update_status(priv->bl); + platform_set_drvdata(pdev, priv); + + return 0; +} + +static int rt4831_bl_remove(struct platform_device *pdev) +{ + struct rt4831_priv *priv = platform_get_drvdata(pdev); + struct backlight_device *bl_dev = priv->bl; + + bl_dev->props.brightness = 0; + backlight_update_status(priv->bl); + + return 0; +} + +static const struct of_device_id __maybe_unused rt4831_bl_of_match[] = { + { .compatible = "richtek,rt4831-backlight", }, + {} +}; +MODULE_DEVICE_TABLE(of, rt4831_bl_of_match); + +static struct platform_driver rt4831_bl_driver = { + .driver = { + .name = "rt4831-backlight", + .of_match_table = rt4831_bl_of_match, + }, + .probe = rt4831_bl_probe, + .remove = rt4831_bl_remove, +}; +module_platform_driver(rt4831_bl_driver); + +MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index ee33b8ec62bb..840d9813b0bc 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -9,7 +9,7 @@ config VGA_CONSOLE bool "VGA text console" if EXPERT || !X86 depends on !4xx && !PPC_8xx && !SPARC && !M68K && !PARISC && !SUPERH && \ (!ARM || ARCH_FOOTBRIDGE || ARCH_INTEGRATOR || ARCH_NETWINDER) && \ - !ARM64 && !ARC && !MICROBLAZE && !OPENRISC && !NDS32 && !S390 + !ARM64 && !ARC && !MICROBLAZE && !OPENRISC && !NDS32 && !S390 && !UML default y help Saying Y here will allow you to use Linux in text mode through a diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index 5e1ad0c92bfc..d33c5cd684c0 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -2209,7 +2209,6 @@ config FB_SIMPLE config FB_SSD1307 tristate "Solomon SSD1307 framebuffer support" depends on FB && I2C - depends on OF depends on GPIOLIB || COMPILE_TEST select FB_SYS_FOPS select FB_SYS_FILLRECT diff --git a/drivers/virt/nitro_enclaves/ne_pci_dev.c b/drivers/virt/nitro_enclaves/ne_pci_dev.c index b9c1de41e300..143207e9b969 100644 --- a/drivers/virt/nitro_enclaves/ne_pci_dev.c +++ b/drivers/virt/nitro_enclaves/ne_pci_dev.c @@ -480,6 +480,8 @@ static int ne_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto free_ne_pci_dev; } + pci_set_master(pdev); + rc = pci_request_regions_exclusive(pdev, "nitro_enclaves"); if (rc < 0) { dev_err(&pdev->dev, "Error in pci request regions [rc=%d]\n", rc); diff --git a/drivers/virtio/virtio_mem.c b/drivers/virtio/virtio_mem.c index dc2a2e2b2ff8..09ed55de07d7 100644 --- a/drivers/virtio/virtio_mem.c +++ b/drivers/virtio/virtio_mem.c @@ -75,10 +75,14 @@ enum virtio_mem_sbm_mb_state { VIRTIO_MEM_SBM_MB_OFFLINE, /* Partially plugged, fully added to Linux, offline. */ VIRTIO_MEM_SBM_MB_OFFLINE_PARTIAL, - /* Fully plugged, fully added to Linux, online. */ - VIRTIO_MEM_SBM_MB_ONLINE, - /* Partially plugged, fully added to Linux, online. */ - VIRTIO_MEM_SBM_MB_ONLINE_PARTIAL, + /* Fully plugged, fully added to Linux, onlined to a kernel zone. */ + VIRTIO_MEM_SBM_MB_KERNEL, + /* Partially plugged, fully added to Linux, online to a kernel zone */ + VIRTIO_MEM_SBM_MB_KERNEL_PARTIAL, + /* Fully plugged, fully added to Linux, onlined to ZONE_MOVABLE. */ + VIRTIO_MEM_SBM_MB_MOVABLE, + /* Partially plugged, fully added to Linux, onlined to ZONE_MOVABLE. */ + VIRTIO_MEM_SBM_MB_MOVABLE_PARTIAL, VIRTIO_MEM_SBM_MB_COUNT }; @@ -699,18 +703,6 @@ static int virtio_mem_sbm_remove_mb(struct virtio_mem *vm, unsigned long mb_id) } /* - * See virtio_mem_remove_memory(): Try to remove all Linux memory blocks covered - * by the big block. - */ -static int virtio_mem_bbm_remove_bb(struct virtio_mem *vm, unsigned long bb_id) -{ - const uint64_t addr = virtio_mem_bb_id_to_phys(vm, bb_id); - const uint64_t size = vm->bbm.bb_size; - - return virtio_mem_remove_memory(vm, addr, size); -} - -/* * Try offlining and removing memory from Linux. * * Must not be called with the vm->hotplug_mutex held (possible deadlock with @@ -832,11 +824,13 @@ static void virtio_mem_sbm_notify_offline(struct virtio_mem *vm, unsigned long mb_id) { switch (virtio_mem_sbm_get_mb_state(vm, mb_id)) { - case VIRTIO_MEM_SBM_MB_ONLINE_PARTIAL: + case VIRTIO_MEM_SBM_MB_KERNEL_PARTIAL: + case VIRTIO_MEM_SBM_MB_MOVABLE_PARTIAL: virtio_mem_sbm_set_mb_state(vm, mb_id, VIRTIO_MEM_SBM_MB_OFFLINE_PARTIAL); break; - case VIRTIO_MEM_SBM_MB_ONLINE: + case VIRTIO_MEM_SBM_MB_KERNEL: + case VIRTIO_MEM_SBM_MB_MOVABLE: virtio_mem_sbm_set_mb_state(vm, mb_id, VIRTIO_MEM_SBM_MB_OFFLINE); break; @@ -847,21 +841,29 @@ static void virtio_mem_sbm_notify_offline(struct virtio_mem *vm, } static void virtio_mem_sbm_notify_online(struct virtio_mem *vm, - unsigned long mb_id) + unsigned long mb_id, + unsigned long start_pfn) { + const bool is_movable = page_zonenum(pfn_to_page(start_pfn)) == + ZONE_MOVABLE; + int new_state; + switch (virtio_mem_sbm_get_mb_state(vm, mb_id)) { case VIRTIO_MEM_SBM_MB_OFFLINE_PARTIAL: - virtio_mem_sbm_set_mb_state(vm, mb_id, - VIRTIO_MEM_SBM_MB_ONLINE_PARTIAL); + new_state = VIRTIO_MEM_SBM_MB_KERNEL_PARTIAL; + if (is_movable) + new_state = VIRTIO_MEM_SBM_MB_MOVABLE_PARTIAL; break; case VIRTIO_MEM_SBM_MB_OFFLINE: - virtio_mem_sbm_set_mb_state(vm, mb_id, - VIRTIO_MEM_SBM_MB_ONLINE); + new_state = VIRTIO_MEM_SBM_MB_KERNEL; + if (is_movable) + new_state = VIRTIO_MEM_SBM_MB_MOVABLE; break; default: BUG(); break; } + virtio_mem_sbm_set_mb_state(vm, mb_id, new_state); } static void virtio_mem_sbm_notify_going_offline(struct virtio_mem *vm, @@ -1015,7 +1017,7 @@ static int virtio_mem_memory_notifier_cb(struct notifier_block *nb, break; case MEM_ONLINE: if (vm->in_sbm) - virtio_mem_sbm_notify_online(vm, id); + virtio_mem_sbm_notify_online(vm, id, mhp->start_pfn); atomic64_sub(size, &vm->offline_size); /* @@ -1137,7 +1139,7 @@ static void virtio_mem_fake_online(unsigned long pfn, unsigned long nr_pages) */ static int virtio_mem_fake_offline(unsigned long pfn, unsigned long nr_pages) { - const bool is_movable = zone_idx(page_zone(pfn_to_page(pfn))) == + const bool is_movable = page_zonenum(pfn_to_page(pfn)) == ZONE_MOVABLE; int rc, retry_count; @@ -1455,8 +1457,8 @@ static int virtio_mem_bbm_plug_bb(struct virtio_mem *vm, unsigned long bb_id) * * Note: can fail after some subblocks were unplugged. */ -static int virtio_mem_sbm_unplug_any_sb(struct virtio_mem *vm, - unsigned long mb_id, uint64_t *nb_sb) +static int virtio_mem_sbm_unplug_any_sb_raw(struct virtio_mem *vm, + unsigned long mb_id, uint64_t *nb_sb) { int sb_id, count; int rc; @@ -1498,7 +1500,7 @@ static int virtio_mem_sbm_unplug_mb(struct virtio_mem *vm, unsigned long mb_id) { uint64_t nb_sb = vm->sbm.sbs_per_mb; - return virtio_mem_sbm_unplug_any_sb(vm, mb_id, &nb_sb); + return virtio_mem_sbm_unplug_any_sb_raw(vm, mb_id, &nb_sb); } /* @@ -1585,9 +1587,9 @@ static int virtio_mem_sbm_plug_and_add_mb(struct virtio_mem *vm, * Note: Can fail after some subblocks were successfully plugged. */ static int virtio_mem_sbm_plug_any_sb(struct virtio_mem *vm, - unsigned long mb_id, uint64_t *nb_sb, - bool online) + unsigned long mb_id, uint64_t *nb_sb) { + const int old_state = virtio_mem_sbm_get_mb_state(vm, mb_id); unsigned long pfn, nr_pages; int sb_id, count; int rc; @@ -1609,7 +1611,7 @@ static int virtio_mem_sbm_plug_any_sb(struct virtio_mem *vm, if (rc) return rc; *nb_sb -= count; - if (!online) + if (old_state == VIRTIO_MEM_SBM_MB_OFFLINE_PARTIAL) continue; /* fake-online the pages if the memory block is online */ @@ -1619,23 +1621,22 @@ static int virtio_mem_sbm_plug_any_sb(struct virtio_mem *vm, virtio_mem_fake_online(pfn, nr_pages); } - if (virtio_mem_sbm_test_sb_plugged(vm, mb_id, 0, vm->sbm.sbs_per_mb)) { - if (online) - virtio_mem_sbm_set_mb_state(vm, mb_id, - VIRTIO_MEM_SBM_MB_ONLINE); - else - virtio_mem_sbm_set_mb_state(vm, mb_id, - VIRTIO_MEM_SBM_MB_OFFLINE); - } + if (virtio_mem_sbm_test_sb_plugged(vm, mb_id, 0, vm->sbm.sbs_per_mb)) + virtio_mem_sbm_set_mb_state(vm, mb_id, old_state - 1); return 0; } static int virtio_mem_sbm_plug_request(struct virtio_mem *vm, uint64_t diff) { + const int mb_states[] = { + VIRTIO_MEM_SBM_MB_KERNEL_PARTIAL, + VIRTIO_MEM_SBM_MB_MOVABLE_PARTIAL, + VIRTIO_MEM_SBM_MB_OFFLINE_PARTIAL, + }; uint64_t nb_sb = diff / vm->sbm.sb_size; unsigned long mb_id; - int rc; + int rc, i; if (!nb_sb) return 0; @@ -1643,22 +1644,13 @@ static int virtio_mem_sbm_plug_request(struct virtio_mem *vm, uint64_t diff) /* Don't race with onlining/offlining */ mutex_lock(&vm->hotplug_mutex); - /* Try to plug subblocks of partially plugged online blocks. */ - virtio_mem_sbm_for_each_mb(vm, mb_id, - VIRTIO_MEM_SBM_MB_ONLINE_PARTIAL) { - rc = virtio_mem_sbm_plug_any_sb(vm, mb_id, &nb_sb, true); - if (rc || !nb_sb) - goto out_unlock; - cond_resched(); - } - - /* Try to plug subblocks of partially plugged offline blocks. */ - virtio_mem_sbm_for_each_mb(vm, mb_id, - VIRTIO_MEM_SBM_MB_OFFLINE_PARTIAL) { - rc = virtio_mem_sbm_plug_any_sb(vm, mb_id, &nb_sb, false); - if (rc || !nb_sb) - goto out_unlock; - cond_resched(); + for (i = 0; i < ARRAY_SIZE(mb_states); i++) { + virtio_mem_sbm_for_each_mb(vm, mb_id, mb_states[i]) { + rc = virtio_mem_sbm_plug_any_sb(vm, mb_id, &nb_sb); + if (rc || !nb_sb) + goto out_unlock; + cond_resched(); + } } /* @@ -1819,7 +1811,7 @@ static int virtio_mem_sbm_unplug_any_sb_offline(struct virtio_mem *vm, { int rc; - rc = virtio_mem_sbm_unplug_any_sb(vm, mb_id, nb_sb); + rc = virtio_mem_sbm_unplug_any_sb_raw(vm, mb_id, nb_sb); /* some subblocks might have been unplugged even on failure */ if (!virtio_mem_sbm_test_sb_plugged(vm, mb_id, 0, vm->sbm.sbs_per_mb)) @@ -1856,6 +1848,7 @@ static int virtio_mem_sbm_unplug_sb_online(struct virtio_mem *vm, int count) { const unsigned long nr_pages = PFN_DOWN(vm->sbm.sb_size) * count; + const int old_state = virtio_mem_sbm_get_mb_state(vm, mb_id); unsigned long start_pfn; int rc; @@ -1874,8 +1867,17 @@ static int virtio_mem_sbm_unplug_sb_online(struct virtio_mem *vm, return rc; } - virtio_mem_sbm_set_mb_state(vm, mb_id, - VIRTIO_MEM_SBM_MB_ONLINE_PARTIAL); + switch (old_state) { + case VIRTIO_MEM_SBM_MB_KERNEL: + virtio_mem_sbm_set_mb_state(vm, mb_id, + VIRTIO_MEM_SBM_MB_KERNEL_PARTIAL); + break; + case VIRTIO_MEM_SBM_MB_MOVABLE: + virtio_mem_sbm_set_mb_state(vm, mb_id, + VIRTIO_MEM_SBM_MB_MOVABLE_PARTIAL); + break; + } + return 0; } @@ -1942,11 +1944,50 @@ unplugged: return 0; } +/* + * Unplug the desired number of plugged subblocks of a memory block that is + * already added to Linux. Will skip subblock of online memory blocks that are + * busy (by the OS). Will fail if any subblock that's not busy cannot get + * unplugged. + * + * Will modify the state of the memory block. Might temporarily drop the + * hotplug_mutex. + * + * Note: Can fail after some subblocks were successfully unplugged. Can + * return 0 even if subblocks were busy and could not get unplugged. + */ +static int virtio_mem_sbm_unplug_any_sb(struct virtio_mem *vm, + unsigned long mb_id, + uint64_t *nb_sb) +{ + const int old_state = virtio_mem_sbm_get_mb_state(vm, mb_id); + + switch (old_state) { + case VIRTIO_MEM_SBM_MB_KERNEL_PARTIAL: + case VIRTIO_MEM_SBM_MB_KERNEL: + case VIRTIO_MEM_SBM_MB_MOVABLE_PARTIAL: + case VIRTIO_MEM_SBM_MB_MOVABLE: + return virtio_mem_sbm_unplug_any_sb_online(vm, mb_id, nb_sb); + case VIRTIO_MEM_SBM_MB_OFFLINE_PARTIAL: + case VIRTIO_MEM_SBM_MB_OFFLINE: + return virtio_mem_sbm_unplug_any_sb_offline(vm, mb_id, nb_sb); + } + return -EINVAL; +} + static int virtio_mem_sbm_unplug_request(struct virtio_mem *vm, uint64_t diff) { + const int mb_states[] = { + VIRTIO_MEM_SBM_MB_OFFLINE_PARTIAL, + VIRTIO_MEM_SBM_MB_OFFLINE, + VIRTIO_MEM_SBM_MB_MOVABLE_PARTIAL, + VIRTIO_MEM_SBM_MB_KERNEL_PARTIAL, + VIRTIO_MEM_SBM_MB_MOVABLE, + VIRTIO_MEM_SBM_MB_KERNEL, + }; uint64_t nb_sb = diff / vm->sbm.sb_size; unsigned long mb_id; - int rc; + int rc, i; if (!nb_sb) return 0; @@ -1958,47 +1999,26 @@ static int virtio_mem_sbm_unplug_request(struct virtio_mem *vm, uint64_t diff) */ mutex_lock(&vm->hotplug_mutex); - /* Try to unplug subblocks of partially plugged offline blocks. */ - virtio_mem_sbm_for_each_mb_rev(vm, mb_id, - VIRTIO_MEM_SBM_MB_OFFLINE_PARTIAL) { - rc = virtio_mem_sbm_unplug_any_sb_offline(vm, mb_id, &nb_sb); - if (rc || !nb_sb) - goto out_unlock; - cond_resched(); - } - - /* Try to unplug subblocks of plugged offline blocks. */ - virtio_mem_sbm_for_each_mb_rev(vm, mb_id, VIRTIO_MEM_SBM_MB_OFFLINE) { - rc = virtio_mem_sbm_unplug_any_sb_offline(vm, mb_id, &nb_sb); - if (rc || !nb_sb) - goto out_unlock; - cond_resched(); - } - - if (!unplug_online) { - mutex_unlock(&vm->hotplug_mutex); - return 0; - } - - /* Try to unplug subblocks of partially plugged online blocks. */ - virtio_mem_sbm_for_each_mb_rev(vm, mb_id, - VIRTIO_MEM_SBM_MB_ONLINE_PARTIAL) { - rc = virtio_mem_sbm_unplug_any_sb_online(vm, mb_id, &nb_sb); - if (rc || !nb_sb) - goto out_unlock; - mutex_unlock(&vm->hotplug_mutex); - cond_resched(); - mutex_lock(&vm->hotplug_mutex); - } - - /* Try to unplug subblocks of plugged online blocks. */ - virtio_mem_sbm_for_each_mb_rev(vm, mb_id, VIRTIO_MEM_SBM_MB_ONLINE) { - rc = virtio_mem_sbm_unplug_any_sb_online(vm, mb_id, &nb_sb); - if (rc || !nb_sb) - goto out_unlock; - mutex_unlock(&vm->hotplug_mutex); - cond_resched(); - mutex_lock(&vm->hotplug_mutex); + /* + * We try unplug from partially plugged blocks first, to try removing + * whole memory blocks along with metadata. We prioritize ZONE_MOVABLE + * as it's more reliable to unplug memory and remove whole memory + * blocks, and we don't want to trigger a zone imbalances by + * accidentially removing too much kernel memory. + */ + for (i = 0; i < ARRAY_SIZE(mb_states); i++) { + virtio_mem_sbm_for_each_mb_rev(vm, mb_id, mb_states[i]) { + rc = virtio_mem_sbm_unplug_any_sb(vm, mb_id, &nb_sb); + if (rc || !nb_sb) + goto out_unlock; + mutex_unlock(&vm->hotplug_mutex); + cond_resched(); + mutex_lock(&vm->hotplug_mutex); + } + if (!unplug_online && i == 1) { + mutex_unlock(&vm->hotplug_mutex); + return 0; + } } mutex_unlock(&vm->hotplug_mutex); @@ -2085,47 +2105,41 @@ rollback_safe_unplug: } /* - * Try to remove a big block from Linux and unplug it. Will fail with - * -EBUSY if some memory is online. - * - * Will modify the state of the memory block. + * Test if a big block is completely offline. */ -static int virtio_mem_bbm_remove_and_unplug_bb(struct virtio_mem *vm, - unsigned long bb_id) +static bool virtio_mem_bbm_bb_is_offline(struct virtio_mem *vm, + unsigned long bb_id) { - int rc; - - if (WARN_ON_ONCE(virtio_mem_bbm_get_bb_state(vm, bb_id) != - VIRTIO_MEM_BBM_BB_ADDED)) - return -EINVAL; + const unsigned long start_pfn = PFN_DOWN(virtio_mem_bb_id_to_phys(vm, bb_id)); + const unsigned long nr_pages = PFN_DOWN(vm->bbm.bb_size); + unsigned long pfn; - rc = virtio_mem_bbm_remove_bb(vm, bb_id); - if (rc) - return -EBUSY; + for (pfn = start_pfn; pfn < start_pfn + nr_pages; + pfn += PAGES_PER_SECTION) { + if (pfn_to_online_page(pfn)) + return false; + } - rc = virtio_mem_bbm_unplug_bb(vm, bb_id); - if (rc) - virtio_mem_bbm_set_bb_state(vm, bb_id, - VIRTIO_MEM_BBM_BB_PLUGGED); - else - virtio_mem_bbm_set_bb_state(vm, bb_id, - VIRTIO_MEM_BBM_BB_UNUSED); - return rc; + return true; } /* - * Test if a big block is completely offline. + * Test if a big block is completely onlined to ZONE_MOVABLE (or offline). */ -static bool virtio_mem_bbm_bb_is_offline(struct virtio_mem *vm, +static bool virtio_mem_bbm_bb_is_movable(struct virtio_mem *vm, unsigned long bb_id) { const unsigned long start_pfn = PFN_DOWN(virtio_mem_bb_id_to_phys(vm, bb_id)); const unsigned long nr_pages = PFN_DOWN(vm->bbm.bb_size); + struct page *page; unsigned long pfn; for (pfn = start_pfn; pfn < start_pfn + nr_pages; pfn += PAGES_PER_SECTION) { - if (pfn_to_online_page(pfn)) + page = pfn_to_online_page(pfn); + if (!page) + continue; + if (page_zonenum(page) != ZONE_MOVABLE) return false; } @@ -2136,42 +2150,37 @@ static int virtio_mem_bbm_unplug_request(struct virtio_mem *vm, uint64_t diff) { uint64_t nb_bb = diff / vm->bbm.bb_size; uint64_t bb_id; - int rc; + int rc, i; if (!nb_bb) return 0; - /* Try to unplug completely offline big blocks first. */ - virtio_mem_bbm_for_each_bb_rev(vm, bb_id, VIRTIO_MEM_BBM_BB_ADDED) { - cond_resched(); - /* - * As we're holding no locks, this check is racy as memory - * can get onlined in the meantime - but we'll fail gracefully. - */ - if (!virtio_mem_bbm_bb_is_offline(vm, bb_id)) - continue; - rc = virtio_mem_bbm_remove_and_unplug_bb(vm, bb_id); - if (rc == -EBUSY) - continue; - if (!rc) - nb_bb--; - if (rc || !nb_bb) - return rc; - } - - if (!unplug_online) - return 0; + /* + * Try to unplug big blocks. Similar to SBM, start with offline + * big blocks. + */ + for (i = 0; i < 3; i++) { + virtio_mem_bbm_for_each_bb_rev(vm, bb_id, VIRTIO_MEM_BBM_BB_ADDED) { + cond_resched(); - /* Try to unplug any big blocks. */ - virtio_mem_bbm_for_each_bb_rev(vm, bb_id, VIRTIO_MEM_BBM_BB_ADDED) { - cond_resched(); - rc = virtio_mem_bbm_offline_remove_and_unplug_bb(vm, bb_id); - if (rc == -EBUSY) - continue; - if (!rc) - nb_bb--; - if (rc || !nb_bb) - return rc; + /* + * As we're holding no locks, these checks are racy, + * but we don't care. + */ + if (i == 0 && !virtio_mem_bbm_bb_is_offline(vm, bb_id)) + continue; + if (i == 1 && !virtio_mem_bbm_bb_is_movable(vm, bb_id)) + continue; + rc = virtio_mem_bbm_offline_remove_and_unplug_bb(vm, bb_id); + if (rc == -EBUSY) + continue; + if (!rc) + nb_bb--; + if (rc || !nb_bb) + return rc; + } + if (i == 0 && !unplug_online) + return 0; } return nb_bb ? -EBUSY : 0; @@ -2422,6 +2431,10 @@ static int virtio_mem_init(struct virtio_mem *vm) dev_warn(&vm->vdev->dev, "Some device memory is not addressable/pluggable. This can make some memory unusable.\n"); + /* Prepare the offline threshold - make sure we can add two blocks. */ + vm->offline_threshold = max_t(uint64_t, 2 * memory_block_size_bytes(), + VIRTIO_MEM_DEFAULT_OFFLINE_THRESHOLD); + /* * We want subblocks to span at least MAX_ORDER_NR_PAGES and * pageblock_nr_pages pages. This: @@ -2468,14 +2481,11 @@ static int virtio_mem_init(struct virtio_mem *vm) vm->bbm.bb_size - 1; vm->bbm.first_bb_id = virtio_mem_phys_to_bb_id(vm, addr); vm->bbm.next_bb_id = vm->bbm.first_bb_id; - } - /* Prepare the offline threshold - make sure we can add two blocks. */ - vm->offline_threshold = max_t(uint64_t, 2 * memory_block_size_bytes(), - VIRTIO_MEM_DEFAULT_OFFLINE_THRESHOLD); - /* In BBM, we also want at least two big blocks. */ - vm->offline_threshold = max_t(uint64_t, 2 * vm->bbm.bb_size, - vm->offline_threshold); + /* Make sure we can add two big blocks. */ + vm->offline_threshold = max_t(uint64_t, 2 * vm->bbm.bb_size, + vm->offline_threshold); + } dev_info(&vm->vdev->dev, "start address: 0x%llx", vm->addr); dev_info(&vm->vdev->dev, "region size: 0x%llx", vm->region_size); diff --git a/drivers/virtio/virtio_pci_modern_dev.c b/drivers/virtio/virtio_pci_modern_dev.c index 54f297028586..e11ed748e661 100644 --- a/drivers/virtio/virtio_pci_modern_dev.c +++ b/drivers/virtio/virtio_pci_modern_dev.c @@ -384,6 +384,27 @@ u64 vp_modern_get_features(struct virtio_pci_modern_device *mdev) EXPORT_SYMBOL_GPL(vp_modern_get_features); /* + * vp_modern_get_driver_features - get driver features from device + * @mdev: the modern virtio-pci device + * + * Returns the driver features read from the device + */ +u64 vp_modern_get_driver_features(struct virtio_pci_modern_device *mdev) +{ + struct virtio_pci_common_cfg __iomem *cfg = mdev->common; + + u64 features; + + vp_iowrite32(0, &cfg->guest_feature_select); + features = vp_ioread32(&cfg->guest_feature); + vp_iowrite32(1, &cfg->guest_feature_select); + features |= ((u64)vp_ioread32(&cfg->guest_feature) << 32); + + return features; +} +EXPORT_SYMBOL_GPL(vp_modern_get_driver_features); + +/* * vp_modern_set_features - set features to device * @mdev: the modern virtio-pci device * @features: the features set to device diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 71e16b53e9c1..89bfe46a8a7f 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -74,14 +74,14 @@ struct vring_desc_state_packed { void *data; /* Data for callback. */ struct vring_packed_desc *indir_desc; /* Indirect descriptor, if any. */ u16 num; /* Descriptor list length. */ - u16 next; /* The next desc state in a list. */ u16 last; /* The last desc state in a list. */ }; -struct vring_desc_extra_packed { +struct vring_desc_extra { dma_addr_t addr; /* Buffer DMA addr. */ u32 len; /* Buffer length. */ u16 flags; /* Descriptor flags. */ + u16 next; /* The next desc state in a list. */ }; struct vring_virtqueue { @@ -113,6 +113,9 @@ struct vring_virtqueue { /* Last used index we've seen. */ u16 last_used_idx; + /* Hint for event idx: already triggered no need to disable. */ + bool event_triggered; + union { /* Available for split ring */ struct { @@ -130,6 +133,7 @@ struct vring_virtqueue { /* Per-descriptor state. */ struct vring_desc_state_split *desc_state; + struct vring_desc_extra *desc_extra; /* DMA address and size information */ dma_addr_t queue_dma_addr; @@ -166,7 +170,7 @@ struct vring_virtqueue { /* Per-descriptor state. */ struct vring_desc_state_packed *desc_state; - struct vring_desc_extra_packed *desc_extra; + struct vring_desc_extra *desc_extra; /* DMA address and size information */ dma_addr_t ring_dma_addr; @@ -364,8 +368,8 @@ static int vring_mapping_error(const struct vring_virtqueue *vq, * Split ring specific functions - *_split(). */ -static void vring_unmap_one_split(const struct vring_virtqueue *vq, - struct vring_desc *desc) +static void vring_unmap_one_split_indirect(const struct vring_virtqueue *vq, + struct vring_desc *desc) { u16 flags; @@ -389,6 +393,35 @@ static void vring_unmap_one_split(const struct vring_virtqueue *vq, } } +static unsigned int vring_unmap_one_split(const struct vring_virtqueue *vq, + unsigned int i) +{ + struct vring_desc_extra *extra = vq->split.desc_extra; + u16 flags; + + if (!vq->use_dma_api) + goto out; + + flags = extra[i].flags; + + if (flags & VRING_DESC_F_INDIRECT) { + dma_unmap_single(vring_dma_dev(vq), + extra[i].addr, + extra[i].len, + (flags & VRING_DESC_F_WRITE) ? + DMA_FROM_DEVICE : DMA_TO_DEVICE); + } else { + dma_unmap_page(vring_dma_dev(vq), + extra[i].addr, + extra[i].len, + (flags & VRING_DESC_F_WRITE) ? + DMA_FROM_DEVICE : DMA_TO_DEVICE); + } + +out: + return extra[i].next; +} + static struct vring_desc *alloc_indirect_split(struct virtqueue *_vq, unsigned int total_sg, gfp_t gfp) @@ -412,6 +445,35 @@ static struct vring_desc *alloc_indirect_split(struct virtqueue *_vq, return desc; } +static inline unsigned int virtqueue_add_desc_split(struct virtqueue *vq, + struct vring_desc *desc, + unsigned int i, + dma_addr_t addr, + unsigned int len, + u16 flags, + bool indirect) +{ + struct vring_virtqueue *vring = to_vvq(vq); + struct vring_desc_extra *extra = vring->split.desc_extra; + u16 next; + + desc[i].flags = cpu_to_virtio16(vq->vdev, flags); + desc[i].addr = cpu_to_virtio64(vq->vdev, addr); + desc[i].len = cpu_to_virtio32(vq->vdev, len); + + if (!indirect) { + next = extra[i].next; + desc[i].next = cpu_to_virtio16(vq->vdev, next); + + extra[i].addr = addr; + extra[i].len = len; + extra[i].flags = flags; + } else + next = virtio16_to_cpu(vq->vdev, desc[i].next); + + return next; +} + static inline int virtqueue_add_split(struct virtqueue *_vq, struct scatterlist *sgs[], unsigned int total_sg, @@ -484,11 +546,13 @@ static inline int virtqueue_add_split(struct virtqueue *_vq, if (vring_mapping_error(vq, addr)) goto unmap_release; - desc[i].flags = cpu_to_virtio16(_vq->vdev, VRING_DESC_F_NEXT); - desc[i].addr = cpu_to_virtio64(_vq->vdev, addr); - desc[i].len = cpu_to_virtio32(_vq->vdev, sg->length); prev = i; - i = virtio16_to_cpu(_vq->vdev, desc[i].next); + /* Note that we trust indirect descriptor + * table since it use stream DMA mapping. + */ + i = virtqueue_add_desc_split(_vq, desc, i, addr, sg->length, + VRING_DESC_F_NEXT, + indirect); } } for (; n < (out_sgs + in_sgs); n++) { @@ -497,15 +561,22 @@ static inline int virtqueue_add_split(struct virtqueue *_vq, if (vring_mapping_error(vq, addr)) goto unmap_release; - desc[i].flags = cpu_to_virtio16(_vq->vdev, VRING_DESC_F_NEXT | VRING_DESC_F_WRITE); - desc[i].addr = cpu_to_virtio64(_vq->vdev, addr); - desc[i].len = cpu_to_virtio32(_vq->vdev, sg->length); prev = i; - i = virtio16_to_cpu(_vq->vdev, desc[i].next); + /* Note that we trust indirect descriptor + * table since it use stream DMA mapping. + */ + i = virtqueue_add_desc_split(_vq, desc, i, addr, + sg->length, + VRING_DESC_F_NEXT | + VRING_DESC_F_WRITE, + indirect); } } /* Last one doesn't continue. */ desc[prev].flags &= cpu_to_virtio16(_vq->vdev, ~VRING_DESC_F_NEXT); + if (!indirect && vq->use_dma_api) + vq->split.desc_extra[prev & (vq->split.vring.num - 1)].flags = + ~VRING_DESC_F_NEXT; if (indirect) { /* Now that the indirect table is filled in, map it. */ @@ -515,13 +586,11 @@ static inline int virtqueue_add_split(struct virtqueue *_vq, if (vring_mapping_error(vq, addr)) goto unmap_release; - vq->split.vring.desc[head].flags = cpu_to_virtio16(_vq->vdev, - VRING_DESC_F_INDIRECT); - vq->split.vring.desc[head].addr = cpu_to_virtio64(_vq->vdev, - addr); - - vq->split.vring.desc[head].len = cpu_to_virtio32(_vq->vdev, - total_sg * sizeof(struct vring_desc)); + virtqueue_add_desc_split(_vq, vq->split.vring.desc, + head, addr, + total_sg * sizeof(struct vring_desc), + VRING_DESC_F_INDIRECT, + false); } /* We're using some buffers from the free list. */ @@ -529,8 +598,7 @@ static inline int virtqueue_add_split(struct virtqueue *_vq, /* Update free pointer */ if (indirect) - vq->free_head = virtio16_to_cpu(_vq->vdev, - vq->split.vring.desc[head].next); + vq->free_head = vq->split.desc_extra[head].next; else vq->free_head = i; @@ -575,8 +643,11 @@ unmap_release: for (n = 0; n < total_sg; n++) { if (i == err_idx) break; - vring_unmap_one_split(vq, &desc[i]); - i = virtio16_to_cpu(_vq->vdev, desc[i].next); + if (indirect) { + vring_unmap_one_split_indirect(vq, &desc[i]); + i = virtio16_to_cpu(_vq->vdev, desc[i].next); + } else + i = vring_unmap_one_split(vq, i); } if (indirect) @@ -630,14 +701,13 @@ static void detach_buf_split(struct vring_virtqueue *vq, unsigned int head, i = head; while (vq->split.vring.desc[i].flags & nextflag) { - vring_unmap_one_split(vq, &vq->split.vring.desc[i]); - i = virtio16_to_cpu(vq->vq.vdev, vq->split.vring.desc[i].next); + vring_unmap_one_split(vq, i); + i = vq->split.desc_extra[i].next; vq->vq.num_free++; } - vring_unmap_one_split(vq, &vq->split.vring.desc[i]); - vq->split.vring.desc[i].next = cpu_to_virtio16(vq->vq.vdev, - vq->free_head); + vring_unmap_one_split(vq, i); + vq->split.desc_extra[i].next = vq->free_head; vq->free_head = head; /* Plus final descriptor */ @@ -652,15 +722,14 @@ static void detach_buf_split(struct vring_virtqueue *vq, unsigned int head, if (!indir_desc) return; - len = virtio32_to_cpu(vq->vq.vdev, - vq->split.vring.desc[head].len); + len = vq->split.desc_extra[head].len; - BUG_ON(!(vq->split.vring.desc[head].flags & - cpu_to_virtio16(vq->vq.vdev, VRING_DESC_F_INDIRECT))); + BUG_ON(!(vq->split.desc_extra[head].flags & + VRING_DESC_F_INDIRECT)); BUG_ON(len == 0 || len % sizeof(struct vring_desc)); for (j = 0; j < len / sizeof(struct vring_desc); j++) - vring_unmap_one_split(vq, &indir_desc[j]); + vring_unmap_one_split_indirect(vq, &indir_desc[j]); kfree(indir_desc); vq->split.desc_state[head].indir_desc = NULL; @@ -739,7 +808,10 @@ static void virtqueue_disable_cb_split(struct virtqueue *_vq) if (!(vq->split.avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT)) { vq->split.avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT; - if (!vq->event) + if (vq->event) + /* TODO: this is a hack. Figure out a cleaner value to write. */ + vring_used_event(&vq->split.vring) = 0x0; + else vq->split.vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->split.avail_flags_shadow); @@ -912,7 +984,7 @@ static struct virtqueue *vring_create_virtqueue_split( */ static void vring_unmap_state_packed(const struct vring_virtqueue *vq, - struct vring_desc_extra_packed *state) + struct vring_desc_extra *state) { u16 flags; @@ -1061,7 +1133,7 @@ static int virtqueue_add_indirect_packed(struct vring_virtqueue *vq, 1 << VRING_PACKED_DESC_F_USED; } vq->packed.next_avail_idx = n; - vq->free_head = vq->packed.desc_state[id].next; + vq->free_head = vq->packed.desc_extra[id].next; /* Store token and indirect buffer state. */ vq->packed.desc_state[id].num = 1; @@ -1169,7 +1241,7 @@ static inline int virtqueue_add_packed(struct virtqueue *_vq, le16_to_cpu(flags); } prev = curr; - curr = vq->packed.desc_state[curr].next; + curr = vq->packed.desc_extra[curr].next; if ((unlikely(++i >= vq->packed.vring.num))) { i = 0; @@ -1213,13 +1285,16 @@ static inline int virtqueue_add_packed(struct virtqueue *_vq, unmap_release: err_idx = i; i = head; + curr = vq->free_head; vq->packed.avail_used_flags = avail_used_flags; for (n = 0; n < total_sg; n++) { if (i == err_idx) break; - vring_unmap_desc_packed(vq, &desc[i]); + vring_unmap_state_packed(vq, + &vq->packed.desc_extra[curr]); + curr = vq->packed.desc_extra[curr].next; i++; if (i >= vq->packed.vring.num) i = 0; @@ -1290,7 +1365,7 @@ static void detach_buf_packed(struct vring_virtqueue *vq, /* Clear data ptr. */ state->data = NULL; - vq->packed.desc_state[state->last].next = vq->free_head; + vq->packed.desc_extra[state->last].next = vq->free_head; vq->free_head = id; vq->vq.num_free += state->num; @@ -1299,7 +1374,7 @@ static void detach_buf_packed(struct vring_virtqueue *vq, for (i = 0; i < state->num; i++) { vring_unmap_state_packed(vq, &vq->packed.desc_extra[curr]); - curr = vq->packed.desc_state[curr].next; + curr = vq->packed.desc_extra[curr].next; } } @@ -1550,6 +1625,25 @@ static void *virtqueue_detach_unused_buf_packed(struct virtqueue *_vq) return NULL; } +static struct vring_desc_extra *vring_alloc_desc_extra(struct vring_virtqueue *vq, + unsigned int num) +{ + struct vring_desc_extra *desc_extra; + unsigned int i; + + desc_extra = kmalloc_array(num, sizeof(struct vring_desc_extra), + GFP_KERNEL); + if (!desc_extra) + return NULL; + + memset(desc_extra, 0, num * sizeof(struct vring_desc_extra)); + + for (i = 0; i < num - 1; i++) + desc_extra[i].next = i + 1; + + return desc_extra; +} + static struct virtqueue *vring_create_virtqueue_packed( unsigned int index, unsigned int num, @@ -1567,7 +1661,6 @@ static struct virtqueue *vring_create_virtqueue_packed( struct vring_packed_desc_event *driver, *device; dma_addr_t ring_dma_addr, driver_event_dma_addr, device_event_dma_addr; size_t ring_size_in_bytes, event_size_in_bytes; - unsigned int i; ring_size_in_bytes = num * sizeof(struct vring_packed_desc); @@ -1605,6 +1698,7 @@ static struct virtqueue *vring_create_virtqueue_packed( vq->weak_barriers = weak_barriers; vq->broken = false; vq->last_used_idx = 0; + vq->event_triggered = false; vq->num_added = 0; vq->packed_ring = true; vq->use_dma_api = vring_use_dma_api(vdev); @@ -1649,18 +1743,11 @@ static struct virtqueue *vring_create_virtqueue_packed( /* Put everything in free lists. */ vq->free_head = 0; - for (i = 0; i < num-1; i++) - vq->packed.desc_state[i].next = i + 1; - vq->packed.desc_extra = kmalloc_array(num, - sizeof(struct vring_desc_extra_packed), - GFP_KERNEL); + vq->packed.desc_extra = vring_alloc_desc_extra(vq, num); if (!vq->packed.desc_extra) goto err_desc_extra; - memset(vq->packed.desc_extra, 0, - num * sizeof(struct vring_desc_extra_packed)); - /* No callback? Tell other side not to bother us. */ if (!callback) { vq->packed.event_flags_shadow = VRING_PACKED_EVENT_FLAG_DISABLE; @@ -1875,7 +1962,7 @@ bool virtqueue_kick(struct virtqueue *vq) EXPORT_SYMBOL_GPL(virtqueue_kick); /** - * virtqueue_get_buf - get the next used buffer + * virtqueue_get_buf_ctx - get the next used buffer * @_vq: the struct virtqueue we're talking about. * @len: the length written into the buffer * @ctx: extra context for the token @@ -1919,6 +2006,12 @@ void virtqueue_disable_cb(struct virtqueue *_vq) { struct vring_virtqueue *vq = to_vvq(_vq); + /* If device triggered an event already it won't trigger one again: + * no need to disable. + */ + if (vq->event_triggered) + return; + if (vq->packed_ring) virtqueue_disable_cb_packed(_vq); else @@ -1942,6 +2035,9 @@ unsigned virtqueue_enable_cb_prepare(struct virtqueue *_vq) { struct vring_virtqueue *vq = to_vvq(_vq); + if (vq->event_triggered) + vq->event_triggered = false; + return vq->packed_ring ? virtqueue_enable_cb_prepare_packed(_vq) : virtqueue_enable_cb_prepare_split(_vq); } @@ -2005,6 +2101,9 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *_vq) { struct vring_virtqueue *vq = to_vvq(_vq); + if (vq->event_triggered) + vq->event_triggered = false; + return vq->packed_ring ? virtqueue_enable_cb_delayed_packed(_vq) : virtqueue_enable_cb_delayed_split(_vq); } @@ -2044,6 +2143,10 @@ irqreturn_t vring_interrupt(int irq, void *_vq) if (unlikely(vq->broken)) return IRQ_HANDLED; + /* Just a hint for performance: so it's ok that this can be racy! */ + if (vq->event) + vq->event_triggered = true; + pr_debug("virtqueue callback for %p (%p)\n", vq, vq->vq.callback); if (vq->vq.callback) vq->vq.callback(&vq->vq); @@ -2062,7 +2165,6 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index, void (*callback)(struct virtqueue *), const char *name) { - unsigned int i; struct vring_virtqueue *vq; if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED)) @@ -2083,6 +2185,7 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index, vq->weak_barriers = weak_barriers; vq->broken = false; vq->last_used_idx = 0; + vq->event_triggered = false; vq->num_added = 0; vq->use_dma_api = vring_use_dma_api(vdev); #ifdef DEBUG @@ -2114,20 +2217,26 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index, vq->split.desc_state = kmalloc_array(vring.num, sizeof(struct vring_desc_state_split), GFP_KERNEL); - if (!vq->split.desc_state) { - kfree(vq); - return NULL; - } + if (!vq->split.desc_state) + goto err_state; + + vq->split.desc_extra = vring_alloc_desc_extra(vq, vring.num); + if (!vq->split.desc_extra) + goto err_extra; /* Put everything in free lists. */ vq->free_head = 0; - for (i = 0; i < vring.num-1; i++) - vq->split.vring.desc[i].next = cpu_to_virtio16(vdev, i + 1); memset(vq->split.desc_state, 0, vring.num * sizeof(struct vring_desc_state_split)); list_add_tail(&vq->vq.list, &vdev->vqs); return &vq->vq; + +err_extra: + kfree(vq->split.desc_state); +err_state: + kfree(vq); + return NULL; } EXPORT_SYMBOL_GPL(__vring_new_virtqueue); @@ -2208,8 +2317,10 @@ void vring_del_virtqueue(struct virtqueue *_vq) vq->split.queue_dma_addr); } } - if (!vq->packed_ring) + if (!vq->packed_ring) { kfree(vq->split.desc_state); + kfree(vq->split.desc_extra); + } list_del(&_vq->list); kfree(vq); } diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c index e28acf482e0c..e1a141135992 100644 --- a/drivers/virtio/virtio_vdpa.c +++ b/drivers/virtio/virtio_vdpa.c @@ -142,6 +142,8 @@ virtio_vdpa_setup_vq(struct virtio_device *vdev, unsigned int index, struct vdpa_callback cb; struct virtqueue *vq; u64 desc_addr, driver_addr, device_addr; + /* Assume split virtqueue, switch to packed if necessary */ + struct vdpa_vq_state state = {0}; unsigned long flags; u32 align, num; int err; @@ -191,6 +193,19 @@ virtio_vdpa_setup_vq(struct virtio_device *vdev, unsigned int index, goto err_vq; } + /* reset virtqueue state index */ + if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED)) { + struct vdpa_vq_state_packed *s = &state.packed; + + s->last_avail_counter = 1; + s->last_avail_idx = 0; + s->last_used_counter = 1; + s->last_used_idx = 0; + } + err = ops->set_vq_state(vdpa, index, &state); + if (err) + goto err_vq; + ops->set_vq_ready(vdpa, index, 1); vq->priv = info; diff --git a/drivers/visorbus/visorchipset.c b/drivers/visorbus/visorchipset.c index cb1eb7e05f87..5668cad86e37 100644 --- a/drivers/visorbus/visorchipset.c +++ b/drivers/visorbus/visorchipset.c @@ -1561,7 +1561,7 @@ schedule_out: static int visorchipset_init(struct acpi_device *acpi_device) { - int err = -ENODEV; + int err = -ENOMEM; struct visorchannel *controlvm_channel; chipset_dev = kzalloc(sizeof(*chipset_dev), GFP_KERNEL); @@ -1584,8 +1584,10 @@ static int visorchipset_init(struct acpi_device *acpi_device) "controlvm", sizeof(struct visor_controlvm_channel), VISOR_CONTROLVM_CHANNEL_VERSIONID, - VISOR_CHANNEL_SIGNATURE)) + VISOR_CHANNEL_SIGNATURE)) { + err = -ENODEV; goto error_delete_groups; + } /* if booting in a crash kernel */ if (is_kdump_kernel()) INIT_DELAYED_WORK(&chipset_dev->periodic_controlvm_work, diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c index b471779c3e2c..6c962e88501c 100644 --- a/drivers/w1/masters/ds2482.c +++ b/drivers/w1/masters/ds2482.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/** +/* * ds2482.c - provides i2c to w1-master bridge(s) * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> * @@ -19,7 +19,7 @@ #include <linux/w1.h> -/** +/* * Allow the active pullup to be disabled, default is enabled. * * Note from the DS2482 datasheet: @@ -39,7 +39,7 @@ static int extra_config; module_param(extra_config, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(extra_config, "Extra Configuration settings 1=APU,2=PPM,3=SPU,8=1WS"); -/** +/* * The DS2482 registers - there are 3 registers that are addressed by a read * pointer. The read pointer is set by the last command executed. * @@ -62,7 +62,7 @@ MODULE_PARM_DESC(extra_config, "Extra Configuration settings 1=APU,2=PPM,3=SPU,8 #define DS2482_PTR_CODE_CHANNEL 0xD2 /* DS2482-800 only */ #define DS2482_PTR_CODE_CONFIG 0xC3 -/** +/* * Configure Register bit definitions * The top 4 bits always read 0. * To write, the top nibble must be the 1's compl. of the low nibble. @@ -73,7 +73,7 @@ MODULE_PARM_DESC(extra_config, "Extra Configuration settings 1=APU,2=PPM,3=SPU,8 #define DS2482_REG_CFG_APU 0x01 /* active pull-up */ -/** +/* * Write and verify codes for the CHANNEL_SELECT command (DS2482-800 only). * To set the channel, write the value at the index of the channel. * Read and compare against the corresponding value to verify the change. @@ -84,7 +84,7 @@ static const u8 ds2482_chan_rd[8] = { 0xB8, 0xB1, 0xAA, 0xA3, 0x9C, 0x95, 0x8E, 0x87 }; -/** +/* * Status Register bit definitions (read only) */ #define DS2482_REG_STS_DIR 0x80 @@ -124,9 +124,9 @@ struct ds2482_data { /** - * Helper to calculate values for configuration register - * @param conf the raw config value - * @return the value w/ complements that can be written to register + * ds2482_calculate_config - Helper to calculate values for configuration register + * @conf: the raw config value + * Return: the value w/ complements that can be written to register */ static inline u8 ds2482_calculate_config(u8 conf) { @@ -140,10 +140,10 @@ static inline u8 ds2482_calculate_config(u8 conf) /** - * Sets the read pointer. - * @param pdev The ds2482 client pointer - * @param read_ptr see DS2482_PTR_CODE_xxx above - * @return -1 on failure, 0 on success + * ds2482_select_register - Sets the read pointer. + * @pdev: The ds2482 client pointer + * @read_ptr: see DS2482_PTR_CODE_xxx above + * Return: -1 on failure, 0 on success */ static inline int ds2482_select_register(struct ds2482_data *pdev, u8 read_ptr) { @@ -159,12 +159,12 @@ static inline int ds2482_select_register(struct ds2482_data *pdev, u8 read_ptr) } /** - * Sends a command without a parameter - * @param pdev The ds2482 client pointer - * @param cmd DS2482_CMD_RESET, + * ds2482_send_cmd - Sends a command without a parameter + * @pdev: The ds2482 client pointer + * @cmd: DS2482_CMD_RESET, * DS2482_CMD_1WIRE_RESET, * DS2482_CMD_1WIRE_READ_BYTE - * @return -1 on failure, 0 on success + * Return: -1 on failure, 0 on success */ static inline int ds2482_send_cmd(struct ds2482_data *pdev, u8 cmd) { @@ -176,14 +176,14 @@ static inline int ds2482_send_cmd(struct ds2482_data *pdev, u8 cmd) } /** - * Sends a command with a parameter - * @param pdev The ds2482 client pointer - * @param cmd DS2482_CMD_WRITE_CONFIG, + * ds2482_send_cmd_data - Sends a command with a parameter + * @pdev: The ds2482 client pointer + * @cmd: DS2482_CMD_WRITE_CONFIG, * DS2482_CMD_1WIRE_SINGLE_BIT, * DS2482_CMD_1WIRE_WRITE_BYTE, * DS2482_CMD_1WIRE_TRIPLET - * @param byte The data to send - * @return -1 on failure, 0 on success + * @byte: The data to send + * Return: -1 on failure, 0 on success */ static inline int ds2482_send_cmd_data(struct ds2482_data *pdev, u8 cmd, u8 byte) @@ -205,10 +205,10 @@ static inline int ds2482_send_cmd_data(struct ds2482_data *pdev, #define DS2482_WAIT_IDLE_TIMEOUT 100 /** - * Waits until the 1-wire interface is idle (not busy) + * ds2482_wait_1wire_idle - Waits until the 1-wire interface is idle (not busy) * - * @param pdev Pointer to the device structure - * @return the last value read from status or -1 (failure) + * @pdev: Pointer to the device structure + * Return: the last value read from status or -1 (failure) */ static int ds2482_wait_1wire_idle(struct ds2482_data *pdev) { @@ -230,12 +230,12 @@ static int ds2482_wait_1wire_idle(struct ds2482_data *pdev) } /** - * Selects a w1 channel. + * ds2482_set_channel - Selects a w1 channel. * The 1-wire interface must be idle before calling this function. * - * @param pdev The ds2482 client pointer - * @param channel 0-7 - * @return -1 (failure) or 0 (success) + * @pdev: The ds2482 client pointer + * @channel: 0-7 + * Return: -1 (failure) or 0 (success) */ static int ds2482_set_channel(struct ds2482_data *pdev, u8 channel) { @@ -254,11 +254,11 @@ static int ds2482_set_channel(struct ds2482_data *pdev, u8 channel) /** - * Performs the touch-bit function, which writes a 0 or 1 and reads the level. + * ds2482_w1_touch_bit - Performs the touch-bit function, which writes a 0 or 1 and reads the level. * - * @param data The ds2482 channel pointer - * @param bit The level to write: 0 or non-zero - * @return The level read: 0 or 1 + * @data: The ds2482 channel pointer + * @bit: The level to write: 0 or non-zero + * Return: The level read: 0 or 1 */ static u8 ds2482_w1_touch_bit(void *data, u8 bit) { @@ -284,13 +284,13 @@ static u8 ds2482_w1_touch_bit(void *data, u8 bit) } /** - * Performs the triplet function, which reads two bits and writes a bit. + * ds2482_w1_triplet - Performs the triplet function, which reads two bits and writes a bit. * The bit written is determined by the two reads: * 00 => dbit, 01 => 0, 10 => 1 * - * @param data The ds2482 channel pointer - * @param dbit The direction to choose if both branches are valid - * @return b0=read1 b1=read2 b3=bit written + * @data: The ds2482 channel pointer + * @dbit: The direction to choose if both branches are valid + * Return: b0=read1 b1=read2 b3=bit written */ static u8 ds2482_w1_triplet(void *data, u8 dbit) { @@ -317,10 +317,10 @@ static u8 ds2482_w1_triplet(void *data, u8 dbit) } /** - * Performs the write byte function. + * ds2482_w1_write_byte - Performs the write byte function. * - * @param data The ds2482 channel pointer - * @param byte The value to write + * @data: The ds2482 channel pointer + * @byte: The value to write */ static void ds2482_w1_write_byte(void *data, u8 byte) { @@ -341,10 +341,10 @@ static void ds2482_w1_write_byte(void *data, u8 byte) } /** - * Performs the read byte function. + * ds2482_w1_read_byte - Performs the read byte function. * - * @param data The ds2482 channel pointer - * @return The value read + * @data: The ds2482 channel pointer + * Return: The value read */ static u8 ds2482_w1_read_byte(void *data) { @@ -378,10 +378,10 @@ static u8 ds2482_w1_read_byte(void *data) /** - * Sends a reset on the 1-wire interface + * ds2482_w1_reset_bus - Sends a reset on the 1-wire interface * - * @param data The ds2482 channel pointer - * @return 0=Device present, 1=No device present or error + * @data: The ds2482 channel pointer + * Return: 0=Device present, 1=No device present or error */ static u8 ds2482_w1_reset_bus(void *data) { @@ -541,7 +541,7 @@ static int ds2482_remove(struct i2c_client *client) return 0; } -/** +/* * Driver data (common to all clients) */ static const struct i2c_device_id ds2482_id[] = { diff --git a/drivers/w1/slaves/w1_ds2438.c b/drivers/w1/slaves/w1_ds2438.c index 5cfb0ae23e91..ca64f99c8f3d 100644 --- a/drivers/w1/slaves/w1_ds2438.c +++ b/drivers/w1/slaves/w1_ds2438.c @@ -49,6 +49,15 @@ #define DS2438_CURRENT_MSB 0x06 #define DS2438_THRESHOLD 0x07 +/* Page #1 definitions */ +#define DS2438_ETM_0 0x00 +#define DS2438_ETM_1 0x01 +#define DS2438_ETM_2 0x02 +#define DS2438_ETM_3 0x03 +#define DS2438_ICA 0x04 +#define DS2438_OFFSET_LSB 0x05 +#define DS2438_OFFSET_MSB 0x06 + static int w1_ds2438_get_page(struct w1_slave *sl, int pageno, u8 *buf) { unsigned int retries = W1_DS2438_RETRIES; @@ -62,13 +71,13 @@ static int w1_ds2438_get_page(struct w1_slave *sl, int pageno, u8 *buf) if (w1_reset_select_slave(sl)) continue; w1_buf[0] = W1_DS2438_RECALL_MEMORY; - w1_buf[1] = 0x00; + w1_buf[1] = (u8)pageno; w1_write_block(sl->master, w1_buf, 2); if (w1_reset_select_slave(sl)) continue; w1_buf[0] = W1_DS2438_READ_SCRATCH; - w1_buf[1] = 0x00; + w1_buf[1] = (u8)pageno; w1_write_block(sl->master, w1_buf, 2); count = w1_read_block(sl->master, buf, DS2438_PAGE_SIZE + 1); @@ -154,11 +163,11 @@ static int w1_ds2438_change_config_bit(struct w1_slave *sl, u8 mask, u8 value) if ((status & mask) == value) return 0; /* already set as requested */ - else { - /* changing bit */ - status ^= mask; - perform_write = 1; - } + + /* changing bit */ + status ^= mask; + perform_write = 1; + break; } @@ -184,6 +193,34 @@ static int w1_ds2438_change_config_bit(struct w1_slave *sl, u8 mask, u8 value) return -1; } +static int w1_ds2438_change_offset_register(struct w1_slave *sl, u8 *value) +{ + unsigned int retries = W1_DS2438_RETRIES; + u8 w1_buf[9]; + u8 w1_page1_buf[DS2438_PAGE_SIZE + 1 /*for CRC*/]; + + if (w1_ds2438_get_page(sl, 1, w1_page1_buf) == 0) { + memcpy(&w1_buf[2], w1_page1_buf, DS2438_PAGE_SIZE - 1); /* last register reserved */ + w1_buf[7] = value[0]; /* change only offset register */ + w1_buf[8] = value[1]; + while (retries--) { + if (w1_reset_select_slave(sl)) + continue; + w1_buf[0] = W1_DS2438_WRITE_SCRATCH; + w1_buf[1] = 0x01; /* write to page 1 */ + w1_write_block(sl->master, w1_buf, 9); + + if (w1_reset_select_slave(sl)) + continue; + w1_buf[0] = W1_DS2438_COPY_SCRATCH; + w1_buf[1] = 0x01; + w1_write_block(sl->master, w1_buf, 2); + return 0; + } + } + return -1; +} + static int w1_ds2438_get_voltage(struct w1_slave *sl, int adc_input, uint16_t *voltage) { @@ -287,9 +324,9 @@ static ssize_t iad_read(struct file *filp, struct kobject *kobj, if (!buf) return -EINVAL; - if (w1_ds2438_get_current(sl, &voltage) == 0) { + if (w1_ds2438_get_current(sl, &voltage) == 0) ret = snprintf(buf, count, "%i\n", voltage); - } else + else ret = -EIO; return ret; @@ -325,6 +362,55 @@ static ssize_t page0_read(struct file *filp, struct kobject *kobj, return ret; } +static ssize_t page1_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, + loff_t off, size_t count) +{ + struct w1_slave *sl = kobj_to_w1_slave(kobj); + int ret; + u8 w1_buf[DS2438_PAGE_SIZE + 1 /*for CRC*/]; + + if (off != 0) + return 0; + if (!buf) + return -EINVAL; + + mutex_lock(&sl->master->bus_mutex); + + /* Read no more than page1 size */ + if (count > DS2438_PAGE_SIZE) + count = DS2438_PAGE_SIZE; + + if (w1_ds2438_get_page(sl, 1, w1_buf) == 0) { + memcpy(buf, &w1_buf, count); + ret = count; + } else + ret = -EIO; + + mutex_unlock(&sl->master->bus_mutex); + + return ret; +} + +static ssize_t offset_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, + loff_t off, size_t count) +{ + struct w1_slave *sl = kobj_to_w1_slave(kobj); + int ret; + + mutex_lock(&sl->master->bus_mutex); + + if (w1_ds2438_change_offset_register(sl, buf) == 0) + ret = count; + else + ret = -EIO; + + mutex_unlock(&sl->master->bus_mutex); + + return ret; +} + static ssize_t temperature_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) @@ -338,9 +424,9 @@ static ssize_t temperature_read(struct file *filp, struct kobject *kobj, if (!buf) return -EINVAL; - if (w1_ds2438_get_temperature(sl, &temp) == 0) { + if (w1_ds2438_get_temperature(sl, &temp) == 0) ret = snprintf(buf, count, "%i\n", temp); - } else + else ret = -EIO; return ret; @@ -359,9 +445,9 @@ static ssize_t vad_read(struct file *filp, struct kobject *kobj, if (!buf) return -EINVAL; - if (w1_ds2438_get_voltage(sl, DS2438_ADC_INPUT_VAD, &voltage) == 0) { + if (w1_ds2438_get_voltage(sl, DS2438_ADC_INPUT_VAD, &voltage) == 0) ret = snprintf(buf, count, "%u\n", voltage); - } else + else ret = -EIO; return ret; @@ -380,16 +466,18 @@ static ssize_t vdd_read(struct file *filp, struct kobject *kobj, if (!buf) return -EINVAL; - if (w1_ds2438_get_voltage(sl, DS2438_ADC_INPUT_VDD, &voltage) == 0) { + if (w1_ds2438_get_voltage(sl, DS2438_ADC_INPUT_VDD, &voltage) == 0) ret = snprintf(buf, count, "%u\n", voltage); - } else + else ret = -EIO; return ret; } -static BIN_ATTR(iad, S_IRUGO | S_IWUSR | S_IWGRP, iad_read, iad_write, 0); +static BIN_ATTR_RW(iad, 0); static BIN_ATTR_RO(page0, DS2438_PAGE_SIZE); +static BIN_ATTR_RO(page1, DS2438_PAGE_SIZE); +static BIN_ATTR_WO(offset, 2); static BIN_ATTR_RO(temperature, 0/* real length varies */); static BIN_ATTR_RO(vad, 0/* real length varies */); static BIN_ATTR_RO(vdd, 0/* real length varies */); @@ -397,6 +485,8 @@ static BIN_ATTR_RO(vdd, 0/* real length varies */); static struct bin_attribute *w1_ds2438_bin_attrs[] = { &bin_attr_iad, &bin_attr_page0, + &bin_attr_page1, + &bin_attr_offset, &bin_attr_temperature, &bin_attr_vad, &bin_attr_vdd, diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index 9d08a1c9c445..ca70c5f03206 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c @@ -834,7 +834,7 @@ static int check_family_data(struct w1_slave *sl) } /** - * support_bulk_read() - check if slave support bulk read + * bulk_read_support() - check if slave support bulk read * @sl: device to check the ability * * Return: true if bulk read is supported, false if not or error @@ -2056,7 +2056,6 @@ static ssize_t w1_seq_show(struct device *device, { struct w1_slave *sl = dev_to_w1_slave(device); ssize_t c = PAGE_SIZE; - int rv; int i; u8 ack; u64 rn; @@ -2084,7 +2083,7 @@ static ssize_t w1_seq_show(struct device *device, goto error; w1_write_8(sl->master, W1_42_COND_READ); - rv = w1_read_block(sl->master, (u8 *)&rn, 8); + w1_read_block(sl->master, (u8 *)&rn, 8); reg_num = (struct w1_reg_num *) &rn; if (reg_num->family == W1_42_FINISHED_BYTE) break; diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 355100dad60a..546dfc1e2349 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -22,9 +22,9 @@ menuconfig WATCHDOG The watchdog is usually used together with the watchdog daemon which is available from - <ftp://ibiblio.org/pub/Linux/system/daemons/watchdog/>. This daemon can - also monitor NFS connections and can reboot the machine when the process - table is full. + <https://ibiblio.org/pub/Linux/system/daemons/watchdog/>. This daemon + can also monitor NFS connections and can reboot the machine when the + process table is full. If unsure, say N. @@ -73,6 +73,14 @@ config WATCHDOG_SYSFS Say Y here if you want to enable watchdog device status read through sysfs attributes. +config WATCHDOG_HRTIMER_PRETIMEOUT + bool "Enable watchdog hrtimer-based pretimeouts" + help + Enable this if you want to use a hrtimer timer based pretimeout for + watchdogs that do not natively support pretimeout support. Be aware + that because this pretimeout functionality uses hrtimers, it may not + be able to fire before the actual watchdog fires in some situations. + comment "Watchdog Pretimeout Governors" config WATCHDOG_PRETIMEOUT_GOV @@ -302,7 +310,7 @@ config XILINX_WATCHDOG depends on HAS_IOMEM select WATCHDOG_CORE help - Watchdog driver for the xps_timebase_wdt ip core. + Watchdog driver for the xps_timebase_wdt IP core. To compile this driver as a module, choose M here: the module will be called of_xilinx_wdt. @@ -404,8 +412,8 @@ config ASM9260_WATCHDOG select WATCHDOG_CORE select RESET_CONTROLLER help - Watchdog timer embedded into Alphascale asm9260 chips. This will reboot your - system when the timeout is reached. + Watchdog timer embedded into Alphascale asm9260 chips. This will + reboot your system when the timeout is reached. config AT91RM9200_WATCHDOG tristate "AT91RM9200 watchdog" @@ -548,8 +556,9 @@ config OMAP_WATCHDOG depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS || COMPILE_TEST select WATCHDOG_CORE help - Support for TI OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog. Say 'Y' - here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog timer. + Support for TI OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog. + Say 'Y' here to enable the + OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog timer. config PNX4008_WATCHDOG tristate "LPC32XX Watchdog" @@ -980,6 +989,18 @@ config VISCONTI_WATCHDOG Say Y here to include support for the watchdog timer in Toshiba Visconti SoCs. +config MSC313E_WATCHDOG + tristate "MStar MSC313e watchdog" + depends on ARCH_MSTARV7 || COMPILE_TEST + select WATCHDOG_CORE + help + Say Y here to include support for the Watchdog timer embedded + into MStar MSC313e chips. This will reboot your system when the + timeout is reached. + + To compile this driver as a module, choose M here: the + module will be called msc313e_wdt. + # X86 (i386 + ia64 + x86_64) Architecture config ACQUIRE_WDT @@ -1096,13 +1117,16 @@ config SBC_FITPC2_WATCHDOG This is the driver for the built-in watchdog timer on the fit-PC2, fit-PC2i, CM-iAM single-board computers made by Compulab. - It`s possible to enable watchdog timer either from BIOS (F2) or from booted Linux. - When "Watchdog Timer Value" enabled one can set 31-255 s operational range. + It's possible to enable the watchdog timer either from BIOS (F2) or + from booted Linux. + When the "Watchdog Timer Value" is enabled one can set 31-255 seconds + operational range. - Entering BIOS setup temporary disables watchdog operation regardless to current state, - so system will not be restarted while user in BIOS setup. + Entering BIOS setup temporarily disables watchdog operation regardless + of current state, so system will not be restarted while user is in + BIOS setup. - Once watchdog was enabled the system will be restarted every + Once the watchdog is enabled the system will be restarted every "Watchdog Timer Value" period, so to prevent it user can restart or disable the watchdog. @@ -1124,11 +1148,12 @@ config IB700_WDT depends on X86 help This is the driver for the hardware watchdog on the IB700 Single - Board Computer produced by TMC Technology (www.tmc-uk.com). This watchdog - simply watches your kernel to make sure it doesn't freeze, and if - it does, it reboots your computer after a certain amount of time. + Board Computer produced by TMC Technology (www.tmc-uk.com). This + watchdog simply watches your kernel to make sure it doesn't freeze, + and if it does, it reboots your computer after a certain amount of time. - This driver is like the WDT501 driver but for slightly different hardware. + This driver is like the WDT501 driver but for slightly different + hardware. To compile this driver as a module, choose M here: the module will be called ib700wdt. @@ -1807,10 +1832,10 @@ config PIC32_DMT select WATCHDOG_CORE depends on MACH_PIC32 || (MIPS && COMPILE_TEST) help - Watchdog driver for PIC32 instruction fetch counting timer. This specific - timer is typically be used in misson critical and safety critical - applications, where any single failure of the software functionality - and sequencing must be detected. + Watchdog driver for PIC32 instruction fetch counting timer. This + specific timer is typically be used in mission critical and safety + critical applications, where any single failure of the software + functionality and sequencing must be detected. To compile this driver as a loadable module, choose M here. The module will be called pic32-dmt. @@ -1844,10 +1869,6 @@ config 8xxx_WDT For BookE processors (MPC85xx) use the BOOKE_WDT driver instead. -config MV64X60_WDT - tristate "MV64X60 (Marvell Discovery) Watchdog Timer" - depends on MV64X60 || COMPILE_TEST - config PIKA_WDT tristate "PIKA FPGA Watchdog" depends on WARP || (PPC64 && COMPILE_TEST) @@ -2013,8 +2034,8 @@ config PCWATCHDOG This card simply watches your kernel to make sure it doesn't freeze, and if it does, it reboots your computer after a certain amount of time. This driver is like the WDT501 driver but for different - hardware. Please read <file:Documentation/watchdog/pcwd-watchdog.rst>. The PC - watchdog cards can be ordered from <http://www.berkprod.com/>. + hardware. Please read <file:Documentation/watchdog/pcwd-watchdog.rst>. + The PC watchdog cards can be ordered from <http://www.berkprod.com/>. To compile this driver as a module, choose M here: the module will be called pcwd. @@ -2115,7 +2136,7 @@ config KEEMBAY_WATCHDOG This option enable support for an In-secure watchdog timer driver for Intel Keem Bay SoC. This WDT has a 32 bit timer and decrements in every count unit. An interrupt will be triggered, when the count crosses - the thershold configured in the register. + the threshold configured in the register. To compile this driver as a module, choose M here: the module will be called keembay_wdt. diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index a7eade8b4d45..abaf2ebd814e 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_WATCHDOG_CORE) += watchdog.o watchdog-objs += watchdog_core.o watchdog_dev.o watchdog-$(CONFIG_WATCHDOG_PRETIMEOUT_GOV) += watchdog_pretimeout.o +watchdog-$(CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT) += watchdog_hrtimer_pretimeout.o obj-$(CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP) += pretimeout_noop.o obj-$(CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC) += pretimeout_panic.o @@ -92,6 +93,7 @@ obj-$(CONFIG_SPRD_WATCHDOG) += sprd_wdt.o obj-$(CONFIG_PM8916_WATCHDOG) += pm8916_wdt.o obj-$(CONFIG_ARM_SMC_WATCHDOG) += arm_smc_wdt.o obj-$(CONFIG_VISCONTI_WATCHDOG) += visconti_wdt.o +obj-$(CONFIG_MSC313E_WATCHDOG) += msc313e_wdt.o # X86 (i386 + ia64 + x86_64) Architecture obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o @@ -175,7 +177,6 @@ obj-$(CONFIG_PIC32_DMT) += pic32-dmt.o # POWERPC Architecture obj-$(CONFIG_GEF_WDT) += gef_wdt.o obj-$(CONFIG_8xxx_WDT) += mpc8xxx_wdt.o -obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o obj-$(CONFIG_PIKA_WDT) += pika_wdt.o obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o obj-$(CONFIG_MEN_A21_WDT) += mena21_wdt.o diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c index 7e00960651fa..436571b6fc79 100644 --- a/drivers/watchdog/aspeed_wdt.c +++ b/drivers/watchdog/aspeed_wdt.c @@ -147,7 +147,7 @@ static int aspeed_wdt_set_timeout(struct watchdog_device *wdd, wdd->timeout = timeout; - actual = min(timeout, wdd->max_hw_heartbeat_ms * 1000); + actual = min(timeout, wdd->max_hw_heartbeat_ms / 1000); writel(actual * WDT_RATE_1MHZ, wdt->base + WDT_RELOAD_VALUE); writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART); @@ -175,8 +175,8 @@ static ssize_t access_cs0_show(struct device *dev, struct aspeed_wdt *wdt = dev_get_drvdata(dev); u32 status = readl(wdt->base + WDT_TIMEOUT_STATUS); - return sprintf(buf, "%u\n", - !(status & WDT_TIMEOUT_STATUS_BOOT_SECONDARY)); + return sysfs_emit(buf, "%u\n", + !(status & WDT_TIMEOUT_STATUS_BOOT_SECONDARY)); } static ssize_t access_cs0_store(struct device *dev, diff --git a/drivers/watchdog/bcm7038_wdt.c b/drivers/watchdog/bcm7038_wdt.c index 979caa18d3c8..acaaa0005d5b 100644 --- a/drivers/watchdog/bcm7038_wdt.c +++ b/drivers/watchdog/bcm7038_wdt.c @@ -34,6 +34,25 @@ struct bcm7038_watchdog { static bool nowayout = WATCHDOG_NOWAYOUT; +static inline void bcm7038_wdt_write(u32 value, void __iomem *addr) +{ + /* MIPS chips strapped for BE will automagically configure the + * peripheral registers for CPU-native byte order. + */ + if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) + __raw_writel(value, addr); + else + writel_relaxed(value, addr); +} + +static inline u32 bcm7038_wdt_read(void __iomem *addr) +{ + if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) + return __raw_readl(addr); + else + return readl_relaxed(addr); +} + static void bcm7038_wdt_set_timeout_reg(struct watchdog_device *wdog) { struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog); @@ -41,15 +60,15 @@ static void bcm7038_wdt_set_timeout_reg(struct watchdog_device *wdog) timeout = wdt->rate * wdog->timeout; - writel(timeout, wdt->base + WDT_TIMEOUT_REG); + bcm7038_wdt_write(timeout, wdt->base + WDT_TIMEOUT_REG); } static int bcm7038_wdt_ping(struct watchdog_device *wdog) { struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog); - writel(WDT_START_1, wdt->base + WDT_CMD_REG); - writel(WDT_START_2, wdt->base + WDT_CMD_REG); + bcm7038_wdt_write(WDT_START_1, wdt->base + WDT_CMD_REG); + bcm7038_wdt_write(WDT_START_2, wdt->base + WDT_CMD_REG); return 0; } @@ -66,8 +85,8 @@ static int bcm7038_wdt_stop(struct watchdog_device *wdog) { struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog); - writel(WDT_STOP_1, wdt->base + WDT_CMD_REG); - writel(WDT_STOP_2, wdt->base + WDT_CMD_REG); + bcm7038_wdt_write(WDT_STOP_1, wdt->base + WDT_CMD_REG); + bcm7038_wdt_write(WDT_STOP_2, wdt->base + WDT_CMD_REG); return 0; } @@ -88,7 +107,7 @@ static unsigned int bcm7038_wdt_get_timeleft(struct watchdog_device *wdog) struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog); u32 time_left; - time_left = readl(wdt->base + WDT_CMD_REG); + time_left = bcm7038_wdt_read(wdt->base + WDT_CMD_REG); return time_left / wdt->rate; } diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c index 7817fb976f9c..5e4dc1a0f2c6 100644 --- a/drivers/watchdog/booke_wdt.c +++ b/drivers/watchdog/booke_wdt.c @@ -148,7 +148,7 @@ static void __booke_wdt_enable(void *data) } /** - * booke_wdt_disable - disable the watchdog on the given CPU + * __booke_wdt_disable - disable the watchdog on the given CPU * * This function is called on each CPU. It disables the watchdog on that CPU. * diff --git a/drivers/watchdog/diag288_wdt.c b/drivers/watchdog/diag288_wdt.c index aafc8d98bf9f..4cb10877017c 100644 --- a/drivers/watchdog/diag288_wdt.c +++ b/drivers/watchdog/diag288_wdt.c @@ -118,8 +118,6 @@ static int wdt_start(struct watchdog_device *dev) if (test_and_set_bit(DIAG_WDOG_BUSY, &wdt_status)) return -EBUSY; - ret = -ENODEV; - if (MACHINE_IS_VM) { ebc_cmd = kmalloc(MAX_CMDLEN, GFP_KERNEL); if (!ebc_cmd) { @@ -167,8 +165,6 @@ static int wdt_ping(struct watchdog_device *dev) int ret; unsigned int func; - ret = -ENODEV; - if (MACHINE_IS_VM) { ebc_cmd = kmalloc(MAX_CMDLEN, GFP_KERNEL); if (!ebc_cmd) diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c index 32d0e1781e63..cd578843277e 100644 --- a/drivers/watchdog/dw_wdt.c +++ b/drivers/watchdog/dw_wdt.c @@ -13,22 +13,21 @@ */ #include <linux/bitops.h> -#include <linux/limits.h> -#include <linux/kernel.h> #include <linux/clk.h> +#include <linux/debugfs.h> #include <linux/delay.h> #include <linux/err.h> +#include <linux/interrupt.h> #include <linux/io.h> #include <linux/kernel.h> +#include <linux/limits.h> #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/interrupt.h> #include <linux/of.h> -#include <linux/pm.h> #include <linux/platform_device.h> +#include <linux/pm.h> #include <linux/reset.h> #include <linux/watchdog.h> -#include <linux/debugfs.h> #define WDOG_CONTROL_REG_OFFSET 0x00 #define WDOG_CONTROL_REG_WDT_EN_MASK 0x01 diff --git a/drivers/watchdog/eurotechwdt.c b/drivers/watchdog/eurotechwdt.c index 2418ebb707bd..ce682942662c 100644 --- a/drivers/watchdog/eurotechwdt.c +++ b/drivers/watchdog/eurotechwdt.c @@ -392,7 +392,7 @@ static struct notifier_block eurwdt_notifier = { }; /** - * cleanup_module: + * eurwdt_exit: * * Unload the watchdog. You cannot do this with any file handles open. * If your watchdog is set to continue ticking on close and you unload diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 22ddba3802ef..a5006a58e0db 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -45,6 +45,7 @@ static unsigned long __iomem *hpwdt_timer_con; static const struct pci_device_id hpwdt_devices[] = { { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB203) }, /* iLO2 */ { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3306) }, /* iLO3 */ + { PCI_DEVICE(PCI_VENDOR_ID_HP_3PAR, 0x0389) }, /* PCtrl */ {0}, /* terminate list */ }; MODULE_DEVICE_TABLE(pci, hpwdt_devices); diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index bf31d7b67a69..b3f604669e2c 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -71,6 +71,8 @@ #define TCOBASE(p) ((p)->tco_res->start) /* SMI Control and Enable Register */ #define SMI_EN(p) ((p)->smi_res->start) +#define TCO_EN (1 << 13) +#define GBL_SMI_EN (1 << 0) #define TCO_RLD(p) (TCOBASE(p) + 0x00) /* TCO Timer Reload/Curr. Value */ #define TCOv1_TMR(p) (TCOBASE(p) + 0x01) /* TCOv1 Timer Initial Value*/ @@ -355,8 +357,12 @@ static int iTCO_wdt_set_timeout(struct watchdog_device *wd_dev, unsigned int t) tmrval = seconds_to_ticks(p, t); - /* For TCO v1 the timer counts down twice before rebooting */ - if (p->iTCO_version == 1) + /* + * If TCO SMIs are off, the timer counts down twice before rebooting. + * Otherwise, the BIOS generally reboots when the SMI triggers. + */ + if (p->smi_res && + (SMI_EN(p) & (TCO_EN | GBL_SMI_EN)) != (TCO_EN | GBL_SMI_EN)) tmrval /= 2; /* from the specs: */ @@ -479,13 +485,13 @@ static int iTCO_wdt_probe(struct platform_device *pdev) if (!devm_request_region(dev, p->smi_res->start, resource_size(p->smi_res), pdev->name)) { - pr_err("I/O address 0x%04llx already in use, device disabled\n", + dev_err(dev, "I/O address 0x%04llx already in use, device disabled\n", (u64)SMI_EN(p)); return -EBUSY; } } else if (iTCO_vendorsupport || turn_SMI_watchdog_clear_off >= p->iTCO_version) { - pr_err("SMI I/O resource is missing\n"); + dev_err(dev, "SMI I/O resource is missing\n"); return -ENODEV; } @@ -521,7 +527,7 @@ static int iTCO_wdt_probe(struct platform_device *pdev) * Disables TCO logic generating an SMI# */ val32 = inl(SMI_EN(p)); - val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */ + val32 &= ~TCO_EN; /* Turn off SMI clearing watchdog */ outl(val32, SMI_EN(p)); } diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c index b84f80f7d342..cc86018c5eb5 100644 --- a/drivers/watchdog/imx2_wdt.c +++ b/drivers/watchdog/imx2_wdt.c @@ -65,6 +65,7 @@ struct imx2_wdt_device { struct regmap *regmap; struct watchdog_device wdog; bool ext_reset; + bool clk_is_on; }; static bool nowayout = WATCHDOG_NOWAYOUT; @@ -160,6 +161,9 @@ static int imx2_wdt_ping(struct watchdog_device *wdog) { struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); + if (!wdev->clk_is_on) + return 0; + regmap_write(wdev->regmap, IMX2_WDT_WSR, IMX2_WDT_SEQ1); regmap_write(wdev->regmap, IMX2_WDT_WSR, IMX2_WDT_SEQ2); return 0; @@ -301,6 +305,8 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) if (ret) return ret; + wdev->clk_is_on = true; + regmap_read(wdev->regmap, IMX2_WDT_WRSR, &val); wdog->bootstatus = val & IMX2_WDT_WRSR_TOUT ? WDIOF_CARDRESET : 0; @@ -361,6 +367,8 @@ static int __maybe_unused imx2_wdt_suspend(struct device *dev) clk_disable_unprepare(wdev->clk); + wdev->clk_is_on = false; + return 0; } @@ -375,6 +383,8 @@ static int __maybe_unused imx2_wdt_resume(struct device *dev) if (ret) return ret; + wdev->clk_is_on = true; + if (watchdog_active(wdog) && !imx2_wdt_is_running(wdev)) { /* * If the watchdog is still active and resumes diff --git a/drivers/watchdog/imx_sc_wdt.c b/drivers/watchdog/imx_sc_wdt.c index e9ee22a7cb45..8ac021748d16 100644 --- a/drivers/watchdog/imx_sc_wdt.c +++ b/drivers/watchdog/imx_sc_wdt.c @@ -183,16 +183,12 @@ static int imx_sc_wdt_probe(struct platform_device *pdev) watchdog_stop_on_reboot(wdog); watchdog_stop_on_unregister(wdog); - ret = devm_watchdog_register_device(dev, wdog); - if (ret) - return ret; - ret = imx_scu_irq_group_enable(SC_IRQ_GROUP_WDOG, SC_IRQ_WDOG, true); if (ret) { dev_warn(dev, "Enable irq failed, pretimeout NOT supported\n"); - return 0; + goto register_device; } imx_sc_wdd->wdt_notifier.notifier_call = imx_sc_wdt_notify; @@ -203,7 +199,7 @@ static int imx_sc_wdt_probe(struct platform_device *pdev) false); dev_warn(dev, "Register irq notifier failed, pretimeout NOT supported\n"); - return 0; + goto register_device; } ret = devm_add_action_or_reset(dev, imx_sc_wdt_action, @@ -213,7 +209,8 @@ static int imx_sc_wdt_probe(struct platform_device *pdev) else dev_warn(dev, "Add action failed, pretimeout NOT supported\n"); - return 0; +register_device: + return devm_watchdog_register_device(dev, wdog); } static int __maybe_unused imx_sc_wdt_suspend(struct device *dev) diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c index 2b4831842162..bb1122909396 100644 --- a/drivers/watchdog/it87_wdt.c +++ b/drivers/watchdog/it87_wdt.c @@ -152,14 +152,6 @@ static inline int superio_inw(int reg) return val; } -static inline void superio_outw(int val, int reg) -{ - outb(reg++, REG); - outb(val >> 8, VAL); - outb(reg, REG); - outb(val, VAL); -} - /* Internal function, should be called after superio_select(GPIO) */ static void _wdt_update_timeout(unsigned int t) { diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c index bdf9564efa29..395bde79e292 100644 --- a/drivers/watchdog/jz4740_wdt.c +++ b/drivers/watchdog/jz4740_wdt.c @@ -176,9 +176,9 @@ static int jz4740_wdt_probe(struct platform_device *pdev) watchdog_set_drvdata(jz4740_wdt, drvdata); drvdata->map = device_node_to_regmap(dev->parent->of_node); - if (!drvdata->map) { + if (IS_ERR(drvdata->map)) { dev_err(dev, "regmap not found\n"); - return -EINVAL; + return PTR_ERR(drvdata->map); } return devm_watchdog_register_device(dev, &drvdata->wdt); diff --git a/drivers/watchdog/keembay_wdt.c b/drivers/watchdog/keembay_wdt.c index 547d3fea33ff..2a39114dbc64 100644 --- a/drivers/watchdog/keembay_wdt.c +++ b/drivers/watchdog/keembay_wdt.c @@ -23,12 +23,19 @@ #define TIM_WDOG_EN 0x8 #define TIM_SAFE 0xc -#define WDT_ISR_MASK GENMASK(9, 8) -#define WDT_ISR_CLEAR 0x8200ff18 +#define WDT_TH_INT_MASK BIT(8) +#define WDT_TO_INT_MASK BIT(9) +#define WDT_INT_CLEAR_SMC 0x8200ff18 + #define WDT_UNLOCK 0xf1d0dead +#define WDT_DISABLE 0x0 +#define WDT_ENABLE 0x1 + #define WDT_LOAD_MAX U32_MAX #define WDT_LOAD_MIN 1 + #define WDT_TIMEOUT 5 +#define WDT_PRETIMEOUT 4 static unsigned int timeout = WDT_TIMEOUT; module_param(timeout, int, 0); @@ -82,8 +89,7 @@ static int keembay_wdt_start(struct watchdog_device *wdog) { struct keembay_wdt *wdt = watchdog_get_drvdata(wdog); - keembay_wdt_set_timeout_reg(wdog); - keembay_wdt_writel(wdt, TIM_WDOG_EN, 1); + keembay_wdt_writel(wdt, TIM_WDOG_EN, WDT_ENABLE); return 0; } @@ -92,7 +98,7 @@ static int keembay_wdt_stop(struct watchdog_device *wdog) { struct keembay_wdt *wdt = watchdog_get_drvdata(wdog); - keembay_wdt_writel(wdt, TIM_WDOG_EN, 0); + keembay_wdt_writel(wdt, TIM_WDOG_EN, WDT_DISABLE); return 0; } @@ -108,6 +114,7 @@ static int keembay_wdt_set_timeout(struct watchdog_device *wdog, u32 t) { wdog->timeout = t; keembay_wdt_set_timeout_reg(wdog); + keembay_wdt_set_pretimeout_reg(wdog); return 0; } @@ -139,9 +146,8 @@ static irqreturn_t keembay_wdt_to_isr(int irq, void *dev_id) struct keembay_wdt *wdt = dev_id; struct arm_smccc_res res; - keembay_wdt_writel(wdt, TIM_WATCHDOG, 1); - arm_smccc_smc(WDT_ISR_CLEAR, WDT_ISR_MASK, 0, 0, 0, 0, 0, 0, &res); - dev_crit(wdt->wdd.parent, "Intel Keem Bay non-sec wdt timeout.\n"); + arm_smccc_smc(WDT_INT_CLEAR_SMC, WDT_TO_INT_MASK, 0, 0, 0, 0, 0, 0, &res); + dev_crit(wdt->wdd.parent, "Intel Keem Bay non-secure wdt timeout.\n"); emergency_restart(); return IRQ_HANDLED; @@ -152,8 +158,10 @@ static irqreturn_t keembay_wdt_th_isr(int irq, void *dev_id) struct keembay_wdt *wdt = dev_id; struct arm_smccc_res res; - arm_smccc_smc(WDT_ISR_CLEAR, WDT_ISR_MASK, 0, 0, 0, 0, 0, 0, &res); - dev_crit(wdt->wdd.parent, "Intel Keem Bay non-sec wdt pre-timeout.\n"); + keembay_wdt_set_pretimeout(&wdt->wdd, 0x0); + + arm_smccc_smc(WDT_INT_CLEAR_SMC, WDT_TH_INT_MASK, 0, 0, 0, 0, 0, 0, &res); + dev_crit(wdt->wdd.parent, "Intel Keem Bay non-secure wdt pre-timeout.\n"); watchdog_notify_pretimeout(&wdt->wdd); return IRQ_HANDLED; @@ -224,11 +232,13 @@ static int keembay_wdt_probe(struct platform_device *pdev) wdt->wdd.min_timeout = WDT_LOAD_MIN; wdt->wdd.max_timeout = WDT_LOAD_MAX / wdt->rate; wdt->wdd.timeout = WDT_TIMEOUT; + wdt->wdd.pretimeout = WDT_PRETIMEOUT; watchdog_set_drvdata(&wdt->wdd, wdt); watchdog_set_nowayout(&wdt->wdd, nowayout); watchdog_init_timeout(&wdt->wdd, timeout, dev); keembay_wdt_set_timeout(&wdt->wdd, wdt->wdd.timeout); + keembay_wdt_set_pretimeout(&wdt->wdd, wdt->wdd.pretimeout); ret = devm_watchdog_register_device(dev, &wdt->wdd); if (ret) @@ -271,8 +281,8 @@ static const struct of_device_id keembay_wdt_match[] = { MODULE_DEVICE_TABLE(of, keembay_wdt_match); static struct platform_driver keembay_wdt_driver = { - .probe = keembay_wdt_probe, - .driver = { + .probe = keembay_wdt_probe, + .driver = { .name = "keembay_wdt", .of_match_table = keembay_wdt_match, .pm = &keembay_wdt_pm_ops, diff --git a/drivers/watchdog/lpc18xx_wdt.c b/drivers/watchdog/lpc18xx_wdt.c index 78cf11c94941..60b6d74f267d 100644 --- a/drivers/watchdog/lpc18xx_wdt.c +++ b/drivers/watchdog/lpc18xx_wdt.c @@ -292,7 +292,7 @@ static int lpc18xx_wdt_remove(struct platform_device *pdev) struct lpc18xx_wdt_dev *lpc18xx_wdt = platform_get_drvdata(pdev); dev_warn(&pdev->dev, "I quit now, hardware will probably reboot!\n"); - del_timer(&lpc18xx_wdt->timer); + del_timer_sync(&lpc18xx_wdt->timer); return 0; } diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c index e023d7d90d66..c7a7235e6224 100644 --- a/drivers/watchdog/mei_wdt.c +++ b/drivers/watchdog/mei_wdt.c @@ -105,7 +105,7 @@ struct mei_wdt { #endif /* CONFIG_DEBUG_FS */ }; -/* +/** * struct mei_mc_hdr - Management Control Command Header * * @command: Management Control (0x2) @@ -121,7 +121,7 @@ struct mei_mc_hdr { }; /** - * struct mei_wdt_start_request watchdog start/ping + * struct mei_wdt_start_request - watchdog start/ping * * @hdr: Management Control Command Header * @timeout: timeout value @@ -134,7 +134,7 @@ struct mei_wdt_start_request { } __packed; /** - * struct mei_wdt_start_response watchdog start/ping response + * struct mei_wdt_start_response - watchdog start/ping response * * @hdr: Management Control Command Header * @status: operation status @@ -474,7 +474,7 @@ out: complete(&wdt->response); } -/* +/** * mei_wdt_notif - callback for event notification * * @cldev: bus device diff --git a/drivers/watchdog/meson_wdt.c b/drivers/watchdog/meson_wdt.c index 459f3ae02c91..539feaa1f904 100644 --- a/drivers/watchdog/meson_wdt.c +++ b/drivers/watchdog/meson_wdt.c @@ -162,7 +162,6 @@ static int meson_wdt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct meson_wdt_dev *meson_wdt; - const struct of_device_id *of_id; int err; meson_wdt = devm_kzalloc(dev, sizeof(*meson_wdt), GFP_KERNEL); @@ -173,12 +172,7 @@ static int meson_wdt_probe(struct platform_device *pdev) if (IS_ERR(meson_wdt->wdt_base)) return PTR_ERR(meson_wdt->wdt_base); - of_id = of_match_device(meson_wdt_dt_ids, dev); - if (!of_id) { - dev_err(dev, "Unable to initialize WDT data\n"); - return -ENODEV; - } - meson_wdt->data = of_id->data; + meson_wdt->data = device_get_match_data(dev); meson_wdt->wdt_dev.parent = dev; meson_wdt->wdt_dev.info = &meson_wdt_info; diff --git a/drivers/watchdog/msc313e_wdt.c b/drivers/watchdog/msc313e_wdt.c new file mode 100644 index 000000000000..0d497aa0fb7d --- /dev/null +++ b/drivers/watchdog/msc313e_wdt.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MStar WDT driver + * + * Copyright (C) 2019 - 2021 Daniel Palmer + * Copyright (C) 2021 Romain Perier + * + */ + +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/watchdog.h> + +#define REG_WDT_CLR 0x0 +#define REG_WDT_MAX_PRD_L 0x10 +#define REG_WDT_MAX_PRD_H 0x14 + +#define MSC313E_WDT_MIN_TIMEOUT 1 +#define MSC313E_WDT_DEFAULT_TIMEOUT 30 + +static unsigned int timeout; + +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds"); + +struct msc313e_wdt_priv { + void __iomem *base; + struct watchdog_device wdev; + struct clk *clk; +}; + +static int msc313e_wdt_start(struct watchdog_device *wdev) +{ + struct msc313e_wdt_priv *priv = watchdog_get_drvdata(wdev); + u32 timeout; + int err; + + err = clk_prepare_enable(priv->clk); + if (err) + return err; + + timeout = wdev->timeout * clk_get_rate(priv->clk); + writew(timeout & 0xffff, priv->base + REG_WDT_MAX_PRD_L); + writew((timeout >> 16) & 0xffff, priv->base + REG_WDT_MAX_PRD_H); + writew(1, priv->base + REG_WDT_CLR); + return 0; +} + +static int msc313e_wdt_ping(struct watchdog_device *wdev) +{ + struct msc313e_wdt_priv *priv = watchdog_get_drvdata(wdev); + + writew(1, priv->base + REG_WDT_CLR); + return 0; +} + +static int msc313e_wdt_stop(struct watchdog_device *wdev) +{ + struct msc313e_wdt_priv *priv = watchdog_get_drvdata(wdev); + + writew(0, priv->base + REG_WDT_MAX_PRD_L); + writew(0, priv->base + REG_WDT_MAX_PRD_H); + writew(0, priv->base + REG_WDT_CLR); + clk_disable_unprepare(priv->clk); + return 0; +} + +static int msc313e_wdt_settimeout(struct watchdog_device *wdev, unsigned int new_time) +{ + wdev->timeout = new_time; + + return msc313e_wdt_start(wdev); +} + +static const struct watchdog_info msc313e_wdt_ident = { + .identity = "MSC313e watchdog", + .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, +}; + +static const struct watchdog_ops msc313e_wdt_ops = { + .owner = THIS_MODULE, + .start = msc313e_wdt_start, + .stop = msc313e_wdt_stop, + .ping = msc313e_wdt_ping, + .set_timeout = msc313e_wdt_settimeout, +}; + +static const struct of_device_id msc313e_wdt_of_match[] = { + { .compatible = "mstar,msc313e-wdt", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, msc313e_wdt_of_match); + +static int msc313e_wdt_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct msc313e_wdt_priv *priv; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) { + dev_err(dev, "No input clock\n"); + return PTR_ERR(priv->clk); + } + + priv->wdev.info = &msc313e_wdt_ident, + priv->wdev.ops = &msc313e_wdt_ops, + priv->wdev.parent = dev; + priv->wdev.min_timeout = MSC313E_WDT_MIN_TIMEOUT; + priv->wdev.max_timeout = U32_MAX / clk_get_rate(priv->clk); + priv->wdev.timeout = MSC313E_WDT_DEFAULT_TIMEOUT; + + watchdog_set_drvdata(&priv->wdev, priv); + + watchdog_init_timeout(&priv->wdev, timeout, dev); + watchdog_stop_on_reboot(&priv->wdev); + watchdog_stop_on_unregister(&priv->wdev); + + return devm_watchdog_register_device(dev, &priv->wdev); +} + +static int __maybe_unused msc313e_wdt_suspend(struct device *dev) +{ + struct msc313e_wdt_priv *priv = dev_get_drvdata(dev); + + if (watchdog_active(&priv->wdev)) + msc313e_wdt_stop(&priv->wdev); + + return 0; +} + +static int __maybe_unused msc313e_wdt_resume(struct device *dev) +{ + struct msc313e_wdt_priv *priv = dev_get_drvdata(dev); + + if (watchdog_active(&priv->wdev)) + msc313e_wdt_start(&priv->wdev); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(msc313e_wdt_pm_ops, msc313e_wdt_suspend, msc313e_wdt_resume); + +static struct platform_driver msc313e_wdt_driver = { + .driver = { + .name = "msc313e-wdt", + .of_match_table = msc313e_wdt_of_match, + .pm = &msc313e_wdt_pm_ops, + }, + .probe = msc313e_wdt_probe, +}; +module_platform_driver(msc313e_wdt_driver); + +MODULE_AUTHOR("Daniel Palmer <daniel@thingy.jp>"); +MODULE_DESCRIPTION("Watchdog driver for MStar MSC313e"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c index 97ca993bd009..16b6aff324a7 100644 --- a/drivers/watchdog/mtk_wdt.c +++ b/drivers/watchdog/mtk_wdt.c @@ -25,9 +25,10 @@ #include <linux/reset-controller.h> #include <linux/types.h> #include <linux/watchdog.h> +#include <linux/interrupt.h> #define WDT_MAX_TIMEOUT 31 -#define WDT_MIN_TIMEOUT 1 +#define WDT_MIN_TIMEOUT 2 #define WDT_LENGTH_TIMEOUT(n) ((n) << 5) #define WDT_LENGTH 0x04 @@ -187,12 +188,19 @@ static int mtk_wdt_set_timeout(struct watchdog_device *wdt_dev, u32 reg; wdt_dev->timeout = timeout; + /* + * In dual mode, irq will be triggered at timeout / 2 + * the real timeout occurs at timeout + */ + if (wdt_dev->pretimeout) + wdt_dev->pretimeout = timeout / 2; /* * One bit is the value of 512 ticks * The clock has 32 KHz */ - reg = WDT_LENGTH_TIMEOUT(timeout << 6) | WDT_LENGTH_KEY; + reg = WDT_LENGTH_TIMEOUT((timeout - wdt_dev->pretimeout) << 6) + | WDT_LENGTH_KEY; iowrite32(reg, wdt_base + WDT_LENGTH); mtk_wdt_ping(wdt_dev); @@ -239,13 +247,48 @@ static int mtk_wdt_start(struct watchdog_device *wdt_dev) return ret; reg = ioread32(wdt_base + WDT_MODE); - reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); + if (wdt_dev->pretimeout) + reg |= (WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); + else + reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); reg |= (WDT_MODE_EN | WDT_MODE_KEY); iowrite32(reg, wdt_base + WDT_MODE); return 0; } +static int mtk_wdt_set_pretimeout(struct watchdog_device *wdd, + unsigned int timeout) +{ + struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdd); + void __iomem *wdt_base = mtk_wdt->wdt_base; + u32 reg = ioread32(wdt_base + WDT_MODE); + + if (timeout && !wdd->pretimeout) { + wdd->pretimeout = wdd->timeout / 2; + reg |= (WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); + } else if (!timeout && wdd->pretimeout) { + wdd->pretimeout = 0; + reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); + } else { + return 0; + } + + reg |= WDT_MODE_KEY; + iowrite32(reg, wdt_base + WDT_MODE); + + return mtk_wdt_set_timeout(wdd, wdd->timeout); +} + +static irqreturn_t mtk_wdt_isr(int irq, void *arg) +{ + struct watchdog_device *wdd = arg; + + watchdog_notify_pretimeout(wdd); + + return IRQ_HANDLED; +} + static const struct watchdog_info mtk_wdt_info = { .identity = DRV_NAME, .options = WDIOF_SETTIMEOUT | @@ -253,12 +296,21 @@ static const struct watchdog_info mtk_wdt_info = { WDIOF_MAGICCLOSE, }; +static const struct watchdog_info mtk_wdt_pt_info = { + .identity = DRV_NAME, + .options = WDIOF_SETTIMEOUT | + WDIOF_PRETIMEOUT | + WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, +}; + static const struct watchdog_ops mtk_wdt_ops = { .owner = THIS_MODULE, .start = mtk_wdt_start, .stop = mtk_wdt_stop, .ping = mtk_wdt_ping, .set_timeout = mtk_wdt_set_timeout, + .set_pretimeout = mtk_wdt_set_pretimeout, .restart = mtk_wdt_restart, }; @@ -267,7 +319,7 @@ static int mtk_wdt_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct mtk_wdt_dev *mtk_wdt; const struct mtk_wdt_data *wdt_data; - int err; + int err, irq; mtk_wdt = devm_kzalloc(dev, sizeof(*mtk_wdt), GFP_KERNEL); if (!mtk_wdt) @@ -279,7 +331,22 @@ static int mtk_wdt_probe(struct platform_device *pdev) if (IS_ERR(mtk_wdt->wdt_base)) return PTR_ERR(mtk_wdt->wdt_base); - mtk_wdt->wdt_dev.info = &mtk_wdt_info; + irq = platform_get_irq(pdev, 0); + if (irq > 0) { + err = devm_request_irq(&pdev->dev, irq, mtk_wdt_isr, 0, "wdt_bark", + &mtk_wdt->wdt_dev); + if (err) + return err; + + mtk_wdt->wdt_dev.info = &mtk_wdt_pt_info; + mtk_wdt->wdt_dev.pretimeout = WDT_MAX_TIMEOUT / 2; + } else { + if (irq == -EPROBE_DEFER) + return -EPROBE_DEFER; + + mtk_wdt->wdt_dev.info = &mtk_wdt_info; + } + mtk_wdt->wdt_dev.ops = &mtk_wdt_ops; mtk_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT; mtk_wdt->wdt_dev.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT * 1000; diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c index 8aa1cb4a295f..ea1bbf5ee528 100644 --- a/drivers/watchdog/mtx-1_wdt.c +++ b/drivers/watchdog/mtx-1_wdt.c @@ -41,8 +41,6 @@ #include <linux/uaccess.h> #include <linux/gpio/consumer.h> -#include <asm/mach-au1x00/au1000.h> - #define MTX1_WDT_INTERVAL (5 * HZ) static int ticks = 100 * HZ; diff --git a/drivers/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c deleted file mode 100644 index 894aa63488d3..000000000000 --- a/drivers/watchdog/mv64x60_wdt.c +++ /dev/null @@ -1,324 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * mv64x60_wdt.c - MV64X60 (Marvell Discovery) watchdog userspace interface - * - * Author: James Chapman <jchapman@katalix.com> - * - * Platform-specific setup code should configure the dog to generate - * interrupt or reset as required. This code only enables/disables - * and services the watchdog. - * - * Derived from mpc8xx_wdt.c, with the following copyright. - * - * 2002 (c) Florian Schirmer <jolt@tuxbox.org> - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/fs.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/miscdevice.h> -#include <linux/module.h> -#include <linux/watchdog.h> -#include <linux/platform_device.h> -#include <linux/mv643xx.h> -#include <linux/uaccess.h> -#include <linux/io.h> - -#define MV64x60_WDT_WDC_OFFSET 0 - -/* - * The watchdog configuration register contains a pair of 2-bit fields, - * 1. a reload field, bits 27-26, which triggers a reload of - * the countdown register, and - * 2. an enable field, bits 25-24, which toggles between - * enabling and disabling the watchdog timer. - * Bit 31 is a read-only field which indicates whether the - * watchdog timer is currently enabled. - * - * The low 24 bits contain the timer reload value. - */ -#define MV64x60_WDC_ENABLE_SHIFT 24 -#define MV64x60_WDC_SERVICE_SHIFT 26 -#define MV64x60_WDC_ENABLED_SHIFT 31 - -#define MV64x60_WDC_ENABLED_TRUE 1 -#define MV64x60_WDC_ENABLED_FALSE 0 - -/* Flags bits */ -#define MV64x60_WDOG_FLAG_OPENED 0 - -static unsigned long wdt_flags; -static int wdt_status; -static void __iomem *mv64x60_wdt_regs; -static int mv64x60_wdt_timeout; -static int mv64x60_wdt_count; -static unsigned int bus_clk; -static char expect_close; -static DEFINE_SPINLOCK(mv64x60_wdt_spinlock); - -static bool nowayout = WATCHDOG_NOWAYOUT; -module_param(nowayout, bool, 0); -MODULE_PARM_DESC(nowayout, - "Watchdog cannot be stopped once started (default=" - __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); - -static int mv64x60_wdt_toggle_wdc(int enabled_predicate, int field_shift) -{ - u32 data; - u32 enabled; - int ret = 0; - - spin_lock(&mv64x60_wdt_spinlock); - data = readl(mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET); - enabled = (data >> MV64x60_WDC_ENABLED_SHIFT) & 1; - - /* only toggle the requested field if enabled state matches predicate */ - if ((enabled ^ enabled_predicate) == 0) { - /* We write a 1, then a 2 -- to the appropriate field */ - data = (1 << field_shift) | mv64x60_wdt_count; - writel(data, mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET); - - data = (2 << field_shift) | mv64x60_wdt_count; - writel(data, mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET); - ret = 1; - } - spin_unlock(&mv64x60_wdt_spinlock); - - return ret; -} - -static void mv64x60_wdt_service(void) -{ - mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE, - MV64x60_WDC_SERVICE_SHIFT); -} - -static void mv64x60_wdt_handler_enable(void) -{ - if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_FALSE, - MV64x60_WDC_ENABLE_SHIFT)) { - mv64x60_wdt_service(); - pr_notice("watchdog activated\n"); - } -} - -static void mv64x60_wdt_handler_disable(void) -{ - if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE, - MV64x60_WDC_ENABLE_SHIFT)) - pr_notice("watchdog deactivated\n"); -} - -static void mv64x60_wdt_set_timeout(unsigned int timeout) -{ - /* maximum bus cycle count is 0xFFFFFFFF */ - if (timeout > 0xFFFFFFFF / bus_clk) - timeout = 0xFFFFFFFF / bus_clk; - - mv64x60_wdt_count = timeout * bus_clk >> 8; - mv64x60_wdt_timeout = timeout; -} - -static int mv64x60_wdt_open(struct inode *inode, struct file *file) -{ - if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags)) - return -EBUSY; - - if (nowayout) - __module_get(THIS_MODULE); - - mv64x60_wdt_handler_enable(); - - return stream_open(inode, file); -} - -static int mv64x60_wdt_release(struct inode *inode, struct file *file) -{ - if (expect_close == 42) - mv64x60_wdt_handler_disable(); - else { - pr_crit("unexpected close, not stopping timer!\n"); - mv64x60_wdt_service(); - } - expect_close = 0; - - clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags); - - return 0; -} - -static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data, - size_t len, loff_t *ppos) -{ - if (len) { - if (!nowayout) { - size_t i; - - expect_close = 0; - - for (i = 0; i != len; i++) { - char c; - if (get_user(c, data + i)) - return -EFAULT; - if (c == 'V') - expect_close = 42; - } - } - mv64x60_wdt_service(); - } - - return len; -} - -static long mv64x60_wdt_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - int timeout; - int options; - void __user *argp = (void __user *)arg; - static const struct watchdog_info info = { - .options = WDIOF_SETTIMEOUT | - WDIOF_MAGICCLOSE | - WDIOF_KEEPALIVEPING, - .firmware_version = 0, - .identity = "MV64x60 watchdog", - }; - - switch (cmd) { - case WDIOC_GETSUPPORT: - if (copy_to_user(argp, &info, sizeof(info))) - return -EFAULT; - break; - - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - if (put_user(wdt_status, (int __user *)argp)) - return -EFAULT; - wdt_status &= ~WDIOF_KEEPALIVEPING; - break; - - case WDIOC_GETTEMP: - return -EOPNOTSUPP; - - case WDIOC_SETOPTIONS: - if (get_user(options, (int __user *)argp)) - return -EFAULT; - - if (options & WDIOS_DISABLECARD) - mv64x60_wdt_handler_disable(); - - if (options & WDIOS_ENABLECARD) - mv64x60_wdt_handler_enable(); - break; - - case WDIOC_KEEPALIVE: - mv64x60_wdt_service(); - wdt_status |= WDIOF_KEEPALIVEPING; - break; - - case WDIOC_SETTIMEOUT: - if (get_user(timeout, (int __user *)argp)) - return -EFAULT; - mv64x60_wdt_set_timeout(timeout); - fallthrough; - - case WDIOC_GETTIMEOUT: - if (put_user(mv64x60_wdt_timeout, (int __user *)argp)) - return -EFAULT; - break; - - default: - return -ENOTTY; - } - - return 0; -} - -static const struct file_operations mv64x60_wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = mv64x60_wdt_write, - .unlocked_ioctl = mv64x60_wdt_ioctl, - .compat_ioctl = compat_ptr_ioctl, - .open = mv64x60_wdt_open, - .release = mv64x60_wdt_release, -}; - -static struct miscdevice mv64x60_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &mv64x60_wdt_fops, -}; - -static int mv64x60_wdt_probe(struct platform_device *dev) -{ - struct mv64x60_wdt_pdata *pdata = dev_get_platdata(&dev->dev); - struct resource *r; - int timeout = 10; - - bus_clk = 133; /* in MHz */ - if (pdata) { - timeout = pdata->timeout; - bus_clk = pdata->bus_clk; - } - - /* Since bus_clk is truncated MHz, actual frequency could be - * up to 1MHz higher. Round up, since it's better to time out - * too late than too soon. - */ - bus_clk++; - bus_clk *= 1000000; /* convert to Hz */ - - r = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (!r) - return -ENODEV; - - mv64x60_wdt_regs = devm_ioremap(&dev->dev, r->start, resource_size(r)); - if (mv64x60_wdt_regs == NULL) - return -ENOMEM; - - mv64x60_wdt_set_timeout(timeout); - - mv64x60_wdt_handler_disable(); /* in case timer was already running */ - - return misc_register(&mv64x60_wdt_miscdev); -} - -static int mv64x60_wdt_remove(struct platform_device *dev) -{ - misc_deregister(&mv64x60_wdt_miscdev); - - mv64x60_wdt_handler_disable(); - - return 0; -} - -static struct platform_driver mv64x60_wdt_driver = { - .probe = mv64x60_wdt_probe, - .remove = mv64x60_wdt_remove, - .driver = { - .name = MV64x60_WDT_NAME, - }, -}; - -static int __init mv64x60_wdt_init(void) -{ - pr_info("MV64x60 watchdog driver\n"); - - return platform_driver_register(&mv64x60_wdt_driver); -} - -static void __exit mv64x60_wdt_exit(void) -{ - platform_driver_unregister(&mv64x60_wdt_driver); -} - -module_init(mv64x60_wdt_init); -module_exit(mv64x60_wdt_exit); - -MODULE_AUTHOR("James Chapman <jchapman@katalix.com>"); -MODULE_DESCRIPTION("MV64x60 watchdog driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" MV64x60_WDT_NAME); diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c index 391c774a1f67..0fe71f7e66d5 100644 --- a/drivers/watchdog/octeon-wdt-main.c +++ b/drivers/watchdog/octeon-wdt-main.c @@ -120,7 +120,7 @@ static int cpu2core(int cpu) } /** - * Poke the watchdog when an interrupt is received + * octeon_wdt_poke_irq - Poke the watchdog when an interrupt is received * * @cpl: * @dev_id: @@ -154,7 +154,7 @@ static irqreturn_t octeon_wdt_poke_irq(int cpl, void *dev_id) extern int prom_putchar(char c); /** - * Write a string to the uart + * octeon_wdt_write_string - Write a string to the uart * * @str: String to write */ @@ -166,7 +166,7 @@ static void octeon_wdt_write_string(const char *str) } /** - * Write a hex number out of the uart + * octeon_wdt_write_hex() - Write a hex number out of the uart * * @value: Number to display * @digits: Number of digits to print (1 to 16) @@ -193,6 +193,8 @@ static const char reg_name[][3] = { }; /** + * octeon_wdt_nmi_stage3: + * * NMI stage 3 handler. NMIs are handled in the following manner: * 1) The first NMI handler enables CVMSEG and transfers from * the bootbus region into normal memory. It is careful to not @@ -514,7 +516,7 @@ static struct watchdog_device octeon_wdt = { static enum cpuhp_state octeon_wdt_online; /** - * Module/ driver initialization. + * octeon_wdt_init - Module/ driver initialization. * * Returns Zero on success */ @@ -586,7 +588,7 @@ err: } /** - * Module / driver shutdown + * octeon_wdt_cleanup - Module / driver shutdown */ static void __exit octeon_wdt_cleanup(void) { diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c index 7fe4f7c3f7ce..3318544366b8 100644 --- a/drivers/watchdog/of_xilinx_wdt.c +++ b/drivers/watchdog/of_xilinx_wdt.c @@ -6,6 +6,7 @@ * (C) Copyright 2011 (Alejandro Cabrera <aldaya@gmail.com>) */ +#include <linux/bits.h> #include <linux/clk.h> #include <linux/err.h> #include <linux/module.h> @@ -24,12 +25,12 @@ #define XWT_TBR_OFFSET 0x8 /* Timebase Register Offset */ /* Control/Status Register Masks */ -#define XWT_CSR0_WRS_MASK 0x00000008 /* Reset status */ -#define XWT_CSR0_WDS_MASK 0x00000004 /* Timer state */ -#define XWT_CSR0_EWDT1_MASK 0x00000002 /* Enable bit 1 */ +#define XWT_CSR0_WRS_MASK BIT(3) /* Reset status */ +#define XWT_CSR0_WDS_MASK BIT(2) /* Timer state */ +#define XWT_CSR0_EWDT1_MASK BIT(1) /* Enable bit 1 */ /* Control/Status Register 0/1 bits */ -#define XWT_CSRX_EWDT2_MASK 0x00000001 /* Enable bit 2 */ +#define XWT_CSRX_EWDT2_MASK BIT(0) /* Enable bit 2 */ /* SelfTest constants */ #define XWT_MAX_SELFTEST_LOOP_COUNT 0x00010000 @@ -40,7 +41,7 @@ struct xwdt_device { void __iomem *base; u32 wdt_interval; - spinlock_t spinlock; + spinlock_t spinlock; /* spinlock for register handling */ struct watchdog_device xilinx_wdt_wdd; struct clk *clk; }; @@ -70,6 +71,8 @@ static int xilinx_wdt_start(struct watchdog_device *wdd) spin_unlock(&xdev->spinlock); + dev_dbg(wdd->parent, "Watchdog Started!\n"); + return 0; } @@ -91,7 +94,7 @@ static int xilinx_wdt_stop(struct watchdog_device *wdd) clk_disable(xdev->clk); - pr_info("Stopped!\n"); + dev_dbg(wdd->parent, "Watchdog Stopped!\n"); return 0; } @@ -208,6 +211,15 @@ static int xwdt_probe(struct platform_device *pdev) "The watchdog clock freq cannot be obtained\n"); } else { pfreq = clk_get_rate(xdev->clk); + rc = clk_prepare_enable(xdev->clk); + if (rc) { + dev_err(dev, "unable to enable clock\n"); + return rc; + } + rc = devm_add_action_or_reset(dev, xwdt_clk_disable_unprepare, + xdev->clk); + if (rc) + return rc; } /* @@ -221,16 +233,6 @@ static int xwdt_probe(struct platform_device *pdev) spin_lock_init(&xdev->spinlock); watchdog_set_drvdata(xilinx_wdt_wdd, xdev); - rc = clk_prepare_enable(xdev->clk); - if (rc) { - dev_err(dev, "unable to enable clock\n"); - return rc; - } - rc = devm_add_action_or_reset(dev, xwdt_clk_disable_unprepare, - xdev->clk); - if (rc) - return rc; - rc = xwdt_selftest(xdev); if (rc == XWT_TIMER_FAILED) { dev_err(dev, "SelfTest routine error\n"); @@ -243,8 +245,8 @@ static int xwdt_probe(struct platform_device *pdev) clk_disable(xdev->clk); - dev_info(dev, "Xilinx Watchdog Timer at %p with timeout %ds\n", - xdev->base, xilinx_wdt_wdd->timeout); + dev_info(dev, "Xilinx Watchdog Timer with timeout %ds\n", + xilinx_wdt_wdd->timeout); platform_set_drvdata(pdev, xdev); diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index 4ddb4ea2e4a3..127eefc9161d 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -174,7 +174,7 @@ static int armadaxp_wdt_clock_init(struct platform_device *pdev, return ret; } - /* Fix the wdt and timer1 clock freqency to 25MHz */ + /* Fix the wdt and timer1 clock frequency to 25MHz */ val = WDT_AXP_FIXED_ENABLE_BIT | TIMER1_FIXED_ENABLE_BIT; atomic_io_modify(dev->reg + TIMER_CTRL, val, val); diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c index 2d4504302c9e..9f9a340427fc 100644 --- a/drivers/watchdog/pc87413_wdt.c +++ b/drivers/watchdog/pc87413_wdt.c @@ -445,7 +445,7 @@ static long pc87413_ioctl(struct file *file, unsigned int cmd, /* -- Notifier funtions -----------------------------------------*/ /** - * notify_sys: + * pc87413_notify_sys: * @this: our notifier block * @code: the event being reported * @unused: unused diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c index e38a87ffe5f5..0d2209c5eaca 100644 --- a/drivers/watchdog/qcom-wdt.c +++ b/drivers/watchdog/qcom-wdt.c @@ -329,7 +329,9 @@ static int __maybe_unused qcom_wdt_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(qcom_wdt_pm_ops, qcom_wdt_suspend, qcom_wdt_resume); +static const struct dev_pm_ops qcom_wdt_pm_ops = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(qcom_wdt_suspend, qcom_wdt_resume) +}; static const struct of_device_id qcom_wdt_of_table[] = { { .compatible = "qcom,kpss-timer", .data = &match_data_apcs_tmr }, diff --git a/drivers/watchdog/sama5d4_wdt.c b/drivers/watchdog/sama5d4_wdt.c index e5d11d6a2600..ec20ad4e534f 100644 --- a/drivers/watchdog/sama5d4_wdt.c +++ b/drivers/watchdog/sama5d4_wdt.c @@ -268,8 +268,10 @@ static int sama5d4_wdt_probe(struct platform_device *pdev) wdd->min_timeout = MIN_WDT_TIMEOUT; wdd->max_timeout = MAX_WDT_TIMEOUT; wdt->last_ping = jiffies; - wdt->sam9x60_support = of_device_is_compatible(dev->of_node, - "microchip,sam9x60-wdt"); + + if (of_device_is_compatible(dev->of_node, "microchip,sam9x60-wdt") || + of_device_is_compatible(dev->of_node, "microchip,sama7g5-wdt")) + wdt->sam9x60_support = true; watchdog_set_drvdata(wdd, wdt); @@ -329,6 +331,10 @@ static const struct of_device_id sama5d4_wdt_of_match[] = { { .compatible = "microchip,sam9x60-wdt", }, + { + .compatible = "microchip,sama7g5-wdt", + }, + { } }; MODULE_DEVICE_TABLE(of, sama5d4_wdt_of_match); diff --git a/drivers/watchdog/sbc60xxwdt.c b/drivers/watchdog/sbc60xxwdt.c index a947a63fb44a..7b974802dfc7 100644 --- a/drivers/watchdog/sbc60xxwdt.c +++ b/drivers/watchdog/sbc60xxwdt.c @@ -146,7 +146,7 @@ static void wdt_startup(void) static void wdt_turnoff(void) { /* Stop the timer */ - del_timer(&timer); + del_timer_sync(&timer); inb_p(wdt_stop); pr_info("Watchdog timer is now disabled...\n"); } diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c index f0f1e3b2e463..ee9ff38929eb 100644 --- a/drivers/watchdog/sbsa_gwdt.c +++ b/drivers/watchdog/sbsa_gwdt.c @@ -73,16 +73,21 @@ #define SBSA_GWDT_WCS_WS0 BIT(1) #define SBSA_GWDT_WCS_WS1 BIT(2) +#define SBSA_GWDT_VERSION_MASK 0xF +#define SBSA_GWDT_VERSION_SHIFT 16 + /** * struct sbsa_gwdt - Internal representation of the SBSA GWDT * @wdd: kernel watchdog_device structure * @clk: store the System Counter clock frequency, in Hz. + * @version: store the architecture version * @refresh_base: Virtual address of the watchdog refresh frame * @control_base: Virtual address of the watchdog control frame */ struct sbsa_gwdt { struct watchdog_device wdd; u32 clk; + int version; void __iomem *refresh_base; void __iomem *control_base; }; @@ -113,6 +118,30 @@ MODULE_PARM_DESC(nowayout, __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); /* + * Arm Base System Architecture 1.0 introduces watchdog v1 which + * increases the length watchdog offset register to 48 bits. + * - For version 0: WOR is 32 bits; + * - For version 1: WOR is 48 bits which comprises the register + * offset 0x8 and 0xC, and the bits [63:48] are reserved which are + * Read-As-Zero and Writes-Ignored. + */ +static u64 sbsa_gwdt_reg_read(struct sbsa_gwdt *gwdt) +{ + if (gwdt->version == 0) + return readl(gwdt->control_base + SBSA_GWDT_WOR); + else + return readq(gwdt->control_base + SBSA_GWDT_WOR); +} + +static void sbsa_gwdt_reg_write(u64 val, struct sbsa_gwdt *gwdt) +{ + if (gwdt->version == 0) + writel((u32)val, gwdt->control_base + SBSA_GWDT_WOR); + else + writeq(val, gwdt->control_base + SBSA_GWDT_WOR); +} + +/* * watchdog operation functions */ static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd, @@ -123,16 +152,14 @@ static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd, wdd->timeout = timeout; if (action) - writel(gwdt->clk * timeout, - gwdt->control_base + SBSA_GWDT_WOR); + sbsa_gwdt_reg_write(gwdt->clk * timeout, gwdt); else /* * In the single stage mode, The first signal (WS0) is ignored, * the timeout is (WOR * 2), so the WOR should be configured * to half value of timeout. */ - writel(gwdt->clk / 2 * timeout, - gwdt->control_base + SBSA_GWDT_WOR); + sbsa_gwdt_reg_write(gwdt->clk / 2 * timeout, gwdt); return 0; } @@ -149,7 +176,7 @@ static unsigned int sbsa_gwdt_get_timeleft(struct watchdog_device *wdd) */ if (!action && !(readl(gwdt->control_base + SBSA_GWDT_WCS) & SBSA_GWDT_WCS_WS0)) - timeleft += readl(gwdt->control_base + SBSA_GWDT_WOR); + timeleft += sbsa_gwdt_reg_read(gwdt); timeleft += lo_hi_readq(gwdt->control_base + SBSA_GWDT_WCV) - arch_timer_read_counter(); @@ -172,6 +199,17 @@ static int sbsa_gwdt_keepalive(struct watchdog_device *wdd) return 0; } +static void sbsa_gwdt_get_version(struct watchdog_device *wdd) +{ + struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd); + int ver; + + ver = readl(gwdt->control_base + SBSA_GWDT_W_IIDR); + ver = (ver >> SBSA_GWDT_VERSION_SHIFT) & SBSA_GWDT_VERSION_MASK; + + gwdt->version = ver; +} + static int sbsa_gwdt_start(struct watchdog_device *wdd) { struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd); @@ -252,10 +290,14 @@ static int sbsa_gwdt_probe(struct platform_device *pdev) wdd->info = &sbsa_gwdt_info; wdd->ops = &sbsa_gwdt_ops; wdd->min_timeout = 1; - wdd->max_hw_heartbeat_ms = U32_MAX / gwdt->clk * 1000; wdd->timeout = DEFAULT_TIMEOUT; watchdog_set_drvdata(wdd, gwdt); watchdog_set_nowayout(wdd, nowayout); + sbsa_gwdt_get_version(wdd); + if (gwdt->version == 0) + wdd->max_hw_heartbeat_ms = U32_MAX / gwdt->clk * 1000; + else + wdd->max_hw_heartbeat_ms = GENMASK_ULL(47, 0) / gwdt->clk * 1000; status = readl(cf_base + SBSA_GWDT_WCS); if (status & SBSA_GWDT_WCS_WS1) { diff --git a/drivers/watchdog/sc520_wdt.c b/drivers/watchdog/sc520_wdt.c index e66e6b905964..ca65468f4b9c 100644 --- a/drivers/watchdog/sc520_wdt.c +++ b/drivers/watchdog/sc520_wdt.c @@ -186,7 +186,7 @@ static int wdt_startup(void) static int wdt_turnoff(void) { /* Stop the timer */ - del_timer(&timer); + del_timer_sync(&timer); /* Stop the watchdog */ wdt_config(0); diff --git a/drivers/watchdog/sl28cpld_wdt.c b/drivers/watchdog/sl28cpld_wdt.c index a45047d8d9ab..2de93298475f 100644 --- a/drivers/watchdog/sl28cpld_wdt.c +++ b/drivers/watchdog/sl28cpld_wdt.c @@ -164,7 +164,7 @@ static int sl28cpld_wdt_probe(struct platform_device *pdev) /* * Initial timeout value, may be overwritten by device tree or module - * parmeter in watchdog_init_timeout(). + * parameter in watchdog_init_timeout(). * * Reading a zero here means that either the hardware has a default * value of zero (which is very unlikely and definitely a hardware diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index 58a00e1ab23b..dbeb2146c968 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -11,7 +11,6 @@ * warranty of any kind, whether express or implied. */ -#include <linux/acpi.h> #include <linux/device.h> #include <linux/resource.h> #include <linux/amba/bus.h> @@ -23,8 +22,8 @@ #include <linux/math64.h> #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/of.h> #include <linux/pm.h> +#include <linux/property.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/types.h> @@ -58,7 +57,8 @@ * @wdd: instance of struct watchdog_device * @lock: spin lock protecting dev structure and io access * @base: base address of wdt - * @clk: clock structure of wdt + * @clk: (optional) clock structure of wdt + * @rate: (optional) clock rate when provided via properties * @adev: amba device structure of wdt * @status: current status of wdt * @load_val: load value to be set for current timeout @@ -231,6 +231,7 @@ static int sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id) { struct sp805_wdt *wdt; + u64 rate = 0; int ret = 0; wdt = devm_kzalloc(&adev->dev, sizeof(*wdt), GFP_KERNEL); @@ -243,25 +244,23 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id) if (IS_ERR(wdt->base)) return PTR_ERR(wdt->base); - if (adev->dev.of_node) { - wdt->clk = devm_clk_get(&adev->dev, NULL); - if (IS_ERR(wdt->clk)) { - dev_err(&adev->dev, "Clock not found\n"); - return PTR_ERR(wdt->clk); - } - wdt->rate = clk_get_rate(wdt->clk); - } else if (has_acpi_companion(&adev->dev)) { - /* - * When Driver probe with ACPI device, clock devices - * are not available, so watchdog rate get from - * clock-frequency property given in _DSD object. - */ - device_property_read_u64(&adev->dev, "clock-frequency", - &wdt->rate); - if (!wdt->rate) { - dev_err(&adev->dev, "no clock-frequency property\n"); - return -ENODEV; - } + /* + * When driver probe with ACPI device, clock devices + * are not available, so watchdog rate get from + * clock-frequency property given in _DSD object. + */ + device_property_read_u64(&adev->dev, "clock-frequency", &rate); + + wdt->clk = devm_clk_get_optional(&adev->dev, NULL); + if (IS_ERR(wdt->clk)) + return dev_err_probe(&adev->dev, PTR_ERR(wdt->clk), "Clock not found\n"); + + wdt->rate = clk_get_rate(wdt->clk); + if (!wdt->rate) + wdt->rate = rate; + if (!wdt->rate) { + dev_err(&adev->dev, "no clock-frequency property\n"); + return -ENODEV; } wdt->adev = adev; diff --git a/drivers/watchdog/w83877f_wdt.c b/drivers/watchdog/w83877f_wdt.c index 5772cc5d3780..f2650863fd02 100644 --- a/drivers/watchdog/w83877f_wdt.c +++ b/drivers/watchdog/w83877f_wdt.c @@ -166,7 +166,7 @@ static void wdt_startup(void) static void wdt_turnoff(void) { /* Stop the timer */ - del_timer(&timer); + del_timer_sync(&timer); wdt_change(WDT_DISABLE); diff --git a/drivers/watchdog/watchdog_core.h b/drivers/watchdog/watchdog_core.h index a5062e8e0d13..5b35a8439e26 100644 --- a/drivers/watchdog/watchdog_core.h +++ b/drivers/watchdog/watchdog_core.h @@ -7,6 +7,8 @@ * * (c) Copyright 2008-2011 Wim Van Sebroeck <wim@iguana.be>. * + * (c) Copyright 2021 Hewlett Packard Enterprise Development LP. + * * This source code is part of the generic code that can be used * by all the watchdog timer drivers. * @@ -22,12 +24,58 @@ * This material is provided "AS-IS" and at no charge. */ +#include <linux/hrtimer.h> +#include <linux/kthread.h> + #define MAX_DOGS 32 /* Maximum number of watchdog devices */ /* + * struct watchdog_core_data - watchdog core internal data + * @dev: The watchdog's internal device + * @cdev: The watchdog's Character device. + * @wdd: Pointer to watchdog device. + * @lock: Lock for watchdog core. + * @status: Watchdog core internal status bits. + */ +struct watchdog_core_data { + struct device dev; + struct cdev cdev; + struct watchdog_device *wdd; + struct mutex lock; + ktime_t last_keepalive; + ktime_t last_hw_keepalive; + ktime_t open_deadline; + struct hrtimer timer; + struct kthread_work work; +#if IS_ENABLED(CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT) + struct hrtimer pretimeout_timer; +#endif + unsigned long status; /* Internal status bits */ +#define _WDOG_DEV_OPEN 0 /* Opened ? */ +#define _WDOG_ALLOW_RELEASE 1 /* Did we receive the magic char ? */ +#define _WDOG_KEEPALIVE 2 /* Did we receive a keepalive ? */ +}; + +/* * Functions/procedures to be called by the core */ extern int watchdog_dev_register(struct watchdog_device *); extern void watchdog_dev_unregister(struct watchdog_device *); extern int __init watchdog_dev_init(void); extern void __exit watchdog_dev_exit(void); + +static inline bool watchdog_have_pretimeout(struct watchdog_device *wdd) +{ + return wdd->info->options & WDIOF_PRETIMEOUT || + IS_ENABLED(CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT); +} + +#if IS_ENABLED(CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT) +void watchdog_hrtimer_pretimeout_init(struct watchdog_device *wdd); +void watchdog_hrtimer_pretimeout_start(struct watchdog_device *wdd); +void watchdog_hrtimer_pretimeout_stop(struct watchdog_device *wdd); +#else +static inline void watchdog_hrtimer_pretimeout_init(struct watchdog_device *wdd) {} +static inline void watchdog_hrtimer_pretimeout_start(struct watchdog_device *wdd) {} +static inline void watchdog_hrtimer_pretimeout_stop(struct watchdog_device *wdd) {} +#endif diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index 2946f3a63110..3bab32485273 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -7,6 +7,7 @@ * * (c) Copyright 2008-2011 Wim Van Sebroeck <wim@iguana.be>. * + * (c) Copyright 2021 Hewlett Packard Enterprise Development LP. * * This source code is part of the generic code that can be used * by all the watchdog timer drivers. @@ -46,30 +47,6 @@ #include "watchdog_core.h" #include "watchdog_pretimeout.h" -/* - * struct watchdog_core_data - watchdog core internal data - * @dev: The watchdog's internal device - * @cdev: The watchdog's Character device. - * @wdd: Pointer to watchdog device. - * @lock: Lock for watchdog core. - * @status: Watchdog core internal status bits. - */ -struct watchdog_core_data { - struct device dev; - struct cdev cdev; - struct watchdog_device *wdd; - struct mutex lock; - ktime_t last_keepalive; - ktime_t last_hw_keepalive; - ktime_t open_deadline; - struct hrtimer timer; - struct kthread_work work; - unsigned long status; /* Internal status bits */ -#define _WDOG_DEV_OPEN 0 /* Opened ? */ -#define _WDOG_ALLOW_RELEASE 1 /* Did we receive the magic char ? */ -#define _WDOG_KEEPALIVE 2 /* Did we receive a keepalive ? */ -}; - /* the dev_t structure to store the dynamically allocated watchdog devices */ static dev_t watchdog_devt; /* Reference to watchdog device behind /dev/watchdog */ @@ -185,6 +162,9 @@ static int __watchdog_ping(struct watchdog_device *wdd) else err = wdd->ops->start(wdd); /* restart watchdog */ + if (err == 0) + watchdog_hrtimer_pretimeout_start(wdd); + watchdog_update_worker(wdd); return err; @@ -275,8 +255,10 @@ static int watchdog_start(struct watchdog_device *wdd) started_at = ktime_get(); if (watchdog_hw_running(wdd) && wdd->ops->ping) { err = __watchdog_ping(wdd); - if (err == 0) + if (err == 0) { set_bit(WDOG_ACTIVE, &wdd->status); + watchdog_hrtimer_pretimeout_start(wdd); + } } else { err = wdd->ops->start(wdd); if (err == 0) { @@ -284,6 +266,7 @@ static int watchdog_start(struct watchdog_device *wdd) wd_data->last_keepalive = started_at; wd_data->last_hw_keepalive = started_at; watchdog_update_worker(wdd); + watchdog_hrtimer_pretimeout_start(wdd); } } @@ -325,6 +308,7 @@ static int watchdog_stop(struct watchdog_device *wdd) if (err == 0) { clear_bit(WDOG_ACTIVE, &wdd->status); watchdog_update_worker(wdd); + watchdog_hrtimer_pretimeout_stop(wdd); } return err; @@ -361,6 +345,9 @@ static unsigned int watchdog_get_status(struct watchdog_device *wdd) if (test_and_clear_bit(_WDOG_KEEPALIVE, &wd_data->status)) status |= WDIOF_KEEPALIVEPING; + if (IS_ENABLED(CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT)) + status |= WDIOF_PRETIMEOUT; + return status; } @@ -408,7 +395,7 @@ static int watchdog_set_pretimeout(struct watchdog_device *wdd, { int err = 0; - if (!(wdd->info->options & WDIOF_PRETIMEOUT)) + if (!watchdog_have_pretimeout(wdd)) return -EOPNOTSUPP; if (watchdog_pretimeout_invalid(wdd, timeout)) @@ -451,7 +438,8 @@ static ssize_t nowayout_show(struct device *dev, struct device_attribute *attr, { struct watchdog_device *wdd = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", !!test_bit(WDOG_NO_WAY_OUT, &wdd->status)); + return sysfs_emit(buf, "%d\n", !!test_bit(WDOG_NO_WAY_OUT, + &wdd->status)); } static ssize_t nowayout_store(struct device *dev, struct device_attribute *attr, @@ -485,7 +473,7 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr, status = watchdog_get_status(wdd); mutex_unlock(&wd_data->lock); - return sprintf(buf, "0x%x\n", status); + return sysfs_emit(buf, "0x%x\n", status); } static DEVICE_ATTR_RO(status); @@ -494,7 +482,7 @@ static ssize_t bootstatus_show(struct device *dev, { struct watchdog_device *wdd = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", wdd->bootstatus); + return sysfs_emit(buf, "%u\n", wdd->bootstatus); } static DEVICE_ATTR_RO(bootstatus); @@ -510,7 +498,7 @@ static ssize_t timeleft_show(struct device *dev, struct device_attribute *attr, status = watchdog_get_timeleft(wdd, &val); mutex_unlock(&wd_data->lock); if (!status) - status = sprintf(buf, "%u\n", val); + status = sysfs_emit(buf, "%u\n", val); return status; } @@ -521,16 +509,34 @@ static ssize_t timeout_show(struct device *dev, struct device_attribute *attr, { struct watchdog_device *wdd = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", wdd->timeout); + return sysfs_emit(buf, "%u\n", wdd->timeout); } static DEVICE_ATTR_RO(timeout); +static ssize_t min_timeout_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct watchdog_device *wdd = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", wdd->min_timeout); +} +static DEVICE_ATTR_RO(min_timeout); + +static ssize_t max_timeout_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct watchdog_device *wdd = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", wdd->max_timeout); +} +static DEVICE_ATTR_RO(max_timeout); + static ssize_t pretimeout_show(struct device *dev, struct device_attribute *attr, char *buf) { struct watchdog_device *wdd = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", wdd->pretimeout); + return sysfs_emit(buf, "%u\n", wdd->pretimeout); } static DEVICE_ATTR_RO(pretimeout); @@ -539,7 +545,7 @@ static ssize_t identity_show(struct device *dev, struct device_attribute *attr, { struct watchdog_device *wdd = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", wdd->info->identity); + return sysfs_emit(buf, "%s\n", wdd->info->identity); } static DEVICE_ATTR_RO(identity); @@ -549,9 +555,9 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr, struct watchdog_device *wdd = dev_get_drvdata(dev); if (watchdog_active(wdd)) - return sprintf(buf, "active\n"); + return sysfs_emit(buf, "active\n"); - return sprintf(buf, "inactive\n"); + return sysfs_emit(buf, "inactive\n"); } static DEVICE_ATTR_RO(state); @@ -594,13 +600,11 @@ static umode_t wdt_is_visible(struct kobject *kobj, struct attribute *attr, if (attr == &dev_attr_timeleft.attr && !wdd->ops->get_timeleft) mode = 0; - else if (attr == &dev_attr_pretimeout.attr && - !(wdd->info->options & WDIOF_PRETIMEOUT)) + else if (attr == &dev_attr_pretimeout.attr && !watchdog_have_pretimeout(wdd)) mode = 0; else if ((attr == &dev_attr_pretimeout_governor.attr || attr == &dev_attr_pretimeout_available_governors.attr) && - (!(wdd->info->options & WDIOF_PRETIMEOUT) || - !IS_ENABLED(CONFIG_WATCHDOG_PRETIMEOUT_GOV))) + (!watchdog_have_pretimeout(wdd) || !IS_ENABLED(CONFIG_WATCHDOG_PRETIMEOUT_GOV))) mode = 0; return mode; @@ -609,6 +613,8 @@ static struct attribute *wdt_attrs[] = { &dev_attr_state.attr, &dev_attr_identity.attr, &dev_attr_timeout.attr, + &dev_attr_min_timeout.attr, + &dev_attr_max_timeout.attr, &dev_attr_pretimeout.attr, &dev_attr_timeleft.attr, &dev_attr_bootstatus.attr, @@ -1009,6 +1015,7 @@ static int watchdog_cdev_register(struct watchdog_device *wdd) kthread_init_work(&wd_data->work, watchdog_ping_work); hrtimer_init(&wd_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD); wd_data->timer.function = watchdog_timer_expired; + watchdog_hrtimer_pretimeout_init(wdd); if (wdd->id == 0) { old_wd_data = wd_data; @@ -1096,6 +1103,7 @@ static void watchdog_cdev_unregister(struct watchdog_device *wdd) hrtimer_cancel(&wd_data->timer); kthread_cancel_work_sync(&wd_data->work); + watchdog_hrtimer_pretimeout_stop(wdd); put_device(&wd_data->dev); } diff --git a/drivers/watchdog/watchdog_hrtimer_pretimeout.c b/drivers/watchdog/watchdog_hrtimer_pretimeout.c new file mode 100644 index 000000000000..940b53718a91 --- /dev/null +++ b/drivers/watchdog/watchdog_hrtimer_pretimeout.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (c) Copyright 2021 Hewlett Packard Enterprise Development LP. + */ + +#include <linux/hrtimer.h> +#include <linux/watchdog.h> + +#include "watchdog_core.h" +#include "watchdog_pretimeout.h" + +static enum hrtimer_restart watchdog_hrtimer_pretimeout(struct hrtimer *timer) +{ + struct watchdog_core_data *wd_data; + + wd_data = container_of(timer, struct watchdog_core_data, pretimeout_timer); + + watchdog_notify_pretimeout(wd_data->wdd); + return HRTIMER_NORESTART; +} + +void watchdog_hrtimer_pretimeout_init(struct watchdog_device *wdd) +{ + struct watchdog_core_data *wd_data = wdd->wd_data; + + hrtimer_init(&wd_data->pretimeout_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + wd_data->pretimeout_timer.function = watchdog_hrtimer_pretimeout; +} + +void watchdog_hrtimer_pretimeout_start(struct watchdog_device *wdd) +{ + if (!(wdd->info->options & WDIOF_PRETIMEOUT) && + !watchdog_pretimeout_invalid(wdd, wdd->pretimeout)) + hrtimer_start(&wdd->wd_data->pretimeout_timer, + ktime_set(wdd->timeout - wdd->pretimeout, 0), + HRTIMER_MODE_REL); + else + hrtimer_cancel(&wdd->wd_data->pretimeout_timer); +} + +void watchdog_hrtimer_pretimeout_stop(struct watchdog_device *wdd) +{ + hrtimer_cancel(&wdd->wd_data->pretimeout_timer); +} diff --git a/drivers/watchdog/watchdog_pretimeout.c b/drivers/watchdog/watchdog_pretimeout.c index 01ca84be240f..376a495ab80c 100644 --- a/drivers/watchdog/watchdog_pretimeout.c +++ b/drivers/watchdog/watchdog_pretimeout.c @@ -9,6 +9,7 @@ #include <linux/string.h> #include <linux/watchdog.h> +#include "watchdog_core.h" #include "watchdog_pretimeout.h" /* Default watchdog pretimeout governor */ @@ -55,7 +56,7 @@ int watchdog_pretimeout_available_governors_get(char *buf) mutex_lock(&governor_lock); list_for_each_entry(priv, &governor_list, entry) - count += sprintf(buf + count, "%s\n", priv->gov->name); + count += sysfs_emit_at(buf, count, "%s\n", priv->gov->name); mutex_unlock(&governor_lock); @@ -68,7 +69,7 @@ int watchdog_pretimeout_governor_get(struct watchdog_device *wdd, char *buf) spin_lock_irq(&pretimeout_lock); if (wdd->gov) - count = sprintf(buf, "%s\n", wdd->gov->name); + count = sysfs_emit(buf, "%s\n", wdd->gov->name); spin_unlock_irq(&pretimeout_lock); return count; @@ -177,7 +178,7 @@ int watchdog_register_pretimeout(struct watchdog_device *wdd) { struct watchdog_pretimeout *p; - if (!(wdd->info->options & WDIOF_PRETIMEOUT)) + if (!watchdog_have_pretimeout(wdd)) return 0; p = kzalloc(sizeof(*p), GFP_KERNEL); @@ -197,7 +198,7 @@ void watchdog_unregister_pretimeout(struct watchdog_device *wdd) { struct watchdog_pretimeout *p, *t; - if (!(wdd->info->options & WDIOF_PRETIMEOUT)) + if (!watchdog_have_pretimeout(wdd)) return; spin_lock_irq(&pretimeout_lock); diff --git a/drivers/watchdog/wdat_wdt.c b/drivers/watchdog/wdat_wdt.c index cec7917790e5..195c8c004b69 100644 --- a/drivers/watchdog/wdat_wdt.c +++ b/drivers/watchdog/wdat_wdt.c @@ -208,7 +208,7 @@ static int wdat_wdt_enable_reboot(struct wdat_wdt *wdat) /* * WDAT specification says that the watchdog is required to reboot * the system when it fires. However, it also states that it is - * recommeded to make it configurable through hardware register. We + * recommended to make it configurable through hardware register. We * enable reboot now if it is configurable, just in case. */ ret = wdat_wdt_run_action(wdat, ACPI_WDAT_SET_REBOOT, 0, NULL); @@ -475,7 +475,7 @@ static int wdat_wdt_suspend_noirq(struct device *dev) return 0; /* - * We need to stop the watchdog if firmare is not doing it or if we + * We need to stop the watchdog if firmware is not doing it or if we * are going suspend to idle (where firmware is not involved). If * firmware is stopping the watchdog we kick it here one more time * to give it some time. diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c index a9e40b5c633e..183876156243 100644 --- a/drivers/watchdog/wdt.c +++ b/drivers/watchdog/wdt.c @@ -494,7 +494,7 @@ static int wdt_temp_release(struct inode *inode, struct file *file) } /** - * notify_sys: + * wdt_notify_sys: * @this: our notifier block * @code: the event being reported * @unused: unused @@ -558,7 +558,7 @@ static struct notifier_block wdt_notifier = { }; /** - * cleanup_module: + * wdt_exit: * * Unload the watchdog. You cannot do this with any file handles open. * If your watchdog is set to continue ticking on close and you unload diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c index c3254ba5ace6..d5e56b601351 100644 --- a/drivers/watchdog/wdt_pci.c +++ b/drivers/watchdog/wdt_pci.c @@ -537,7 +537,7 @@ static int wdtpci_temp_release(struct inode *inode, struct file *file) } /** - * notify_sys: + * wdtpci_notify_sys: * @this: our notifier block * @code: the event being reported * @unused: unused diff --git a/drivers/watchdog/ziirave_wdt.c b/drivers/watchdog/ziirave_wdt.c index 4297280807ca..c5a9b820d43a 100644 --- a/drivers/watchdog/ziirave_wdt.c +++ b/drivers/watchdog/ziirave_wdt.c @@ -69,9 +69,6 @@ static char *ziirave_reasons[] = {"power cycle", "hw watchdog", NULL, NULL, #define ZIIRAVE_CMD_JUMP_TO_BOOTLOADER_MAGIC 1 #define ZIIRAVE_CMD_RESET_PROCESSOR_MAGIC 1 -#define ZIIRAVE_FW_VERSION_FMT "02.%02u.%02u" -#define ZIIRAVE_BL_VERSION_FMT "01.%02u.%02u" - struct ziirave_wdt_rev { unsigned char major; unsigned char minor; @@ -445,8 +442,9 @@ static ssize_t ziirave_wdt_sysfs_show_firm(struct device *dev, if (ret) return ret; - ret = sprintf(buf, ZIIRAVE_FW_VERSION_FMT, w_priv->firmware_rev.major, - w_priv->firmware_rev.minor); + ret = sysfs_emit(buf, "02.%02u.%02u\n", + w_priv->firmware_rev.major, + w_priv->firmware_rev.minor); mutex_unlock(&w_priv->sysfs_mutex); @@ -468,8 +466,9 @@ static ssize_t ziirave_wdt_sysfs_show_boot(struct device *dev, if (ret) return ret; - ret = sprintf(buf, ZIIRAVE_BL_VERSION_FMT, w_priv->bootloader_rev.major, - w_priv->bootloader_rev.minor); + ret = sysfs_emit(buf, "01.%02u.%02u\n", + w_priv->bootloader_rev.major, + w_priv->bootloader_rev.minor); mutex_unlock(&w_priv->sysfs_mutex); @@ -491,7 +490,7 @@ static ssize_t ziirave_wdt_sysfs_show_reason(struct device *dev, if (ret) return ret; - ret = sprintf(buf, "%s", ziirave_reasons[w_priv->reset_reason]); + ret = sysfs_emit(buf, "%s\n", ziirave_reasons[w_priv->reset_reason]); mutex_unlock(&w_priv->sysfs_mutex); @@ -536,7 +535,7 @@ static ssize_t ziirave_wdt_sysfs_store_firm(struct device *dev, } dev_info(&client->dev, - "Firmware updated to version " ZIIRAVE_FW_VERSION_FMT "\n", + "Firmware updated to version 02.%02u.%02u\n", w_priv->firmware_rev.major, w_priv->firmware_rev.minor); /* Restore the watchdog timeout */ @@ -677,7 +676,7 @@ static int ziirave_wdt_probe(struct i2c_client *client, } dev_info(&client->dev, - "Firmware version: " ZIIRAVE_FW_VERSION_FMT "\n", + "Firmware version: 02.%02u.%02u\n", w_priv->firmware_rev.major, w_priv->firmware_rev.minor); ret = ziirave_wdt_revision(client, &w_priv->bootloader_rev, @@ -688,7 +687,7 @@ static int ziirave_wdt_probe(struct i2c_client *client, } dev_info(&client->dev, - "Bootloader version: " ZIIRAVE_BL_VERSION_FMT "\n", + "Bootloader version: 01.%02u.%02u\n", w_priv->bootloader_rev.major, w_priv->bootloader_rev.minor); w_priv->reset_reason = i2c_smbus_read_byte_data(client, diff --git a/drivers/xen/pcpu.c b/drivers/xen/pcpu.c index 1bcdd5227771..47aa3a1ccaf5 100644 --- a/drivers/xen/pcpu.c +++ b/drivers/xen/pcpu.c @@ -92,7 +92,7 @@ static int xen_pcpu_up(uint32_t cpu_id) return HYPERVISOR_platform_op(&op); } -static ssize_t show_online(struct device *dev, +static ssize_t online_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -101,7 +101,7 @@ static ssize_t show_online(struct device *dev, return sprintf(buf, "%u\n", !!(cpu->flags & XEN_PCPU_FLAGS_ONLINE)); } -static ssize_t __ref store_online(struct device *dev, +static ssize_t __ref online_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -130,7 +130,7 @@ static ssize_t __ref store_online(struct device *dev, ret = count; return ret; } -static DEVICE_ATTR(online, S_IRUGO | S_IWUSR, show_online, store_online); +static DEVICE_ATTR_RW(online); static struct attribute *pcpu_dev_attrs[] = { &dev_attr_online.attr, diff --git a/drivers/xen/xen-balloon.c b/drivers/xen/xen-balloon.c index a8d24433c8e9..8cd583db20b1 100644 --- a/drivers/xen/xen-balloon.c +++ b/drivers/xen/xen-balloon.c @@ -134,13 +134,13 @@ void xen_balloon_init(void) EXPORT_SYMBOL_GPL(xen_balloon_init); #define BALLOON_SHOW(name, format, args...) \ - static ssize_t show_##name(struct device *dev, \ + static ssize_t name##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ return sprintf(buf, format, ##args); \ } \ - static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) + static DEVICE_ATTR_RO(name) BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages)); BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low)); @@ -152,16 +152,15 @@ static DEVICE_ULONG_ATTR(retry_count, 0444, balloon_stats.retry_count); static DEVICE_ULONG_ATTR(max_retry_count, 0644, balloon_stats.max_retry_count); static DEVICE_BOOL_ATTR(scrub_pages, 0644, xen_scrub_pages); -static ssize_t show_target_kb(struct device *dev, struct device_attribute *attr, +static ssize_t target_kb_show(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "%lu\n", PAGES2KB(balloon_stats.target_pages)); } -static ssize_t store_target_kb(struct device *dev, +static ssize_t target_kb_store(struct device *dev, struct device_attribute *attr, - const char *buf, - size_t count) + const char *buf, size_t count) { char *endchar; unsigned long long target_bytes; @@ -176,22 +175,19 @@ static ssize_t store_target_kb(struct device *dev, return count; } -static DEVICE_ATTR(target_kb, S_IRUGO | S_IWUSR, - show_target_kb, store_target_kb); +static DEVICE_ATTR_RW(target_kb); - -static ssize_t show_target(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t target_show(struct device *dev, struct device_attribute *attr, + char *buf) { return sprintf(buf, "%llu\n", (unsigned long long)balloon_stats.target_pages << PAGE_SHIFT); } -static ssize_t store_target(struct device *dev, +static ssize_t target_store(struct device *dev, struct device_attribute *attr, - const char *buf, - size_t count) + const char *buf, size_t count) { char *endchar; unsigned long long target_bytes; @@ -206,9 +202,7 @@ static ssize_t store_target(struct device *dev, return count; } -static DEVICE_ATTR(target, S_IRUGO | S_IWUSR, - show_target, store_target); - +static DEVICE_ATTR_RW(target); static struct attribute *balloon_attrs[] = { &dev_attr_target_kb.attr, diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index 97f0d234482d..33d09b3f6211 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -207,7 +207,7 @@ void xenbus_otherend_changed(struct xenbus_watch *watch, EXPORT_SYMBOL_GPL(xenbus_otherend_changed); #define XENBUS_SHOW_STAT(name) \ -static ssize_t show_##name(struct device *_dev, \ +static ssize_t name##_show(struct device *_dev, \ struct device_attribute *attr, \ char *buf) \ { \ @@ -215,14 +215,14 @@ static ssize_t show_##name(struct device *_dev, \ \ return sprintf(buf, "%d\n", atomic_read(&dev->name)); \ } \ -static DEVICE_ATTR(name, 0444, show_##name, NULL) +static DEVICE_ATTR_RO(name) XENBUS_SHOW_STAT(event_channels); XENBUS_SHOW_STAT(events); XENBUS_SHOW_STAT(spurious_events); XENBUS_SHOW_STAT(jiffies_eoi_delayed); -static ssize_t show_spurious_threshold(struct device *_dev, +static ssize_t spurious_threshold_show(struct device *_dev, struct device_attribute *attr, char *buf) { @@ -231,9 +231,9 @@ static ssize_t show_spurious_threshold(struct device *_dev, return sprintf(buf, "%d\n", dev->spurious_threshold); } -static ssize_t set_spurious_threshold(struct device *_dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t spurious_threshold_store(struct device *_dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct xenbus_device *dev = to_xenbus_device(_dev); unsigned int val; @@ -248,8 +248,7 @@ static ssize_t set_spurious_threshold(struct device *_dev, return count; } -static DEVICE_ATTR(spurious_threshold, 0644, show_spurious_threshold, - set_spurious_threshold); +static DEVICE_ATTR_RW(spurious_threshold); static struct attribute *xenbus_attrs[] = { &dev_attr_event_channels.attr, |