Re: [PATCH v2] vme: change LM callback argument to void pointer
On 29/04/16 22:41, Aaron Sierra wrote: Make the location monitor callback function prototype more useful by changing the argument from an integer to a void pointer. All VME bridge drivers were simply passing the location monitor index (e.g. 0-3) as the argument to these callbacks. It is much more useful to pass back a pointer to data that the callback-registering driver cares about. There appear to be no in-kernel callers of vme_lm_attach (or vme_lme_request for that matter), so this change only affects the VME subsystem and bridge drivers. This has been tested with Tsi148 hardware, but the CA91Cx42 changes have only been compiled. Signed-off-by: Aaron Sierra Sorry for the long delay - I've only just found time to write the test module I wanted to validate this. Acked-by: Martyn Welch --- v2 - change new argument name from cookie to data - add data cleanup to vme_tsi148.c - update VME API documentation with new prototype - fix checkpatch.pl style warning in vme_bridge.h Documentation/vme_api.txt | 4 ++-- drivers/vme/bridges/vme_ca91cx42.c | 6 -- drivers/vme/bridges/vme_ca91cx42.h | 3 ++- drivers/vme/bridges/vme_tsi148.c | 6 -- drivers/vme/bridges/vme_tsi148.h | 3 ++- drivers/vme/vme.c | 4 ++-- drivers/vme/vme_bridge.h | 3 ++- include/linux/vme.h| 2 +- 8 files changed, 19 insertions(+), 12 deletions(-) diff --git a/Documentation/vme_api.txt b/Documentation/vme_api.txt index ca5b827..4ca63a6 100644 --- a/Documentation/vme_api.txt +++ b/Documentation/vme_api.txt @@ -385,13 +385,13 @@ location monitor location. Each location monitor can monitor a number of adjacent locations: int vme_lm_attach(struct vme_resource *res, int num, - void (*callback)(int)); + void (*callback)(void *)); int vme_lm_detach(struct vme_resource *res, int num); The callback function is declared as follows. - void callback(int num); + void callback(void *data); Slot Detection diff --git a/drivers/vme/bridges/vme_ca91cx42.c b/drivers/vme/bridges/vme_ca91cx42.c index 5fbeab3..d6aab95 100644 --- a/drivers/vme/bridges/vme_ca91cx42.c +++ b/drivers/vme/bridges/vme_ca91cx42.c @@ -69,7 +69,7 @@ static u32 ca91cx42_LM_irqhandler(struct ca91cx42_driver *bridge, u32 stat) for (i = 0; i < 4; i++) { if (stat & CA91CX42_LINT_LM[i]) { /* We only enable interrupts if the callback is set */ - bridge->lm_callback[i](i); + bridge->lm_callback[i](bridge->lm_data[i]); serviced |= CA91CX42_LINT_LM[i]; } } @@ -1414,7 +1414,7 @@ static int ca91cx42_lm_get(struct vme_lm_resource *lm, * Callback will be passed the monitor triggered. */ static int ca91cx42_lm_attach(struct vme_lm_resource *lm, int monitor, - void (*callback)(int)) + void (*callback)(void *), void *data) { u32 lm_ctl, tmp; struct ca91cx42_driver *bridge; @@ -1442,6 +1442,7 @@ static int ca91cx42_lm_attach(struct vme_lm_resource *lm, int monitor, /* Attach callback */ bridge->lm_callback[monitor] = callback; + bridge->lm_data[monitor] = data; /* Enable Location Monitor interrupt */ tmp = ioread32(bridge->base + LINT_EN); @@ -1481,6 +1482,7 @@ static int ca91cx42_lm_detach(struct vme_lm_resource *lm, int monitor) /* Detach callback */ bridge->lm_callback[monitor] = NULL; + bridge->lm_data[monitor] = NULL; /* If all location monitors disabled, disable global Location Monitor */ if ((tmp & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 | diff --git a/drivers/vme/bridges/vme_ca91cx42.h b/drivers/vme/bridges/vme_ca91cx42.h index d54119e..f35c9f5 100644 --- a/drivers/vme/bridges/vme_ca91cx42.h +++ b/drivers/vme/bridges/vme_ca91cx42.h @@ -43,7 +43,8 @@ struct ca91cx42_driver { wait_queue_head_t dma_queue; wait_queue_head_t iack_queue; wait_queue_head_t mbox_queue; - void (*lm_callback[4])(int);/* Called in interrupt handler */ + void (*lm_callback[4])(void *); /* Called in interrupt handler */ + void *lm_data[4]; void *crcsr_kernel; dma_addr_t crcsr_bus; struct mutex vme_rmw; /* Only one RMW cycle at a time */ diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c index 6052483..5a96e9c 100644 --- a/drivers/vme/bridges/vme_tsi148.c +++ b/drivers/vme/bridges/vme_tsi148.c @@ -102,7 +102,7 @@ static u32 tsi148_LM_irqhandler(struct tsi148_driver *bridge, u32 stat) for (i = 0; i < 4; i++) { if (stat & TSI148_LCSR_INTS_LMS[i]) { /* We only enable interrupts if the callback is set */ - bridge->lm_callback[i](i); + bridge->lm_callback[i](bridge->lm_data[i]);
Re: [PATCH] vme: make core vme support explicitly non-modular
On 03/07/16 19:05, Paul Gortmaker wrote: The Kconfig currently controlling compilation of this code is: drivers/vme/Kconfig:menuconfig VME_BUS drivers/vme/Kconfig:bool "VME bridge support" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. We replace module.h and moduleparam.h (unused) with init.h and also export.h ; the latter since this file does export some syms. Since this is a struct bus_type and not a platform_driver, we don't have any ".suppress_bind_attrs" to be concerned about when we drop the ".remove" code from this file. Since module_init was not in use by this code, the init ordering remains unchanged with this commit. Cc: Martyn Welch Cc: Manohar Vanga Cc: Greg Kroah-Hartman Cc: de...@driverdev.osuosl.org Signed-off-by: Paul Gortmaker Acked-by: Martyn Welch --- drivers/vme/vme.c | 27 ++- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/drivers/vme/vme.c b/drivers/vme/vme.c index 37ac0a58e59a..557149f0f88a 100644 --- a/drivers/vme/vme.c +++ b/drivers/vme/vme.c @@ -13,8 +13,8 @@ * option) any later version. */ -#include -#include +#include +#include #include #include #include @@ -39,7 +39,6 @@ static unsigned int vme_bus_numbers; static LIST_HEAD(vme_bus_list); static DEFINE_MUTEX(vme_buses_lock); -static void __exit vme_exit(void); static int __init vme_init(void); static struct vme_dev *dev_to_vme_dev(struct device *dev) @@ -1622,25 +1621,10 @@ static int vme_bus_probe(struct device *dev) return retval; } -static int vme_bus_remove(struct device *dev) -{ - int retval = -ENODEV; - struct vme_driver *driver; - struct vme_dev *vdev = dev_to_vme_dev(dev); - - driver = dev->platform_data; - - if (driver->remove != NULL) - retval = driver->remove(vdev); - - return retval; -} - struct bus_type vme_bus_type = { .name = "vme", .match = vme_bus_match, .probe = vme_bus_probe, - .remove = vme_bus_remove, }; EXPORT_SYMBOL(vme_bus_type); @@ -1648,11 +1632,4 @@ static int __init vme_init(void) { return bus_register(&vme_bus_type); } - -static void __exit vme_exit(void) -{ - bus_unregister(&vme_bus_type); -} - subsys_initcall(vme_init); -module_exit(vme_exit); ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH v2 1/7] lib: string: add functions to case-convert strings
On Tue, Jul 05, 2016 at 01:47:05PM -0700, Markus Mayer wrote: > All functions return a pointer to the terminating '\0' character in the > modified string ("dst" or "s", respectively). I think this is going to be confusing. From the man: The strcpy() and strncpy() functions return a pointer to the destination string dest. I think it would be better to keep the same behaviour, especially since you used the same name for your functions (which I think is sensible), not to mention you don't use this return value in any of your calls. (IMHO strcpy() shouldn't have had a return value and neither should your functions, but since it does, yours should match.) Cheers, Eric ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH v14 net-next 1/1] hv_sock: introduce Hyper-V Sockets
On Thu, Jun 30, Dexuan Cui wrote: > +/* The MTU is 16KB per the host side's design. */ > +struct hvsock_recv_buf { > + unsigned int data_len; > + unsigned int data_offset; > + > + struct vmpipe_proto_header hdr; > + u8 buf[PAGE_SIZE * 4]; Please use some macro related to the protocol rather than a Linux compiletime macro. > +/* We send at most 4KB payload per VMBus packet. */ > +struct hvsock_send_buf { > + struct vmpipe_proto_header hdr; > + u8 buf[PAGE_SIZE]; Same here. > + * Copyright(c) 2016, Microsoft Corporation. All rights reserved. Here the BSD license follows. I think its required/desired to also include a GPL blurb like it is done in many other files: ... * Alternatively, this software may be distributed under the terms of * the GNU General Public License ("GPL") version 2 as published by the * Free Software Foundation. Otherwise the MODULE_LICENSE string might be incorrect. > + /* Hyper-V Sockets requires at least VMBus 4.0 */ > + if ((vmbus_proto_version >> 16) < 4) { > + pr_err("failed to load: VMBus 4 or later is required\n"); I guess this mens WS 2016+, and loading in earlier host versions will trigger this path? I think a silent ENODEV is enough. > + return -ENODEV; Olaf signature.asc Description: PGP signature ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH 1/1] vme: Fix module autoload
On 14/06/16 15:36, Alessio Igor Bogani wrote: These drivers have a PCI device ID table but the PCI module alias information is not created so module autoloading won't work. Signed-off-by: Alessio Igor Bogani Acked-by: Martyn Welch --- drivers/vme/bridges/vme_ca91cx42.c | 2 ++ drivers/vme/bridges/vme_tsi148.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/vme/bridges/vme_ca91cx42.c b/drivers/vme/bridges/vme_ca91cx42.c index 9f2c834..5d049f3 100644 --- a/drivers/vme/bridges/vme_ca91cx42.c +++ b/drivers/vme/bridges/vme_ca91cx42.c @@ -47,6 +47,8 @@ static const struct pci_device_id ca91cx42_ids[] = { { }, }; +MODULE_DEVICE_TABLE(pci, ca91cx42_ids); + static struct pci_driver ca91cx42_driver = { .name = driver_name, .id_table = ca91cx42_ids, diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c index 4bc5d45..6d159a3 100644 --- a/drivers/vme/bridges/vme_tsi148.c +++ b/drivers/vme/bridges/vme_tsi148.c @@ -50,6 +50,8 @@ static const struct pci_device_id tsi148_ids[] = { { }, }; +MODULE_DEVICE_TABLE(pci, tsi148_ids); + static struct pci_driver tsi148_driver = { .name = driver_name, .id_table = tsi148_ids, ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH v2] vme: Adding Fake VME driver
This patch introduces a fake VME bridge driver. This driver currently emulates a subset of the VME bridge functionality. This allows some VME subsystem development and even some VME device driver development to be carried out in the absence of a proper VME bus. Signed-off-by: Martyn Welch --- v2: - Resolved warnings highlighted by the kbuild test robot. - Corrected triggering of fake location monitor. drivers/vme/bridges/Kconfig|8 + drivers/vme/bridges/Makefile |1 + drivers/vme/bridges/vme_fake.c | 1299 3 files changed, 1308 insertions(+) create mode 100644 drivers/vme/bridges/vme_fake.c diff --git a/drivers/vme/bridges/Kconfig b/drivers/vme/bridges/Kconfig index f6d8545..f6ddc37 100644 --- a/drivers/vme/bridges/Kconfig +++ b/drivers/vme/bridges/Kconfig @@ -13,3 +13,11 @@ config VME_TSI148 help If you say Y here you get support for the Tundra TSI148 VME bridge chip. + +config VME_FAKE + tristate "Fake" + help +If you say Y here you get support for the fake VME bridge. This +provides a virtualised VME Bus for devices with no VME bridge. This +is mainly useful for VME development (in the absence of VME +hardware). diff --git a/drivers/vme/bridges/Makefile b/drivers/vme/bridges/Makefile index 59638af..b074542 100644 --- a/drivers/vme/bridges/Makefile +++ b/drivers/vme/bridges/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_VME_CA91CX42) += vme_ca91cx42.o obj-$(CONFIG_VME_TSI148) += vme_tsi148.o +obj-$(CONFIG_VME_FAKE) += vme_fake.o diff --git a/drivers/vme/bridges/vme_fake.c b/drivers/vme/bridges/vme_fake.c new file mode 100644 index 000..7ef298b --- /dev/null +++ b/drivers/vme/bridges/vme_fake.c @@ -0,0 +1,1299 @@ +/* + * Fake VME bridge support. + * + * This drive provides a fake VME bridge chip, this enables debugging of the + * VME framework in the absence of a VME system. + * + * This driver has to do a number of things in software that would be driven + * by hardware if it was available, it will also result in extra overhead at + * times when compared with driving actual hardware. + * + * Author: Martyn Welch + * Copyright (c) 2014 Martyn Welch + * + * Based on vme_tsi148.c: + * + * Author: Martyn Welch + * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. + * + * Based on work by Tom Armistead and Ajit Prem + * Copyright 2004 Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../vme_bridge.h" + +/* + * Define the number of each that the fake driver supports. + */ +#define FAKE_MAX_MASTER8 /* Max Master Windows */ +#define FAKE_MAX_SLAVE 8 /* Max Slave Windows */ + +/* Structures to hold information normally held in device registers */ +struct fake_slave_window { + int enabled; + unsigned long long vme_base; + unsigned long long size; + dma_addr_t buf_base; + u32 aspace; + u32 cycle; +}; + +struct fake_master_window { + int enabled; + unsigned long long vme_base; + unsigned long long size; + u32 aspace; + u32 cycle; + u32 dwidth; +}; + +/* Structure used to hold driver specific information */ +struct fake_driver { + struct vme_bridge *parent; + struct fake_slave_window slaves[FAKE_MAX_SLAVE]; + struct fake_master_window masters[FAKE_MAX_MASTER]; + u32 lm_enabled; + unsigned long long lm_base; + u32 lm_aspace; + u32 lm_cycle; + void (*lm_callback[4])(void *); + void *lm_data[4]; + struct tasklet_struct int_tasklet; + int int_level; + int int_statid; + void *crcsr_kernel; + dma_addr_t crcsr_bus; + /* Only one VME interrupt can be generated at a time, provide locking */ + struct mutex vme_int; +}; + +/* Module parameter */ +static int geoid; + +static const char driver_name[] = "vme_fake"; + +static struct vme_bridge *exit_pointer; + +static struct device *vme_root; + +/* + * Calling VME bus interrupt callback if provided. + */ +static void fake_VIRQ_tasklet(unsigned long data) +{ + struct vme_bridge *fake_bridge; + struct fake_driver *bridge; + + fake_bridge = (struct vme_bridge *) data; + bridge = fake_bridge->driver_priv; + + vme_irq_handler(fake_bridge, bridge->int_level, bridge->int_statid); +} + +/* + * Configure VME interrupt + */ +static void fake_irq_set(struct vme_bridge *fake_bridge, int level, + int state, int sync) +{ + /* Nothing to do */ +} + +/* + * Generate a VME bus interrupt at the requested level & vector. Wait for + * interrupt t
Re: [PATCH 0/7] de-stage SW_SYNC validation frawework
Hi Greg, Any comment on this? Thanks, Gustavo 2016-06-20 Gustavo Padovan : > From: Gustavo Padovan > > Hi Greg, > > This is the last step in the Sync Framwork de-stage task. It de-stage > the SW_SYNC validation framework and the sync_debug info debugfs file. > > The first 3 patches are clean up and improvements and the rest is preparation > to de-stage and then finally the actual de-stage. > > Please review, > > Gustavo > > --- > Gustavo Padovan (7): > staging/android: move trace/sync.h to sync_trace.h > staging/android: remove doc from sw_sync > staging/android: display sync_pt name on debugfs > staging/android: do not let userspace trigger WARN_ON > staging/android: prepare sw_sync files for de-staging > dma-buf/sw_sync: de-stage SW_SYNC > staging/android: remove sync framework TODO > > drivers/dma-buf/Kconfig| 14 +++ > drivers/dma-buf/Makefile | 1 + > drivers/{staging/android => dma-buf}/sw_sync.c | 46 > +++--- > drivers/{staging/android => dma-buf}/sync_debug.c | 7 ++-- > drivers/{staging/android => dma-buf}/sync_debug.h | 26 +--- > .../android/trace/sync.h => dma-buf/sync_trace.h} | 6 +-- > drivers/staging/android/Kconfig| 13 -- > drivers/staging/android/Makefile | 1 - > drivers/staging/android/TODO | 8 > 9 files changed, 38 insertions(+), 84 deletions(-) > rename drivers/{staging/android => dma-buf}/sw_sync.c (84%) > rename drivers/{staging/android => dma-buf}/sync_debug.c (97%) > rename drivers/{staging/android => dma-buf}/sync_debug.h (72%) > rename drivers/{staging/android/trace/sync.h => dma-buf/sync_trace.h} (84%) > > -- > 2.5.5 > ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH v2] vme: Adding Fake VME driver
Hi, [auto build test ERROR on driver-core/driver-core-testing] [also build test ERROR on v4.7-rc6 next-20160707] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Martyn-Welch/vme-Adding-Fake-VME-driver/20160708-025909 config: i386-allmodconfig (attached as .config) compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430 reproduce: # save the attached .config to linux build tree make ARCH=i386 All errors (new ones prefixed by >>): drivers/vme/bridges/vme_fake.c: In function 'fake_init': >> drivers/vme/bridges/vme_fake.c:1174:25: error: assignment from incompatible >> pointer type [-Werror=incompatible-pointer-types] fake_bridge->lm_attach = fake_lm_attach; ^ cc1: some warnings being treated as errors vim +1174 drivers/vme/bridges/vme_fake.c 1168 fake_bridge->master_write = fake_master_write; 1169 fake_bridge->master_rmw = fake_master_rmw; 1170 fake_bridge->irq_set = fake_irq_set; 1171 fake_bridge->irq_generate = fake_irq_generate; 1172 fake_bridge->lm_set = fake_lm_set; 1173 fake_bridge->lm_get = fake_lm_get; > 1174 fake_bridge->lm_attach = fake_lm_attach; 1175 fake_bridge->lm_detach = fake_lm_detach; 1176 fake_bridge->slot_get = fake_slot_get; 1177 fake_bridge->alloc_consistent = fake_alloc_consistent; --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation .config.gz Description: Binary data ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH v2] vme: Adding Fake VME driver
Ah, yeah, this patch depends on Aaron Sierra's "[PATCH v2] vme: change LM callback argument to void pointer" patch: http://permalink.gmane.org/gmane.linux.drivers.driver-project.devel/87990 Which changes the parameters for fake_lm_attach() Martyn On 07/07/16 20:59, kbuild test robot wrote: Hi, [auto build test ERROR on driver-core/driver-core-testing] [also build test ERROR on v4.7-rc6 next-20160707] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Martyn-Welch/vme-Adding-Fake-VME-driver/20160708-025909 config: i386-allmodconfig (attached as .config) compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430 reproduce: # save the attached .config to linux build tree make ARCH=i386 All errors (new ones prefixed by >>): drivers/vme/bridges/vme_fake.c: In function 'fake_init': drivers/vme/bridges/vme_fake.c:1174:25: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types] fake_bridge->lm_attach = fake_lm_attach; ^ cc1: some warnings being treated as errors vim +1174 drivers/vme/bridges/vme_fake.c 1168 fake_bridge->master_write = fake_master_write; 1169 fake_bridge->master_rmw = fake_master_rmw; 1170 fake_bridge->irq_set = fake_irq_set; 1171 fake_bridge->irq_generate = fake_irq_generate; 1172 fake_bridge->lm_set = fake_lm_set; 1173 fake_bridge->lm_get = fake_lm_get; 1174fake_bridge->lm_attach = fake_lm_attach; 1175 fake_bridge->lm_detach = fake_lm_detach; 1176 fake_bridge->slot_get = fake_slot_get; 1177 fake_bridge->alloc_consistent = fake_alloc_consistent; --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
销售人员要具备独立判断的能力
销售人员要具备独立判断的能力�w馨瑜 20160708065259 将销#售管理融入培训现场.xls Description: Binary data ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH v2 1/7] lib: string: add functions to case-convert strings
On Tue, Jul 05 2016, Markus Mayer wrote: > Add a collection of generic functions to convert strings to lowercase > or uppercase. > > Changing the case of a string (with or without copying it first) seems > to be a recurring requirement in the kernel that is currently being > solved by several duplicated implementations doing the same thing. This > change aims at reducing this code duplication. > > +/** > + * strncpytoupper - Copy a length-limited string and convert to uppercase. > + * @dst: The buffer to store the result. > + * @src: The string to convert to uppercase. > + * @len: Maximum string length. May be 0 to set no limit. > + * > + * Returns pointer to terminating '\0' in @dst. > + */ > +char *strncpytoupper(char *dst, const char *src, size_t len) > +{ > + size_t i; > + > + for (i = 0; src[i] != '\0' && (i < len || !len); i++) > + dst[i] = toupper(src[i]); > + if (i < len || !len) > + dst[i] = '\0'; > + > + return dst + i; > +} Hm, this seems to copy the insane semantics from strncpy of not guaranteeing '\0'-termination. Why use 0 as a sentinel, when (size_t)-1 == SIZE_MAX would work just as well and require a little less code (no || !len)? I regret suggesting this return semantics and now agree that void would be better, especially since there doesn't seem to be anyone who can use this (or any other) return value. How about if (!len) return; for (i = 0; i < len && src[i]; ++i) dst[i] = toupper(src[i]); dst[i < len ? i : i-1] = '\0'; (I think you must do i < len before testing src[i], since the len parameter should be an upper bound on the number of bytes to access in both src and dst). Rasmus ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel